Merge branches 'timers/clockevents', 'timers/hpet', 'timers/hrtimers' and 'timers...
authorIngo Molnar <mingo@elte.hu>
Sun, 8 Feb 2009 19:14:11 +0000 (20:14 +0100)
committerIngo Molnar <mingo@elte.hu>
Sun, 8 Feb 2009 19:14:11 +0000 (20:14 +0100)
283 files changed:
.mailmap
Documentation/filesystems/ubifs.txt
MAINTAINERS
arch/alpha/include/asm/bug.h
arch/arm/kernel/entry-armv.S
arch/arm/kernel/entry-common.S
arch/arm/kernel/irq.c
arch/arm/mach-msm/board-halibut.c
arch/arm/mach-omap1/devices.c
arch/arm/mach-omap1/mcbsp.c
arch/arm/mach-omap2/devices.c
arch/arm/mach-omap2/id.c
arch/arm/mach-omap2/irq.c
arch/arm/mach-omap2/mcbsp.c
arch/arm/mach-omap2/sleep24xx.S
arch/arm/mach-omap2/timer-gp.c
arch/arm/mach-sa1100/generic.c
arch/arm/mm/fault-armv.c
arch/arm/plat-omap/devices.c
arch/arm/plat-omap/dma.c
arch/arm/plat-omap/include/mach/cpu.h
arch/arm/plat-omap/include/mach/mcbsp.h
arch/arm/plat-omap/include/mach/mmc.h
arch/arm/plat-omap/mcbsp.c
arch/blackfin/Kconfig
arch/blackfin/Makefile
arch/blackfin/configs/BF518F-EZBRD_defconfig
arch/blackfin/configs/BF526-EZBRD_defconfig
arch/blackfin/configs/BF527-EZKIT_defconfig
arch/blackfin/configs/BF533-EZKIT_defconfig
arch/blackfin/configs/BF533-STAMP_defconfig
arch/blackfin/configs/BF537-STAMP_defconfig
arch/blackfin/configs/BF538-EZKIT_defconfig
arch/blackfin/configs/BF548-EZKIT_defconfig
arch/blackfin/configs/BF561-EZKIT_defconfig
arch/blackfin/configs/CM-BF527_defconfig
arch/blackfin/include/asm/checksum.h
arch/blackfin/include/asm/delay.h
arch/blackfin/include/asm/gpio.h
arch/blackfin/include/asm/kgdb.h
arch/blackfin/include/asm/mem_init.h
arch/blackfin/include/asm/pda.h
arch/blackfin/include/asm/reboot.h
arch/blackfin/kernel/Makefile
arch/blackfin/kernel/bfin_dma_5xx.c
arch/blackfin/kernel/bfin_gpio.c
arch/blackfin/kernel/cplb-mpu/cplbinit.c
arch/blackfin/kernel/cplb-nompu/cplbmgr.c
arch/blackfin/kernel/irqchip.c
arch/blackfin/kernel/reboot.c
arch/blackfin/kernel/setup.c
arch/blackfin/kernel/traps.c
arch/blackfin/mach-bf518/boards/ezbrd.c
arch/blackfin/mach-bf518/include/mach/portmux.h
arch/blackfin/mach-bf527/boards/cm_bf527.c
arch/blackfin/mach-bf527/boards/ezbrd.c
arch/blackfin/mach-bf527/boards/ezkit.c
arch/blackfin/mach-bf527/include/mach/portmux.h
arch/blackfin/mach-bf533/boards/blackstamp.c
arch/blackfin/mach-bf533/boards/stamp.c
arch/blackfin/mach-bf533/include/mach/portmux.h
arch/blackfin/mach-bf537/boards/cm_bf537.c
arch/blackfin/mach-bf537/boards/generic_board.c
arch/blackfin/mach-bf537/boards/minotaur.c
arch/blackfin/mach-bf537/boards/pnav10.c
arch/blackfin/mach-bf537/boards/stamp.c
arch/blackfin/mach-bf537/boards/tcm_bf537.c
arch/blackfin/mach-bf537/include/mach/portmux.h
arch/blackfin/mach-bf538/include/mach/portmux.h
arch/blackfin/mach-bf548/boards/ezkit.c
arch/blackfin/mach-bf548/include/mach/anomaly.h
arch/blackfin/mach-bf548/include/mach/bf548.h
arch/blackfin/mach-bf548/include/mach/gpio.h
arch/blackfin/mach-bf548/include/mach/portmux.h
arch/blackfin/mach-bf561/include/mach/defBF561.h
arch/blackfin/mach-bf561/include/mach/portmux.h
arch/blackfin/mach-common/clocks-init.c
arch/blackfin/mach-common/entry.S
arch/blackfin/mach-common/head.S
arch/blackfin/mach-common/interrupt.S
arch/blackfin/mach-common/ints-priority.c
arch/blackfin/mach-common/pm.c
arch/sh/boards/board-ap325rxa.c
arch/sh/configs/ap325rxa_defconfig
arch/sh/configs/migor_defconfig
arch/sh/include/asm/mutex-llsc.h
arch/sh/include/asm/syscall_32.h
arch/sh/include/asm/syscall_64.h
arch/sh/kernel/cpu/sh4/fpu.c
arch/sh/kernel/setup.c
arch/sh/kernel/signal_32.c
arch/sh/kernel/signal_64.c
arch/sh/lib/checksum.S
arch/sparc/include/asm/cpudata_64.h
arch/sparc/include/asm/irq_64.h
arch/sparc/include/asm/kdebug_64.h
arch/sparc/include/asm/nmi.h [new file with mode: 0644]
arch/sparc/include/asm/pcr.h [new file with mode: 0644]
arch/sparc/include/asm/pil.h
arch/sparc/kernel/Makefile
arch/sparc/kernel/cpu.c
arch/sparc/kernel/irq_64.c
arch/sparc/kernel/kernel.h
arch/sparc/kernel/nmi.c [new file with mode: 0644]
arch/sparc/kernel/pcr.c [new file with mode: 0644]
arch/sparc/kernel/process_64.c
arch/sparc/kernel/setup_64.c
arch/sparc/kernel/ttable.S
arch/sparc/mm/fault_64.c
arch/sparc/oprofile/init.c
arch/x86/ia32/ia32entry.S
arch/x86/kernel/apic.c
arch/x86/kernel/cpu/intel_cacheinfo.c
arch/x86/kernel/entry_64.S
arch/x86/kernel/io_apic.c
arch/x86/kernel/irqinit_32.c
arch/x86/kernel/quirks.c
arch/x86/mach-default/setup.c
arch/x86/mach-voyager/setup.c
arch/x86/mach-voyager/voyager_smp.c
arch/x86/mm/fault.c
arch/x86/xen/multicalls.h
drivers/ata/ahci.c
drivers/ata/libata-core.c
drivers/ata/libata-eh.c
drivers/ata/libata-pmp.c
drivers/ata/libata-scsi.c
drivers/ata/libata.h
drivers/ata/pata_qdi.c
drivers/ata/sata_mv.c
drivers/ata/sata_nv.c
drivers/ata/sata_sil.c
drivers/char/Kconfig
drivers/char/sx.c
drivers/dca/dca-core.c
drivers/firewire/fw-card.c
drivers/hwmon/hp_accel.c
drivers/ide/qd65xx.c
drivers/ide/qd65xx.h
drivers/ieee1394/dv1394.c
drivers/md/linear.c
drivers/md/md.c
drivers/md/raid1.c
drivers/mfd/pcf50633-core.c
drivers/misc/Kconfig
drivers/misc/atmel-ssc.c
drivers/misc/hpilo.c
drivers/misc/hpilo.h
drivers/misc/sgi-xp/xpc.h
drivers/misc/sgi-xp/xpc_uv.c
drivers/misc/sgi-xp/xpnet.c
drivers/mtd/maps/sa1100-flash.c
drivers/net/arm/etherh.c
drivers/net/cassini.c
drivers/net/cxgb3/sge.c
drivers/net/e1000/e1000_main.c
drivers/net/gianfar.c
drivers/net/gianfar.h
drivers/net/ibm_newemac/phy.c
drivers/net/pcmcia/pcnet_cs.c
drivers/net/qlge/qlge.h
drivers/net/qlge/qlge_main.c
drivers/net/smc911x.c
drivers/net/smsc9420.c
drivers/net/sungem.c
drivers/net/sungem_phy.c
drivers/net/sunqe.c
drivers/net/tsi108_eth.c
drivers/net/tulip/de2104x.c
drivers/net/usb/hso.c
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl-sta.c
drivers/net/wireless/iwlwifi/iwl3945-base.c
drivers/platform/x86/hp-wmi.c
drivers/rtc/Kconfig
drivers/rtc/Makefile
drivers/rtc/rtc-dm355evm.c [new file with mode: 0644]
drivers/rtc/rtc-ds1390.c
drivers/video/aty/aty128fb.c
drivers/video/aty/atyfb_base.c
drivers/video/aty/radeon_base.c
drivers/video/aty/radeon_pm.c
drivers/video/backlight/Makefile
drivers/video/backlight/da903x.c [deleted file]
drivers/video/backlight/da903x_bl.c [new file with mode: 0644]
drivers/video/fbcmap.c
drivers/video/fbmem.c
fs/binfmt_elf.c
fs/btrfs/Kconfig
fs/btrfs/async-thread.c
fs/btrfs/compression.c
fs/btrfs/ctree.c
fs/btrfs/ctree.h
fs/btrfs/disk-io.c
fs/btrfs/disk-io.h
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/extent_io.h
fs/btrfs/extent_map.c
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/locking.c
fs/btrfs/locking.h
fs/btrfs/ordered-data.c
fs/btrfs/ref-cache.c
fs/btrfs/ref-cache.h
fs/btrfs/super.c
fs/btrfs/transaction.c
fs/btrfs/tree-defrag.c
fs/btrfs/tree-log.c
fs/btrfs/volumes.c
fs/btrfs/xattr.c
fs/btrfs/xattr.h
fs/buffer.c
fs/compat_ioctl.c
fs/ecryptfs/crypto.c
fs/ocfs2/alloc.c
fs/ocfs2/dcache.c
fs/ocfs2/dcache.h
fs/ocfs2/dlmglue.c
fs/ocfs2/ocfs2.h
fs/ocfs2/quota_global.c
fs/ocfs2/super.c
fs/ocfs2/xattr.c
fs/seq_file.c
fs/ubifs/budget.c
fs/ubifs/debug.c
fs/ubifs/debug.h
fs/ubifs/dir.c
fs/ubifs/file.c
fs/ubifs/gc.c
fs/ubifs/io.c
fs/ubifs/journal.c
fs/ubifs/lprops.c
fs/ubifs/lpt_commit.c
fs/ubifs/master.c
fs/ubifs/orphan.c
fs/ubifs/super.c
fs/ubifs/tnc.c
fs/ubifs/ubifs.h
fs/xfs/linux-2.6/xfs_sync.c
fs/xfs/xfs_dfrag.c
fs/xfs/xfs_log_recover.c
include/linux/Kbuild
include/linux/ata.h
include/linux/fb.h
include/linux/if_tunnel.h
include/linux/kernel.h
include/linux/libata.h
include/linux/wait.h
include/video/aty128.h
include/video/mach64.h
include/video/radeon.h
ipc/shm.c
kernel/async.c
kernel/fork.c
kernel/irq/numa_migrate.c
kernel/sched.c
kernel/sys.c
kernel/time/clockevents.c
kernel/trace/ftrace.c
kernel/wait.c
mm/memory.c
mm/page-writeback.c
net/ipv4/tcp_output.c
net/ipv4/udp.c
net/ipv6/ip6_output.c
net/packet/af_packet.c
net/sunrpc/Kconfig
sound/core/oss/pcm_oss.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_proc.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/intel8x0.c
sound/soc/atmel/atmel_ssc_dai.c
sound/soc/atmel/atmel_ssc_dai.h
sound/soc/codecs/wm8350.c
sound/soc/codecs/wm8990.c
sound/soc/omap/omap-pcm.c
sound/usb/usbaudio.c

index 4e83e7b..a62e6a8 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -92,6 +92,7 @@ Rudolf Marek <R.Marek@sh.cvut.cz>
 Rui Saraiva <rmps@joel.ist.utl.pt>
 Sachin P Sant <ssant@in.ibm.com>
 Sam Ravnborg <sam@mars.ravnborg.org>
+Sascha Hauer <s.hauer@pengutronix.de>
 S.ÇaÄŸlar Onur <caglar@pardus.org.tr>
 Simon Kelley <simon@thekelleys.org.uk>
 Stéphane Witzmann <stephane.witzmann@ubpmes.univ-bpclermont.fr>
@@ -100,6 +101,7 @@ Tejun Heo <htejun@gmail.com>
 Thomas Graf <tgraf@suug.ch>
 Tony Luck <tony.luck@intel.com>
 Tsuneo Yoshioka <Tsuneo.Yoshioka@f-secure.com>
-Uwe Kleine-König <Uwe.Kleine-Koenig@digi.com>
 Uwe Kleine-König <ukleinek@informatik.uni-freiburg.de>
+Uwe Kleine-König <ukl@pengutronix.de>
+Uwe Kleine-König <Uwe.Kleine-Koenig@digi.com>
 Valdis Kletnieks <Valdis.Kletnieks@vt.edu>
index 84da2a4..12fedb7 100644 (file)
@@ -79,13 +79,6 @@ Mount options
 
 (*) == default.
 
-norm_unmount (*)       commit on unmount; the journal is committed
-                       when the file-system is unmounted so that the
-                       next mount does not have to replay the journal
-                       and it becomes very fast;
-fast_unmount           do not commit on unmount; this option makes
-                       unmount faster, but the next mount slower
-                       because of the need to replay the journal.
 bulk_read              read more in one go to take advantage of flash
                        media that read faster sequentially
 no_bulk_read (*)       do not bulk-read
index 474ec0c..0ea3a6d 100644 (file)
@@ -911,7 +911,7 @@ S:  Maintained
 BLACKFIN ARCHITECTURE
 P:     Bryan Wu
 M:     cooloney@kernel.org
-L:     uclinux-dist-devel@blackfin.uclinux.org (subscribers-only)
+L:     uclinux-dist-devel@blackfin.uclinux.org
 W:     http://blackfin.uclinux.org
 S:     Supported
 
@@ -1021,6 +1021,14 @@ M:       mb@bu3sch.de
 W:     http://bu3sch.de/btgpio.php
 S:     Maintained
 
+BTRFS FILE SYSTEM
+P:     Chris Mason
+M:     chris.mason@oracle.com
+L:     linux-btrfs@vger.kernel.org
+W:     http://btrfs.wiki.kernel.org/
+T:     git kernel.org:/pub/scm/linux/kernel/git/mason/btrfs-unstable.git
+S:     Maintained
+
 BTTV VIDEO4LINUX DRIVER
 P:     Mauro Carvalho Chehab
 M:     mchehab@infradead.org
@@ -2212,7 +2220,7 @@ P:        Sean Hefty
 M:     sean.hefty@intel.com
 P:     Hal Rosenstock
 M:     hal.rosenstock@gmail.com
-L:     general@lists.openfabrics.org
+L:     general@lists.openfabrics.org (moderated for non-subscribers)
 W:     http://www.openib.org/
 T:     git kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git
 S:     Supported
@@ -4841,6 +4849,7 @@ P:        Ingo Molnar
 M:     mingo@redhat.com
 P:     H. Peter Anvin
 M:     hpa@zytor.com
+M:     x86@kernel.org
 L:     linux-kernel@vger.kernel.org
 T:     git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86.git
 S:     Maintained
index 7b85b7c..1720c8a 100644 (file)
@@ -8,12 +8,12 @@
 
 /* ??? Would be nice to use .gprel32 here, but we can't be sure that the
    function loaded the GP, so this could fail in modules.  */
-#define BUG()  {                                                       \
+#define BUG()  do {                                                    \
        __asm__ __volatile__(                                           \
                "call_pal %0  # bugchk\n\t"                             \
                ".long %1\n\t.8byte %2"                                 \
                : : "i"(PAL_bugchk), "i"(__LINE__), "i"(__FILE__));     \
-       for ( ; ; ); }
+       for ( ; ; ); } while (0)
 
 #define HAVE_ARCH_BUG
 #endif
index 77b0474..85040cf 100644 (file)
@@ -650,6 +650,7 @@ ENTRY(fp_enter)
 no_fp: mov     pc, lr
 
 __und_usr_unknown:
+       enable_irq
        mov     r0, sp
        adr     lr, ret_from_exception
        b       do_undefinstr
index 06269ea..49a6ba9 100644 (file)
@@ -136,7 +136,7 @@ ENTRY(mcount)
        ldmia sp!, {r0-r3, pc}
 
 trace:
-       ldr r1, [fp, #-4]
+       ldr r1, [fp, #-4]                       @ lr of instrumented routine
        mov r0, lr
        sub r0, r0, #MCOUNT_INSN_SIZE
        mov lr, pc
index 7141cee..363db18 100644 (file)
@@ -101,7 +101,7 @@ unlock:
 /* Handle bad interrupts */
 static struct irq_desc bad_irq_desc = {
        .handle_irq = handle_bad_irq,
-       .lock = SPIN_LOCK_UNLOCKED
+       .lock = __SPIN_LOCK_UNLOCKED(bad_irq_desc.lock),
 };
 
 /*
index c2a96e3..e61967d 100644 (file)
@@ -27,6 +27,7 @@
 #include <asm/mach/map.h>
 #include <asm/mach/flash.h>
 
+#include <mach/irqs.h>
 #include <mach/board.h>
 #include <mach/msm_iomap.h>
 
index 77382d8..ba5d7c0 100644 (file)
@@ -181,7 +181,7 @@ void __init omap1_init_mmc(struct omap_mmc_platform_data **mmc_data,
                }
                size = OMAP1_MMC_SIZE;
 
-               omap_mmc_add(i, base, size, irq, mmc_data[i]);
+               omap_mmc_add("mmci-omap", i, base, size, irq, mmc_data[i]);
        };
 }
 
index ca7a0cc..575ba31 100644 (file)
 #define DPS_RSTCT2_PER_EN      (1 << 0)
 #define DSP_RSTCT2_WD_PER_EN   (1 << 1)
 
-struct mcbsp_internal_clk {
-       struct clk clk;
-       struct clk **childs;
-       int n_childs;
-};
-
 #if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)
-static void omap_mcbsp_clk_init(struct mcbsp_internal_clk *mclk)
-{
-       const char *clk_names[] = { "dsp_ck", "api_ck", "dspxor_ck" };
-       int i;
-
-       mclk->n_childs = ARRAY_SIZE(clk_names);
-       mclk->childs = kzalloc(mclk->n_childs * sizeof(struct clk *),
-                               GFP_KERNEL);
-
-       for (i = 0; i < mclk->n_childs; i++) {
-               /* We fake a platform device to get correct device id */
-               struct platform_device pdev;
-
-               pdev.dev.bus = &platform_bus_type;
-               pdev.id = mclk->clk.id;
-               mclk->childs[i] = clk_get(&pdev.dev, clk_names[i]);
-               if (IS_ERR(mclk->childs[i]))
-                       printk(KERN_ERR "Could not get clock %s (%d).\n",
-                               clk_names[i], mclk->clk.id);
-       }
-}
-
-static int omap_mcbsp_clk_enable(struct clk *clk)
-{
-       struct mcbsp_internal_clk *mclk = container_of(clk,
-                                       struct mcbsp_internal_clk, clk);
-       int i;
-
-       for (i = 0; i < mclk->n_childs; i++)
-               clk_enable(mclk->childs[i]);
-       return 0;
-}
-
-static void omap_mcbsp_clk_disable(struct clk *clk)
-{
-       struct mcbsp_internal_clk *mclk = container_of(clk,
-                                       struct mcbsp_internal_clk, clk);
-       int i;
-
-       for (i = 0; i < mclk->n_childs; i++)
-               clk_disable(mclk->childs[i]);
-}
-
-static struct mcbsp_internal_clk omap_mcbsp_clks[] = {
-       {
-               .clk = {
-                       .name           = "mcbsp_clk",
-                       .id             = 1,
-                       .enable         = omap_mcbsp_clk_enable,
-                       .disable        = omap_mcbsp_clk_disable,
-               },
-       },
-       {
-               .clk = {
-                       .name           = "mcbsp_clk",
-                       .id             = 3,
-                       .enable         = omap_mcbsp_clk_enable,
-                       .disable        = omap_mcbsp_clk_disable,
-               },
-       },
-};
-
-#define omap_mcbsp_clks_size   ARRAY_SIZE(omap_mcbsp_clks)
-#else
-#define omap_mcbsp_clks_size   0
-static struct mcbsp_internal_clk __initdata *omap_mcbsp_clks;
-static inline void omap_mcbsp_clk_init(struct mcbsp_internal_clk *mclk)
-{ }
+const char *clk_names[] = { "dsp_ck", "api_ck", "dspxor_ck" };
 #endif
 
 static void omap1_mcbsp_request(unsigned int id)
@@ -167,8 +94,9 @@ static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
                .rx_irq         = INT_McBSP1RX,
                .tx_irq         = INT_McBSP1TX,
                .ops            = &omap1_mcbsp_ops,
-               .clk_name       = "mcbsp_clk",
-               },
+               .clk_names      = clk_names,
+               .num_clks       = 3,
+       },
        {
                .phys_base      = OMAP1510_MCBSP2_BASE,
                .dma_rx_sync    = OMAP_DMA_MCBSP2_RX,
@@ -184,7 +112,8 @@ static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
                .rx_irq         = INT_McBSP3RX,
                .tx_irq         = INT_McBSP3TX,
                .ops            = &omap1_mcbsp_ops,
-               .clk_name       = "mcbsp_clk",
+               .clk_names      = clk_names,
+               .num_clks       = 3,
        },
 };
 #define OMAP15XX_MCBSP_PDATA_SZ                ARRAY_SIZE(omap15xx_mcbsp_pdata)
@@ -202,7 +131,8 @@ static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
                .rx_irq         = INT_McBSP1RX,
                .tx_irq         = INT_McBSP1TX,
                .ops            = &omap1_mcbsp_ops,
-               .clk_name       = "mcbsp_clk",
+               .clk_names      = clk_names,
+               .num_clks       = 3,
        },
        {
                .phys_base      = OMAP1610_MCBSP2_BASE,
@@ -219,7 +149,8 @@ static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
                .rx_irq         = INT_McBSP3RX,
                .tx_irq         = INT_McBSP3TX,
                .ops            = &omap1_mcbsp_ops,
-               .clk_name       = "mcbsp_clk",
+               .clk_names      = clk_names,
+               .num_clks       = 3,
        },
 };
 #define OMAP16XX_MCBSP_PDATA_SZ                ARRAY_SIZE(omap16xx_mcbsp_pdata)
@@ -230,15 +161,6 @@ static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
 
 int __init omap1_mcbsp_init(void)
 {
-       int i;
-
-       for (i = 0; i < omap_mcbsp_clks_size; i++) {
-               if (cpu_is_omap15xx() || cpu_is_omap16xx()) {
-                       omap_mcbsp_clk_init(&omap_mcbsp_clks[i]);
-                       clk_register(&omap_mcbsp_clks[i].clk);
-               }
-       }
-
        if (cpu_is_omap730())
                omap_mcbsp_count = OMAP730_MCBSP_PDATA_SZ;
        if (cpu_is_omap15xx())
index 9d7216f..ce03fa7 100644 (file)
@@ -421,6 +421,7 @@ void __init omap2_init_mmc(struct omap_mmc_platform_data **mmc_data,
                        int nr_controllers)
 {
        int i;
+       char *name;
 
        for (i = 0; i < nr_controllers; i++) {
                unsigned long base, size;
@@ -450,12 +451,14 @@ void __init omap2_init_mmc(struct omap_mmc_platform_data **mmc_data,
                        continue;
                }
 
-               if (cpu_is_omap2420())
+               if (cpu_is_omap2420()) {
                        size = OMAP2420_MMC_SIZE;
-               else
+                       name = "mmci-omap";
+               } else {
                        size = HSMMC_SIZE;
-
-               omap_mmc_add(i, base, size, irq, mmc_data[i]);
+                       name = "mmci-omap-hs";
+               }
+               omap_mmc_add(name, i, base, size, irq, mmc_data[i]);
        };
 }
 
index b0f8e7d..b52a02f 100644 (file)
@@ -172,9 +172,13 @@ void __init omap34xx_check_revision(void)
                        omap_revision = OMAP3430_REV_ES3_0;
                        rev_name = "ES3.0";
                        break;
+               case 4:
+                       omap_revision = OMAP3430_REV_ES3_1;
+                       rev_name = "ES3.1";
+                       break;
                default:
                        /* Use the latest known revision as default */
-                       omap_revision = OMAP3430_REV_ES3_0;
+                       omap_revision = OMAP3430_REV_ES3_1;
                        rev_name = "Unknown revision\n";
                }
        }
index 636e282..9ba20d9 100644 (file)
@@ -134,6 +134,7 @@ static struct irq_chip omap_irq_chip = {
        .ack    = omap_mask_ack_irq,
        .mask   = omap_mask_irq,
        .unmask = omap_unmask_irq,
+       .disable = omap_mask_irq,
 };
 
 static void __init omap_irq_bank_init_one(struct omap_irq_bank *bank)
index e20023c..a9e631f 100644 (file)
 #include <mach/cpu.h>
 #include <mach/mcbsp.h>
 
-struct mcbsp_internal_clk {
-       struct clk clk;
-       struct clk **childs;
-       int n_childs;
-};
-
-#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
-static void omap_mcbsp_clk_init(struct mcbsp_internal_clk *mclk)
-{
-       const char *clk_names[] = { "mcbsp_ick", "mcbsp_fck" };
-       int i;
-
-       mclk->n_childs = ARRAY_SIZE(clk_names);
-       mclk->childs = kzalloc(mclk->n_childs * sizeof(struct clk *),
-                               GFP_KERNEL);
-
-       for (i = 0; i < mclk->n_childs; i++) {
-               /* We fake a platform device to get correct device id */
-               struct platform_device pdev;
-
-               pdev.dev.bus = &platform_bus_type;
-               pdev.id = mclk->clk.id;
-               mclk->childs[i] = clk_get(&pdev.dev, clk_names[i]);
-               if (IS_ERR(mclk->childs[i]))
-                       printk(KERN_ERR "Could not get clock %s (%d).\n",
-                               clk_names[i], mclk->clk.id);
-       }
-}
-
-static int omap_mcbsp_clk_enable(struct clk *clk)
-{
-       struct mcbsp_internal_clk *mclk = container_of(clk,
-                                       struct mcbsp_internal_clk, clk);
-       int i;
-
-       for (i = 0; i < mclk->n_childs; i++)
-               clk_enable(mclk->childs[i]);
-       return 0;
-}
-
-static void omap_mcbsp_clk_disable(struct clk *clk)
-{
-       struct mcbsp_internal_clk *mclk = container_of(clk,
-                                       struct mcbsp_internal_clk, clk);
-       int i;
-
-       for (i = 0; i < mclk->n_childs; i++)
-               clk_disable(mclk->childs[i]);
-}
-
-static struct mcbsp_internal_clk omap_mcbsp_clks[] = {
-       {
-               .clk = {
-                       .name           = "mcbsp_clk",
-                       .id             = 1,
-                       .enable         = omap_mcbsp_clk_enable,
-                       .disable        = omap_mcbsp_clk_disable,
-               },
-       },
-       {
-               .clk = {
-                       .name           = "mcbsp_clk",
-                       .id             = 2,
-                       .enable         = omap_mcbsp_clk_enable,
-                       .disable        = omap_mcbsp_clk_disable,
-               },
-       },
-       {
-               .clk = {
-                       .name           = "mcbsp_clk",
-                       .id             = 3,
-                       .enable         = omap_mcbsp_clk_enable,
-                       .disable        = omap_mcbsp_clk_disable,
-               },
-       },
-       {
-               .clk = {
-                       .name           = "mcbsp_clk",
-                       .id             = 4,
-                       .enable         = omap_mcbsp_clk_enable,
-                       .disable        = omap_mcbsp_clk_disable,
-               },
-       },
-       {
-               .clk = {
-                       .name           = "mcbsp_clk",
-                       .id             = 5,
-                       .enable         = omap_mcbsp_clk_enable,
-                       .disable        = omap_mcbsp_clk_disable,
-               },
-       },
-};
-
-#define omap_mcbsp_clks_size   ARRAY_SIZE(omap_mcbsp_clks)
-#else
-#define omap_mcbsp_clks_size   0
-static struct mcbsp_internal_clk __initdata *omap_mcbsp_clks;
-static inline void omap_mcbsp_clk_init(struct clk *clk)
-{ }
-#endif
+const char *clk_names[] = { "mcbsp_ick", "mcbsp_fck" };
 
 static void omap2_mcbsp2_mux_setup(void)
 {
@@ -156,7 +57,8 @@ static struct omap_mcbsp_platform_data omap2420_mcbsp_pdata[] = {
                .rx_irq         = INT_24XX_MCBSP1_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP1_IRQ_TX,
                .ops            = &omap2_mcbsp_ops,
-               .clk_name       = "mcbsp_clk",
+               .clk_names      = clk_names,
+               .num_clks       = 2,
        },
        {
                .phys_base      = OMAP24XX_MCBSP2_BASE,
@@ -165,7 +67,8 @@ static struct omap_mcbsp_platform_data omap2420_mcbsp_pdata[] = {
                .rx_irq         = INT_24XX_MCBSP2_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP2_IRQ_TX,
                .ops            = &omap2_mcbsp_ops,
-               .clk_name       = "mcbsp_clk",
+               .clk_names      = clk_names,
+               .num_clks       = 2,
        },
 };
 #define OMAP2420_MCBSP_PDATA_SZ                ARRAY_SIZE(omap2420_mcbsp_pdata)
@@ -183,7 +86,8 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = {
                .rx_irq         = INT_24XX_MCBSP1_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP1_IRQ_TX,
                .ops            = &omap2_mcbsp_ops,
-               .clk_name       = "mcbsp_clk",
+               .clk_names      = clk_names,
+               .num_clks       = 2,
        },
        {
                .phys_base      = OMAP24XX_MCBSP2_BASE,
@@ -192,7 +96,8 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = {
                .rx_irq         = INT_24XX_MCBSP2_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP2_IRQ_TX,
                .ops            = &omap2_mcbsp_ops,
-               .clk_name       = "mcbsp_clk",
+               .clk_names      = clk_names,
+               .num_clks       = 2,
        },
        {
                .phys_base      = OMAP2430_MCBSP3_BASE,
@@ -201,7 +106,8 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = {
                .rx_irq         = INT_24XX_MCBSP3_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP3_IRQ_TX,
                .ops            = &omap2_mcbsp_ops,
-               .clk_name       = "mcbsp_clk",
+               .clk_names      = clk_names,
+               .num_clks       = 2,
        },
        {
                .phys_base      = OMAP2430_MCBSP4_BASE,
@@ -210,7 +116,8 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = {
                .rx_irq         = INT_24XX_MCBSP4_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP4_IRQ_TX,
                .ops            = &omap2_mcbsp_ops,
-               .clk_name       = "mcbsp_clk",
+               .clk_names      = clk_names,
+               .num_clks       = 2,
        },
        {
                .phys_base      = OMAP2430_MCBSP5_BASE,
@@ -219,7 +126,8 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = {
                .rx_irq         = INT_24XX_MCBSP5_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP5_IRQ_TX,
                .ops            = &omap2_mcbsp_ops,
-               .clk_name       = "mcbsp_clk",
+               .clk_names      = clk_names,
+               .num_clks       = 2,
        },
 };
 #define OMAP2430_MCBSP_PDATA_SZ                ARRAY_SIZE(omap2430_mcbsp_pdata)
@@ -237,7 +145,8 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
                .rx_irq         = INT_24XX_MCBSP1_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP1_IRQ_TX,
                .ops            = &omap2_mcbsp_ops,
-               .clk_name       = "mcbsp_clk",
+               .clk_names      = clk_names,
+               .num_clks       = 2,
        },
        {
                .phys_base      = OMAP34XX_MCBSP2_BASE,
@@ -246,7 +155,8 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
                .rx_irq         = INT_24XX_MCBSP2_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP2_IRQ_TX,
                .ops            = &omap2_mcbsp_ops,
-               .clk_name       = "mcbsp_clk",
+               .clk_names      = clk_names,
+               .num_clks       = 2,
        },
        {
                .phys_base      = OMAP34XX_MCBSP3_BASE,
@@ -255,7 +165,8 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
                .rx_irq         = INT_24XX_MCBSP3_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP3_IRQ_TX,
                .ops            = &omap2_mcbsp_ops,
-               .clk_name       = "mcbsp_clk",
+               .clk_names      = clk_names,
+               .num_clks       = 2,
        },
        {
                .phys_base      = OMAP34XX_MCBSP4_BASE,
@@ -264,7 +175,8 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
                .rx_irq         = INT_24XX_MCBSP4_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP4_IRQ_TX,
                .ops            = &omap2_mcbsp_ops,
-               .clk_name       = "mcbsp_clk",
+               .clk_names      = clk_names,
+               .num_clks       = 2,
        },
        {
                .phys_base      = OMAP34XX_MCBSP5_BASE,
@@ -273,7 +185,8 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
                .rx_irq         = INT_24XX_MCBSP5_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP5_IRQ_TX,
                .ops            = &omap2_mcbsp_ops,
-               .clk_name       = "mcbsp_clk",
+               .clk_names      = clk_names,
+               .num_clks       = 2,
        },
 };
 #define OMAP34XX_MCBSP_PDATA_SZ                ARRAY_SIZE(omap34xx_mcbsp_pdata)
@@ -284,14 +197,6 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
 
 static int __init omap2_mcbsp_init(void)
 {
-       int i;
-
-       for (i = 0; i < omap_mcbsp_clks_size; i++) {
-               /* Once we call clk_get inside init, we do not register it */
-               omap_mcbsp_clk_init(&omap_mcbsp_clks[i]);
-               clk_register(&omap_mcbsp_clks[i].clk);
-       }
-
        if (cpu_is_omap2420())
                omap_mcbsp_count = OMAP2420_MCBSP_PDATA_SZ;
        if (cpu_is_omap2430())
index 43336b9..bf9e961 100644 (file)
@@ -93,9 +93,8 @@ ENTRY(omap24xx_cpu_suspend)
        orr     r4, r4, #0x40           @ enable self refresh on idle req
        mov     r5, #0x2000             @ set delay (DPLL relock + DLL relock)
        str     r4, [r2]                @ make it so
-       mov     r2, #0
        nop
-       mcr     p15, 0, r2, c7, c0, 4   @ wait for interrupt
+       mcr     p15, 0, r3, c7, c0, 4   @ wait for interrupt
        nop
 loop:
        subs    r5, r5, #0x1            @ awake, wait just a bit
index ae60363..9fc13a2 100644 (file)
@@ -118,7 +118,8 @@ static void __init omap2_gp_clockevent_init(void)
        clockevent_gpt.max_delta_ns =
                clockevent_delta2ns(0xffffffff, &clockevent_gpt);
        clockevent_gpt.min_delta_ns =
-               clockevent_delta2ns(1, &clockevent_gpt);
+               clockevent_delta2ns(3, &clockevent_gpt);
+               /* Timer internal resynch latency. */
 
        clockevent_gpt.cpumask = cpumask_of(0);
        clockevents_register_device(&clockevent_gpt);
index c1fbd5b..23cfdd5 100644 (file)
@@ -289,7 +289,7 @@ static struct platform_device sa11x0pcmcia_device = {
 };
 
 static struct platform_device sa11x0mtd_device = {
-       .name           = "flash",
+       .name           = "sa1100-mtd",
        .id             = -1,
 };
 
index 81d0b87..bc0099d 100644 (file)
@@ -66,7 +66,10 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address)
         * fault (ie, is old), we can safely ignore any issues.
         */
        if (ret && (pte_val(entry) & L_PTE_MT_MASK) != shared_pte_mask) {
-               flush_cache_page(vma, address, pte_pfn(entry));
+               unsigned long pfn = pte_pfn(entry);
+               flush_cache_page(vma, address, pfn);
+               outer_flush_range((pfn << PAGE_SHIFT),
+                                 (pfn << PAGE_SHIFT) + PAGE_SIZE);
                pte_val(entry) &= ~L_PTE_MT_MASK;
                pte_val(entry) |= shared_pte_mask;
                set_pte_at(vma->vm_mm, address, pte, entry);
index ac15c23..208dbb1 100644 (file)
@@ -200,14 +200,15 @@ void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config,
 /*
  * Register MMC devices. Called from mach-omap1 and mach-omap2 device init.
  */
-int __init omap_mmc_add(int id, unsigned long base, unsigned long size,
-               unsigned int irq, struct omap_mmc_platform_data *data)
+int __init omap_mmc_add(const char *name, int id, unsigned long base,
+                               unsigned long size, unsigned int irq,
+                               struct omap_mmc_platform_data *data)
 {
        struct platform_device *pdev;
        struct resource res[OMAP_MMC_NR_RES];
        int ret;
 
-       pdev = platform_device_alloc("mmci-omap", id);
+       pdev = platform_device_alloc(name, id);
        if (!pdev)
                return -ENOMEM;
 
index e77373c..47ec77a 100644 (file)
@@ -709,6 +709,7 @@ int omap_request_dma(int dev_id, const char *dev_name,
        chan->dev_name = dev_name;
        chan->callback = callback;
        chan->data = data;
+       chan->flags = 0;
 
 #ifndef CONFIG_ARCH_OMAP1
        if (cpu_class_is_omap2()) {
@@ -1888,11 +1889,11 @@ static int omap2_dma_handle_ch(int ch)
                status = dma_read(CSR(ch));
        }
 
+       dma_write(status, CSR(ch));
+
        if (likely(dma_chan[ch].callback != NULL))
                dma_chan[ch].callback(ch, status, dma_chan[ch].data);
 
-       dma_write(status, CSR(ch));
-
        return 0;
 }
 
index b2062f1..a8e1178 100644 (file)
@@ -339,6 +339,7 @@ IS_OMAP_TYPE(3430, 0x3430)
 #define OMAP3430_REV_ES2_0     0x34301034
 #define OMAP3430_REV_ES2_1     0x34302034
 #define OMAP3430_REV_ES3_0     0x34303034
+#define OMAP3430_REV_ES3_1     0x34304034
 
 /*
  * omap_chip bits
index eef873d..113c246 100644 (file)
@@ -344,7 +344,8 @@ struct omap_mcbsp_platform_data {
        u8 dma_rx_sync, dma_tx_sync;
        u16 rx_irq, tx_irq;
        struct omap_mcbsp_ops *ops;
-       char const *clk_name;
+       char const **clk_names;
+       int num_clks;
 };
 
 struct omap_mcbsp {
@@ -376,7 +377,8 @@ struct omap_mcbsp {
        /* Protect the field .free, while checking if the mcbsp is in use */
        spinlock_t lock;
        struct omap_mcbsp_platform_data *pdata;
-       struct clk *clk;
+       struct clk **clks;
+       int num_clks;
 };
 extern struct omap_mcbsp **mcbsp_ptr;
 extern int omap_mcbsp_count;
index 031250f..73a9e15 100644 (file)
@@ -115,8 +115,9 @@ void omap1_init_mmc(struct omap_mmc_platform_data **mmc_data,
                                int nr_controllers);
 void omap2_init_mmc(struct omap_mmc_platform_data **mmc_data,
                                int nr_controllers);
-int omap_mmc_add(int id, unsigned long base, unsigned long size,
-                       unsigned int irq, struct omap_mmc_platform_data *data);
+int omap_mmc_add(const char *name, int id, unsigned long base,
+                               unsigned long size, unsigned int irq,
+                               struct omap_mmc_platform_data *data);
 #else
 static inline void omap1_init_mmc(struct omap_mmc_platform_data **mmc_data,
                                int nr_controllers)
@@ -126,8 +127,9 @@ static inline void omap2_init_mmc(struct omap_mmc_platform_data **mmc_data,
                                int nr_controllers)
 {
 }
-static inline int omap_mmc_add(int id, unsigned long base, unsigned long size,
-               unsigned int irq, struct omap_mmc_platform_data *data)
+static inline int omap_mmc_add(const char *name, int id, unsigned long base,
+                               unsigned long size, unsigned int irq,
+                               struct omap_mmc_platform_data *data)
 {
        return 0;
 }
index f2401a8..e5842e3 100644 (file)
@@ -214,6 +214,7 @@ EXPORT_SYMBOL(omap_mcbsp_set_io_type);
 int omap_mcbsp_request(unsigned int id)
 {
        struct omap_mcbsp *mcbsp;
+       int i;
        int err;
 
        if (!omap_mcbsp_check_valid_id(id)) {
@@ -225,7 +226,8 @@ int omap_mcbsp_request(unsigned int id)
        if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->request)
                mcbsp->pdata->ops->request(id);
 
-       clk_enable(mcbsp->clk);
+       for (i = 0; i < mcbsp->num_clks; i++)
+               clk_enable(mcbsp->clks[i]);
 
        spin_lock(&mcbsp->lock);
        if (!mcbsp->free) {
@@ -276,6 +278,7 @@ EXPORT_SYMBOL(omap_mcbsp_request);
 void omap_mcbsp_free(unsigned int id)
 {
        struct omap_mcbsp *mcbsp;
+       int i;
 
        if (!omap_mcbsp_check_valid_id(id)) {
                printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
@@ -286,7 +289,8 @@ void omap_mcbsp_free(unsigned int id)
        if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free)
                mcbsp->pdata->ops->free(id);
 
-       clk_disable(mcbsp->clk);
+       for (i = mcbsp->num_clks - 1; i >= 0; i--)
+               clk_disable(mcbsp->clks[i]);
 
        spin_lock(&mcbsp->lock);
        if (mcbsp->free) {
@@ -872,6 +876,7 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev)
        struct omap_mcbsp_platform_data *pdata = pdev->dev.platform_data;
        struct omap_mcbsp *mcbsp;
        int id = pdev->id - 1;
+       int i;
        int ret = 0;
 
        if (!pdata) {
@@ -916,14 +921,25 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev)
        mcbsp->dma_rx_sync = pdata->dma_rx_sync;
        mcbsp->dma_tx_sync = pdata->dma_tx_sync;
 
-       if (pdata->clk_name)
-               mcbsp->clk = clk_get(&pdev->dev, pdata->clk_name);
-       if (IS_ERR(mcbsp->clk)) {
-               dev_err(&pdev->dev,
-                       "Invalid clock configuration for McBSP%d.\n",
-                       mcbsp->id);
-               ret = PTR_ERR(mcbsp->clk);
-               goto err_clk;
+       if (pdata->num_clks) {
+               mcbsp->num_clks = pdata->num_clks;
+               mcbsp->clks = kzalloc(mcbsp->num_clks * sizeof(struct clk *),
+                                       GFP_KERNEL);
+               if (!mcbsp->clks) {
+                       ret = -ENOMEM;
+                       goto exit;
+               }
+               for (i = 0; i < mcbsp->num_clks; i++) {
+                       mcbsp->clks[i] = clk_get(&pdev->dev, pdata->clk_names[i]);
+                       if (IS_ERR(mcbsp->clks[i])) {
+                               dev_err(&pdev->dev,
+                                       "Invalid %s configuration for McBSP%d.\n",
+                                       pdata->clk_names[i], mcbsp->id);
+                               ret = PTR_ERR(mcbsp->clks[i]);
+                               goto err_clk;
+                       }
+               }
+
        }
 
        mcbsp->pdata = pdata;
@@ -932,6 +948,9 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev)
        return 0;
 
 err_clk:
+       while (i--)
+               clk_put(mcbsp->clks[i]);
+       kfree(mcbsp->clks);
        iounmap(mcbsp->io_base);
 err_ioremap:
        mcbsp->free = 0;
@@ -942,6 +961,7 @@ exit:
 static int __devexit omap_mcbsp_remove(struct platform_device *pdev)
 {
        struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev);
+       int i;
 
        platform_set_drvdata(pdev, NULL);
        if (mcbsp) {
@@ -950,12 +970,18 @@ static int __devexit omap_mcbsp_remove(struct platform_device *pdev)
                                mcbsp->pdata->ops->free)
                        mcbsp->pdata->ops->free(mcbsp->id);
 
-               clk_disable(mcbsp->clk);
-               clk_put(mcbsp->clk);
+               for (i = mcbsp->num_clks - 1; i >= 0; i--) {
+                       clk_disable(mcbsp->clks[i]);
+                       clk_put(mcbsp->clks[i]);
+               }
 
                iounmap(mcbsp->io_base);
 
-               mcbsp->clk = NULL;
+               if (mcbsp->num_clks) {
+                       kfree(mcbsp->clks);
+                       mcbsp->clks = NULL;
+                       mcbsp->num_clks = 0;
+               }
                mcbsp->free = 0;
                mcbsp->dev = NULL;
        }
index a949c4f..8f1f97d 100644 (file)
@@ -169,26 +169,51 @@ config BF542
        help
          BF542 Processor Support.
 
+config BF542M
+       bool "BF542m"
+       help
+         BF542 Processor Support.
+
 config BF544
        bool "BF544"
        help
          BF544 Processor Support.
 
+config BF544M
+       bool "BF544m"
+       help
+         BF544 Processor Support.
+
 config BF547
        bool "BF547"
        help
          BF547 Processor Support.
 
+config BF547M
+       bool "BF547m"
+       help
+         BF547 Processor Support.
+
 config BF548
        bool "BF548"
        help
          BF548 Processor Support.
 
+config BF548M
+       bool "BF548m"
+       help
+         BF548 Processor Support.
+
 config BF549
        bool "BF549"
        help
          BF549 Processor Support.
 
+config BF549M
+       bool "BF549m"
+       help
+         BF549 Processor Support.
+
 config BF561
        bool "BF561"
        help
@@ -224,39 +249,39 @@ config TICK_SOURCE_SYSTMR0
 
 config BF_REV_MIN
        int
-       default 0 if (BF51x || BF52x || BF54x)
+       default 0 if (BF51x || BF52x || (BF54x && !BF54xM))
        default 2 if (BF537 || BF536 || BF534)
-       default 3 if (BF561 ||BF533 || BF532 || BF531)
+       default 3 if (BF561 || BF533 || BF532 || BF531 || BF54xM)
        default 4 if (BF538 || BF539)
 
 config BF_REV_MAX
        int
-       default 2 if (BF51x || BF52x || BF54x)
-       default 3 if (BF537 || BF536 || BF534)
+       default 2 if (BF51x || BF52x || (BF54x && !BF54xM))
+       default 3 if (BF537 || BF536 || BF534 || BF54xM)
        default 5 if (BF561 || BF538 || BF539)
        default 6 if (BF533 || BF532 || BF531)
 
 choice
        prompt "Silicon Rev"
-       default BF_REV_0_1 if (BF51x || BF52x || BF54x)
+       default BF_REV_0_1 if (BF51x || BF52x || (BF54x && !BF54xM))
        default BF_REV_0_2 if (BF534 || BF536 || BF537)
-       default BF_REV_0_3 if (BF531 || BF532 || BF533 || BF561)
+       default BF_REV_0_3 if (BF531 || BF532 || BF533 || BF54xM || BF561)
 
 config BF_REV_0_0
        bool "0.0"
-       depends on (BF51x || BF52x || BF54x)
+       depends on (BF51x || BF52x || (BF54x && !BF54xM))
 
 config BF_REV_0_1
        bool "0.1"
-       depends on (BF52x || BF54x)
+       depends on (BF52x || (BF54x && !BF54xM))
 
 config BF_REV_0_2
        bool "0.2"
-       depends on (BF52x || BF537 || BF536 || BF534 || BF54x)
+       depends on (BF52x || BF537 || BF536 || BF534 || (BF54x && !BF54xM))
 
 config BF_REV_0_3
        bool "0.3"
-       depends on (BF561 || BF537 || BF536 || BF534 || BF533 || BF532 || BF531)
+       depends on (BF54xM || BF561 || BF537 || BF536 || BF534 || BF533 || BF532 || BF531)
 
 config BF_REV_0_4
        bool "0.4"
@@ -293,9 +318,14 @@ config BF53x
        depends on (BF531 || BF532 || BF533 || BF534 || BF536 || BF537)
        default y
 
+config BF54xM
+       bool
+       depends on (BF542M || BF544M || BF547M || BF548M || BF549M)
+       default y
+
 config BF54x
        bool
-       depends on (BF542 || BF544 || BF547 || BF548 || BF549)
+       depends on (BF542 || BF544 || BF547 || BF548 || BF549 || BF54xM)
        default y
 
 config MEM_GENERIC_BOARD
index e550c8d..d54c828 100644 (file)
@@ -21,57 +21,67 @@ KALLSYMS         += --symbol-prefix=_
 KBUILD_DEFCONFIG := BF537-STAMP_defconfig
 
 # setup the machine name and the machine dependent settings
-machine-$(CONFIG_BF512) := bf518
-machine-$(CONFIG_BF514) := bf518
-machine-$(CONFIG_BF516) := bf518
-machine-$(CONFIG_BF518) := bf518
-machine-$(CONFIG_BF522) := bf527
-machine-$(CONFIG_BF523) := bf527
-machine-$(CONFIG_BF524) := bf527
-machine-$(CONFIG_BF525) := bf527
-machine-$(CONFIG_BF526) := bf527
-machine-$(CONFIG_BF527) := bf527
-machine-$(CONFIG_BF531) := bf533
-machine-$(CONFIG_BF532) := bf533
-machine-$(CONFIG_BF533) := bf533
-machine-$(CONFIG_BF534) := bf537
-machine-$(CONFIG_BF536) := bf537
-machine-$(CONFIG_BF537) := bf537
-machine-$(CONFIG_BF538) := bf538
-machine-$(CONFIG_BF539) := bf538
-machine-$(CONFIG_BF542) := bf548
-machine-$(CONFIG_BF544) := bf548
-machine-$(CONFIG_BF547) := bf548
-machine-$(CONFIG_BF548) := bf548
-machine-$(CONFIG_BF549) := bf548
-machine-$(CONFIG_BF561) := bf561
+machine-$(CONFIG_BF512)  := bf518
+machine-$(CONFIG_BF514)  := bf518
+machine-$(CONFIG_BF516)  := bf518
+machine-$(CONFIG_BF518)  := bf518
+machine-$(CONFIG_BF522)  := bf527
+machine-$(CONFIG_BF523)  := bf527
+machine-$(CONFIG_BF524)  := bf527
+machine-$(CONFIG_BF525)  := bf527
+machine-$(CONFIG_BF526)  := bf527
+machine-$(CONFIG_BF527)  := bf527
+machine-$(CONFIG_BF531)  := bf533
+machine-$(CONFIG_BF532)  := bf533
+machine-$(CONFIG_BF533)  := bf533
+machine-$(CONFIG_BF534)  := bf537
+machine-$(CONFIG_BF536)  := bf537
+machine-$(CONFIG_BF537)  := bf537
+machine-$(CONFIG_BF538)  := bf538
+machine-$(CONFIG_BF539)  := bf538
+machine-$(CONFIG_BF542)  := bf548
+machine-$(CONFIG_BF542M) := bf548
+machine-$(CONFIG_BF544)  := bf548
+machine-$(CONFIG_BF544M) := bf548
+machine-$(CONFIG_BF547)  := bf548
+machine-$(CONFIG_BF547M) := bf548
+machine-$(CONFIG_BF548)  := bf548
+machine-$(CONFIG_BF548M) := bf548
+machine-$(CONFIG_BF549)  := bf548
+machine-$(CONFIG_BF549M) := bf548
+machine-$(CONFIG_BF561)  := bf561
 MACHINE := $(machine-y)
 export MACHINE
 
-cpu-$(CONFIG_BF512) := bf512
-cpu-$(CONFIG_BF514) := bf514
-cpu-$(CONFIG_BF516) := bf516
-cpu-$(CONFIG_BF518) := bf518
-cpu-$(CONFIG_BF522) := bf522
-cpu-$(CONFIG_BF523) := bf523
-cpu-$(CONFIG_BF524) := bf524
-cpu-$(CONFIG_BF525) := bf525
-cpu-$(CONFIG_BF526) := bf526
-cpu-$(CONFIG_BF527) := bf527
-cpu-$(CONFIG_BF531) := bf531
-cpu-$(CONFIG_BF532) := bf532
-cpu-$(CONFIG_BF533) := bf533
-cpu-$(CONFIG_BF534) := bf534
-cpu-$(CONFIG_BF536) := bf536
-cpu-$(CONFIG_BF537) := bf537
-cpu-$(CONFIG_BF538) := bf538
-cpu-$(CONFIG_BF539) := bf539
-cpu-$(CONFIG_BF542) := bf542
-cpu-$(CONFIG_BF544) := bf544
-cpu-$(CONFIG_BF547) := bf547
-cpu-$(CONFIG_BF548) := bf548
-cpu-$(CONFIG_BF549) := bf549
-cpu-$(CONFIG_BF561) := bf561
+cpu-$(CONFIG_BF512)  := bf512
+cpu-$(CONFIG_BF514)  := bf514
+cpu-$(CONFIG_BF516)  := bf516
+cpu-$(CONFIG_BF518)  := bf518
+cpu-$(CONFIG_BF522)  := bf522
+cpu-$(CONFIG_BF523)  := bf523
+cpu-$(CONFIG_BF524)  := bf524
+cpu-$(CONFIG_BF525)  := bf525
+cpu-$(CONFIG_BF526)  := bf526
+cpu-$(CONFIG_BF527)  := bf527
+cpu-$(CONFIG_BF531)  := bf531
+cpu-$(CONFIG_BF532)  := bf532
+cpu-$(CONFIG_BF533)  := bf533
+cpu-$(CONFIG_BF534)  := bf534
+cpu-$(CONFIG_BF536)  := bf536
+cpu-$(CONFIG_BF537)  := bf537
+cpu-$(CONFIG_BF538)  := bf538
+cpu-$(CONFIG_BF539)  := bf539
+cpu-$(CONFIG_BF542)  := bf542
+cpu-$(CONFIG_BF542M) := bf542m
+cpu-$(CONFIG_BF544)  := bf544
+cpu-$(CONFIG_BF544M) := bf544m
+cpu-$(CONFIG_BF547)  := bf547
+cpu-$(CONFIG_BF547M) := bf547m
+cpu-$(CONFIG_BF548)  := bf548
+cpu-$(CONFIG_BF548M) := bf548m
+cpu-$(CONFIG_BF549)  := bf549
+cpu-$(CONFIG_BF549M) := bf549m
+cpu-$(CONFIG_BF561)  := bf561
 
 rev-$(CONFIG_BF_REV_0_0)  := 0.0
 rev-$(CONFIG_BF_REV_0_1)  := 0.1
index defb978..4fdb9e0 100644 (file)
@@ -1,6 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.28-rc2
+# Fri Jan  9 17:58:41 2009
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
@@ -149,6 +150,7 @@ CONFIG_BF_REV_0_0=y
 # CONFIG_BF_REV_ANY is not set
 # CONFIG_BF_REV_NONE is not set
 CONFIG_BF51x=y
+CONFIG_MEM_MT48LC32M8A2_75=y
 CONFIG_BFIN518F_EZBRD=y
 
 #
@@ -598,7 +600,10 @@ CONFIG_PHYLIB=y
 # CONFIG_MDIO_BITBANG is not set
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
-# CONFIG_BFIN_MAC is not set
+CONFIG_BFIN_MAC=y
+CONFIG_BFIN_TX_DESC_NUM=10
+CONFIG_BFIN_RX_DESC_NUM=20
+# CONFIG_BFIN_MAC_RMII is not set
 # CONFIG_SMC91X is not set
 # CONFIG_SMSC911X is not set
 # CONFIG_DM9000 is not set
@@ -679,7 +684,7 @@ CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
 # CONFIG_VT_HW_CONSOLE_BINDING is not set
 # CONFIG_DEVKMEM is not set
-# CONFIG_BFIN_JTAG_COMM is not set
+CONFIG_BFIN_JTAG_COMM=m
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
index 992424f..8e2b855 100644 (file)
@@ -723,7 +723,7 @@ CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
 # CONFIG_VT_HW_CONSOLE_BINDING is not set
 # CONFIG_DEVKMEM is not set
-# CONFIG_BFIN_JTAG_COMM is not set
+CONFIG_BFIN_JTAG_COMM=m
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
index 21e3c1a..833128b 100644 (file)
@@ -767,7 +767,7 @@ CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
 # CONFIG_VT_HW_CONSOLE_BINDING is not set
 # CONFIG_DEVKMEM is not set
-# CONFIG_BFIN_JTAG_COMM is not set
+CONFIG_BFIN_JTAG_COMM=m
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
index 0bdf20a..334c94b 100644 (file)
@@ -672,7 +672,7 @@ CONFIG_BFIN_DMA_INTERFACE=m
 CONFIG_SIMPLE_GPIO=m
 # CONFIG_VT is not set
 # CONFIG_DEVKMEM is not set
-# CONFIG_BFIN_JTAG_COMM is not set
+CONFIG_BFIN_JTAG_COMM=m
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
index 2f747d6..9d73343 100644 (file)
@@ -679,7 +679,7 @@ CONFIG_BFIN_DMA_INTERFACE=m
 CONFIG_SIMPLE_GPIO=m
 # CONFIG_VT is not set
 # CONFIG_DEVKMEM is not set
-# CONFIG_BFIN_JTAG_COMM is not set
+CONFIG_BFIN_JTAG_COMM=m
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
index 8b0a812..4fb4108 100644 (file)
@@ -722,7 +722,7 @@ CONFIG_BFIN_DMA_INTERFACE=m
 CONFIG_SIMPLE_GPIO=m
 # CONFIG_VT is not set
 # CONFIG_DEVKMEM is not set
-# CONFIG_BFIN_JTAG_COMM is not set
+CONFIG_BFIN_JTAG_COMM=m
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
index a1f766b..cb32f56 100644 (file)
@@ -726,7 +726,7 @@ CONFIG_BFIN_DMA_INTERFACE=m
 CONFIG_SIMPLE_GPIO=m
 # CONFIG_VT is not set
 # CONFIG_DEVKMEM is not set
-# CONFIG_BFIN_JTAG_COMM is not set
+CONFIG_BFIN_JTAG_COMM=m
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
index cd2da6b..0f86976 100644 (file)
@@ -856,7 +856,7 @@ CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
 # CONFIG_VT_HW_CONSOLE_BINDING is not set
 # CONFIG_DEVKMEM is not set
-# CONFIG_BFIN_JTAG_COMM is not set
+CONFIG_BFIN_JTAG_COMM=m
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
index b398ca2..042c7ad 100644 (file)
@@ -709,7 +709,7 @@ CONFIG_BFIN_DMA_INTERFACE=m
 CONFIG_SIMPLE_GPIO=m
 # CONFIG_VT is not set
 # CONFIG_DEVKMEM is not set
-# CONFIG_BFIN_JTAG_COMM is not set
+CONFIG_BFIN_JTAG_COMM=m
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
index 9514694..865ed85 100644 (file)
@@ -1,7 +1,6 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.24.7
-# Fri Jul 18 18:00:41 2008
+# Linux kernel version: 2.6.28
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
@@ -9,7 +8,6 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
 # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
 CONFIG_BLACKFIN=y
 CONFIG_ZONE_DMA=y
-CONFIG_SEMAPHORE_SLEEPERS=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -32,18 +30,16 @@ CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
-# CONFIG_USER_NS is not set
-# CONFIG_PID_NS is not set
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CGROUPS is not set
-CONFIG_FAIR_GROUP_SCHED=y
-CONFIG_FAIR_USER_SCHED=y
-# CONFIG_FAIR_CGROUP_SCHED is not set
-# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_GROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -52,26 +48,35 @@ CONFIG_EMBEDDED=y
 CONFIG_UID16=y
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 # CONFIG_ELF_CORE is not set
+CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
+CONFIG_AIO=y
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
 CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
 # CONFIG_MODVERSIONS is not set
@@ -82,6 +87,7 @@ CONFIG_BLOCK=y
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
 # CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
 
 #
 # IO Schedulers
@@ -95,9 +101,11 @@ CONFIG_IOSCHED_CFQ=y
 CONFIG_DEFAULT_CFQ=y
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_CLASSIC_RCU=y
 # CONFIG_PREEMPT_NONE is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 # CONFIG_PREEMPT is not set
+# CONFIG_FREEZER is not set
 
 #
 # Blackfin Processor Options
@@ -106,6 +114,10 @@ CONFIG_PREEMPT_VOLUNTARY=y
 #
 # Processor and Board Settings
 #
+# CONFIG_BF512 is not set
+# CONFIG_BF514 is not set
+# CONFIG_BF516 is not set
+# CONFIG_BF518 is not set
 # CONFIG_BF522 is not set
 # CONFIG_BF523 is not set
 # CONFIG_BF524 is not set
@@ -118,48 +130,32 @@ CONFIG_BF527=y
 # CONFIG_BF534 is not set
 # CONFIG_BF536 is not set
 # CONFIG_BF537 is not set
+# CONFIG_BF538 is not set
+# CONFIG_BF539 is not set
 # CONFIG_BF542 is not set
+# CONFIG_BF542M is not set
 # CONFIG_BF544 is not set
+# CONFIG_BF544M is not set
 # CONFIG_BF547 is not set
+# CONFIG_BF547M is not set
 # CONFIG_BF548 is not set
+# CONFIG_BF548M is not set
 # CONFIG_BF549 is not set
+# CONFIG_BF549M is not set
 # CONFIG_BF561 is not set
+CONFIG_BF_REV_MIN=0
+CONFIG_BF_REV_MAX=2
 # CONFIG_BF_REV_0_0 is not set
 CONFIG_BF_REV_0_1=y
 # CONFIG_BF_REV_0_2 is not set
 # CONFIG_BF_REV_0_3 is not set
 # CONFIG_BF_REV_0_4 is not set
 # CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_0_6 is not set
 # CONFIG_BF_REV_ANY is not set
 # CONFIG_BF_REV_NONE is not set
 CONFIG_BF52x=y
 CONFIG_MEM_MT48LC16M16A2TG_75=y
-# CONFIG_BFIN527_EZKIT is not set
-CONFIG_BFIN527_BLUETECHNIX_CM=y
-
-#
-# BF527 Specific Configuration
-#
-
-#
-# Alternative Multiplexing Scheme
-#
-# CONFIG_BF527_SPORT0_PORTF is not set
-CONFIG_BF527_SPORT0_PORTG=y
-CONFIG_BF527_SPORT0_TSCLK_PG10=y
-# CONFIG_BF527_SPORT0_TSCLK_PG14 is not set
-CONFIG_BF527_UART1_PORTF=y
-# CONFIG_BF527_UART1_PORTG is not set
-# CONFIG_BF527_NAND_D_PORTF is not set
-CONFIG_BF527_NAND_D_PORTH=y
-
-#
-# Interrupt Priority Assignment
-#
-
-#
-# Priority
-#
 CONFIG_IRQ_PLL_WAKEUP=7
 CONFIG_IRQ_DMA0_ERROR=7
 CONFIG_IRQ_DMAR0_BLK=7
@@ -179,7 +175,6 @@ CONFIG_IRQ_SPORT0_TX=9
 CONFIG_IRQ_SPORT1_RX=9
 CONFIG_IRQ_SPORT1_TX=9
 CONFIG_IRQ_TWI=10
-CONFIG_IRQ_SPI=10
 CONFIG_IRQ_UART0_RX=10
 CONFIG_IRQ_UART0_TX=10
 CONFIG_IRQ_UART1_RX=10
@@ -205,6 +200,34 @@ CONFIG_IRQ_MEM_DMA1=13
 CONFIG_IRQ_WATCH=13
 CONFIG_IRQ_PORTF_INTA=13
 CONFIG_IRQ_PORTF_INTB=13
+# CONFIG_BFIN527_EZKIT is not set
+CONFIG_BFIN527_BLUETECHNIX_CM=y
+# CONFIG_BFIN526_EZBRD is not set
+
+#
+# BF527 Specific Configuration
+#
+
+#
+# Alternative Multiplexing Scheme
+#
+# CONFIG_BF527_SPORT0_PORTF is not set
+CONFIG_BF527_SPORT0_PORTG=y
+CONFIG_BF527_SPORT0_TSCLK_PG10=y
+# CONFIG_BF527_SPORT0_TSCLK_PG14 is not set
+CONFIG_BF527_UART1_PORTF=y
+# CONFIG_BF527_UART1_PORTG is not set
+# CONFIG_BF527_NAND_D_PORTF is not set
+CONFIG_BF527_NAND_D_PORTH=y
+
+#
+# Interrupt Priority Assignment
+#
+
+#
+# Priority
+#
+CONFIG_IRQ_SPI=10
 CONFIG_IRQ_SPI_ERROR=7
 CONFIG_IRQ_NFC_ERROR=7
 CONFIG_IRQ_HDMA_ERROR=7
@@ -226,7 +249,6 @@ CONFIG_BOOT_LOAD=0x1000
 #
 CONFIG_CLKIN_HZ=25000000
 # CONFIG_BFIN_KERNEL_CLOCK is not set
-CONFIG_MAX_MEM_SIZE=512
 CONFIG_MAX_VCO_HZ=600000000
 CONFIG_MIN_VCO_HZ=50000000
 CONFIG_MAX_SCLK_HZ=133333333
@@ -240,10 +262,10 @@ CONFIG_HZ_250=y
 # CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
 CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 # CONFIG_CYCLES_CLOCKSOURCE is not set
-# CONFIG_TICK_ONESHOT is not set
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -277,6 +299,12 @@ CONFIG_ACCESS_OK_L1=y
 CONFIG_CACHELINE_ALIGNED_L1=y
 # CONFIG_SYSCALL_TAB_L1 is not set
 # CONFIG_CPLB_SWITCH_TAB_L1 is not set
+CONFIG_APP_STACK_L1=y
+
+#
+# Speed Optimizations
+#
+CONFIG_BFIN_INS_LOWOVERHEAD=y
 CONFIG_RAMKERNEL=y
 # CONFIG_ROMKERNEL is not set
 CONFIG_SELECT_MEMORY_MODEL=y
@@ -285,10 +313,10 @@ CONFIG_FLATMEM_MANUAL=y
 # CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_VIRT_TO_BUS=y
 CONFIG_BFIN_GPTIMERS=y
@@ -334,7 +362,6 @@ CONFIG_BANK_3=0xFFC0
 #
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
 #
-# CONFIG_PCI is not set
 # CONFIG_ARCH_SUPPORTS_MSI is not set
 # CONFIG_PCCARD is not set
 
@@ -345,25 +372,20 @@ CONFIG_BINFMT_ELF_FDPIC=y
 CONFIG_BINFMT_FLAT=y
 CONFIG_BINFMT_ZFLAT=y
 # CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 
 #
 # Power management options
 #
 # CONFIG_PM is not set
-CONFIG_SUSPEND_UP_POSSIBLE=y
-# CONFIG_PM_BFIN_SLEEP_DEEPER is not set
-# CONFIG_PM_BFIN_SLEEP is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
 # CONFIG_PM_WAKEUP_BY_GPIO is not set
 
 #
 # CPU Frequency scaling
 #
 # CONFIG_CPU_FREQ is not set
-
-#
-# Networking
-#
 CONFIG_NET=y
 
 #
@@ -376,6 +398,7 @@ CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
 # CONFIG_XFRM_SUB_POLICY is not set
 # CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
@@ -405,8 +428,6 @@ CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETLABEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
@@ -415,6 +436,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
 # CONFIG_VLAN_8021Q is not set
 # CONFIG_DECNET is not set
 # CONFIG_LLC2 is not set
@@ -431,14 +453,14 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 #
 # CONFIG_NET_PKTGEN is not set
 # CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
 # CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
 # CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
@@ -456,6 +478,8 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
 # CONFIG_CONNECTOR is not set
 CONFIG_MTD=y
@@ -464,6 +488,7 @@ CONFIG_MTD=y
 CONFIG_MTD_PARTITIONS=y
 # CONFIG_MTD_REDBOOT_PARTS is not set
 # CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
 
 #
 # User Modules And Translation Layers
@@ -507,6 +532,7 @@ CONFIG_MTD_ROM=m
 #
 CONFIG_MTD_COMPLEX_MAPPINGS=y
 # CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_GPIO_ADDR is not set
 # CONFIG_MTD_UCLINUX is not set
 # CONFIG_MTD_PLATRAM is not set
 
@@ -542,10 +568,12 @@ CONFIG_BLK_DEV=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_BLK_DEV_XIP is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
 # CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
 #
@@ -558,7 +586,6 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -579,6 +606,7 @@ CONFIG_PHYLIB=y
 # CONFIG_SMSC_PHY is not set
 # CONFIG_BROADCOM_PHY is not set
 # CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
 # CONFIG_FIXED_PHY is not set
 # CONFIG_MDIO_BITBANG is not set
 CONFIG_NET_ETHERNET=y
@@ -591,11 +619,14 @@ CONFIG_BFIN_MAC_RMII=y
 # CONFIG_SMC91X is not set
 # CONFIG_SMSC911X is not set
 # CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
 # CONFIG_IBM_NEW_EMAC_ZMII is not set
 # CONFIG_IBM_NEW_EMAC_RGMII is not set
 # CONFIG_IBM_NEW_EMAC_TAH is not set
 # CONFIG_IBM_NEW_EMAC_EMAC4 is not set
-# CONFIG_B44 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 
@@ -604,6 +635,7 @@ CONFIG_BFIN_MAC_RMII=y
 #
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
 
 #
 # USB Network Adapters
@@ -616,7 +648,6 @@ CONFIG_BFIN_MAC_RMII=y
 # CONFIG_WAN is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
 # CONFIG_NET_POLL_CONTROLLER is not set
@@ -642,14 +673,15 @@ CONFIG_BFIN_MAC_RMII=y
 # CONFIG_BF5xx_PPIFCD is not set
 # CONFIG_BFIN_SIMPLE_TIMER is not set
 # CONFIG_BF5xx_PPI is not set
-CONFIG_BFIN_OTP=y
-# CONFIG_BFIN_OTP_WRITE_ENABLE is not set
+# CONFIG_BF5xx_EPPI is not set
 # CONFIG_BFIN_SPORT is not set
 # CONFIG_BFIN_TIMER_LATENCY is not set
 # CONFIG_TWI_LCD is not set
+CONFIG_BFIN_DMA_INTERFACE=m
 CONFIG_SIMPLE_GPIO=m
 # CONFIG_VT is not set
 # CONFIG_DEVKMEM is not set
+# CONFIG_BFIN_JTAG_COMM is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -673,6 +705,8 @@ CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_BFIN_SPORT is not set
 CONFIG_UNIX98_PTYS=y
 # CONFIG_LEGACY_PTYS is not set
+CONFIG_BFIN_OTP=y
+# CONFIG_BFIN_OTP_WRITE_ENABLE is not set
 
 #
 # CAN, the car bus and industrial fieldbus
@@ -680,44 +714,49 @@ CONFIG_UNIX98_PTYS=y
 # CONFIG_CAN4LINUX is not set
 # CONFIG_IPMI_HANDLER is not set
 # CONFIG_HW_RANDOM is not set
-# CONFIG_GEN_RTC is not set
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
 # CONFIG_TCG_TPM is not set
 CONFIG_I2C=y
 CONFIG_I2C_BOARDINFO=y
 CONFIG_I2C_CHARDEV=m
+CONFIG_I2C_HELPER_AUTO=y
 
 #
-# I2C Algorithms
+# I2C Hardware Bus support
 #
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA is not set
 
 #
-# I2C Hardware Bus support
+# I2C system bus drivers (mostly embedded / system-on-chip)
 #
 CONFIG_I2C_BLACKFIN_TWI=m
 CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=100
 # CONFIG_I2C_GPIO is not set
 # CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_TAOS_EVM is not set
-# CONFIG_I2C_STUB is not set
 # CONFIG_I2C_TINY_USB is not set
 
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
 #
 # Miscellaneous I2C Chip support
 #
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 is not set
 # CONFIG_DS1682 is not set
+# CONFIG_AT24 is not set
 # CONFIG_SENSORS_AD5252 is not set
-# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_SENSORS_EEPROM is not set
 # CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCF8575 is not set
+# CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
 # CONFIG_SENSORS_PCF8591 is not set
 # CONFIG_SENSORS_MAX6875 is not set
@@ -726,37 +765,41 @@ CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=100
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
-
-#
-# SPI support
-#
 CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
 CONFIG_SPI_MASTER=y
 
 #
 # SPI Master Controller Drivers
 #
 CONFIG_SPI_BFIN=y
+# CONFIG_SPI_BFIN_LOCK is not set
 # CONFIG_SPI_BITBANG is not set
 
 #
 # SPI Protocol Masters
 #
-# CONFIG_EEPROM_AT25 is not set
+# CONFIG_SPI_AT25 is not set
 # CONFIG_SPI_SPIDEV is not set
 # CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
 # CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
 # CONFIG_SENSORS_ADM1026 is not set
 # CONFIG_SENSORS_ADM1029 is not set
 # CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
 # CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
 # CONFIG_SENSORS_ATXP1 is not set
 # CONFIG_SENSORS_DS1621 is not set
 # CONFIG_SENSORS_F71805F is not set
@@ -777,6 +820,7 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_LM90 is not set
 # CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_MAX1111 is not set
 # CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_MAX6650 is not set
 # CONFIG_SENSORS_PC87360 is not set
@@ -785,6 +829,7 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_SMSC47M192 is not set
 # CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_W83781D is not set
@@ -792,9 +837,12 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_W83792D is not set
 # CONFIG_SENSORS_W83793 is not set
 # CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
 # CONFIG_SENSORS_W83627HF is not set
 # CONFIG_SENSORS_W83627EHF is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
 CONFIG_WATCHDOG=y
 # CONFIG_WATCHDOG_NOWAYOUT is not set
 
@@ -809,22 +857,32 @@ CONFIG_BFIN_WDT=y
 #
 # CONFIG_USBPCWATCHDOG is not set
 
-#
-# Sonics Silicon Backplane
-#
-CONFIG_SSB_POSSIBLE=y
-# CONFIG_SSB is not set
-
 #
 # Multifunction device drivers
 #
+# CONFIG_MFD_CORE is not set
 # CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_REGULATOR is not set
 
 #
 # Multimedia devices
 #
+
+#
+# Multimedia core support
+#
 # CONFIG_VIDEO_DEV is not set
 # CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
 # CONFIG_DAB is not set
 
 #
@@ -839,10 +897,6 @@ CONFIG_SSB_POSSIBLE=y
 # Display device support
 #
 # CONFIG_DISPLAY_SUPPORT is not set
-
-#
-# Sound
-#
 # CONFIG_SOUND is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -850,6 +904,7 @@ CONFIG_USB_ARCH_HAS_HCD=y
 # CONFIG_USB_ARCH_HAS_EHCI is not set
 CONFIG_USB=y
 # CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
 
 #
 # Miscellaneous USB options
@@ -860,40 +915,48 @@ CONFIG_USB_DEVICE_CLASS=y
 # CONFIG_USB_OTG is not set
 # CONFIG_USB_OTG_WHITELIST is not set
 CONFIG_USB_OTG_BLACKLIST_HUB=y
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
 
 #
 # USB Host Controller Drivers
 #
+# CONFIG_USB_C67X00_HCD is not set
 # CONFIG_USB_ISP116X_HCD is not set
-# CONFIG_USB_ISP1362_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
 # CONFIG_USB_SL811_HCD is not set
 # CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
 CONFIG_USB_MUSB_HDRC=y
 CONFIG_USB_MUSB_SOC=y
 
 #
-# Blackfin high speed USB support
+# Blackfin high speed USB Support
 #
 CONFIG_USB_MUSB_HOST=y
 # CONFIG_USB_MUSB_PERIPHERAL is not set
 # CONFIG_USB_MUSB_OTG is not set
 CONFIG_USB_MUSB_HDRC_HCD=y
 CONFIG_MUSB_PIO_ONLY=y
-CONFIG_USB_MUSB_LOGLEVEL=0
+CONFIG_MUSB_DMA_POLL=y
+# CONFIG_USB_MUSB_DEBUG is not set
 
 #
 # USB Device Class drivers
 #
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
 #
 
 #
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
 #
 # CONFIG_USB_LIBUSUAL is not set
 
@@ -901,15 +964,10 @@ CONFIG_USB_MUSB_LOGLEVEL=0
 # USB Imaging devices
 #
 # CONFIG_USB_MDC800 is not set
-CONFIG_USB_MON=y
 
 #
 # USB port drivers
 #
-
-#
-# USB Serial Converter support
-#
 # CONFIG_USB_SERIAL is not set
 
 #
@@ -918,7 +976,7 @@ CONFIG_USB_MON=y
 # CONFIG_USB_EMI62 is not set
 # CONFIG_USB_EMI26 is not set
 # CONFIG_USB_ADUTUX is not set
-# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_SEVSEG is not set
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
@@ -934,17 +992,13 @@ CONFIG_USB_MON=y
 # CONFIG_USB_LD is not set
 # CONFIG_USB_TRANCEVIBRATOR is not set
 # CONFIG_USB_IOWARRIOR is not set
-
-#
-# USB DSL modem support
-#
-
-#
-# USB Gadget Support
-#
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
 # CONFIG_USB_GADGET is not set
 # CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
 CONFIG_RTC_LIB=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_HCTOSYS=y
@@ -973,51 +1027,59 @@ CONFIG_RTC_INTF_DEV=y
 # CONFIG_RTC_DRV_PCF8563 is not set
 # CONFIG_RTC_DRV_PCF8583 is not set
 # CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
 
 #
 # SPI RTC drivers
 #
-# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
 # CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
 
 #
 # Platform RTC drivers
 #
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
 # CONFIG_RTC_DRV_DS1553 is not set
-# CONFIG_RTC_DRV_STK17TA8 is not set
 # CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
 # CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
 # CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
 # CONFIG_RTC_DRV_V3020 is not set
 
 #
 # on-CPU RTC drivers
 #
 CONFIG_RTC_DRV_BFIN=y
-
-#
-# Userspace I/O
-#
+# CONFIG_DMADEVICES is not set
 # CONFIG_UIO is not set
+# CONFIG_STAGING is not set
 
 #
 # File systems
 #
 # CONFIG_EXT2_FS is not set
 # CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
-# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
+# CONFIG_DNOTIFY is not set
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
-# CONFIG_DNOTIFY is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
@@ -1059,8 +1121,11 @@ CONFIG_SYSFS=y
 # CONFIG_JFFS2_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
@@ -1068,13 +1133,12 @@ CONFIG_NFS_FS=m
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 # CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=m
 CONFIG_LOCKD_V4=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=m
-# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_SUNRPC_REGISTER_V4 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 CONFIG_SMB_FS=m
@@ -1130,7 +1194,6 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NLS_KOI8_U is not set
 # CONFIG_NLS_UTF8 is not set
 # CONFIG_DLM is not set
-# CONFIG_INSTRUMENTATION is not set
 
 #
 # Kernel hacking
@@ -1138,14 +1201,61 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_PRINTK_TIME is not set
 CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+
+#
+# Tracers
+#
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
 # CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_KGDB_TESTCASE is not set
+CONFIG_DEBUG_VERBOSE=y
 CONFIG_DEBUG_MMRS=y
+# CONFIG_DEBUG_HWERR is not set
+# CONFIG_DEBUG_DOUBLEFAULT is not set
 CONFIG_DEBUG_HUNT_FOR_ZERO=y
 CONFIG_DEBUG_BFIN_HWTRACE_ON=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
@@ -1154,7 +1264,7 @@ CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
 # CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
-CONFIG_EARLY_PRINTK=y
+# CONFIG_EARLY_PRINTK is not set
 # CONFIG_CPLB_INFO is not set
 CONFIG_ACCESS_CHECK=y
 
@@ -1163,10 +1273,96 @@ CONFIG_ACCESS_CHECK=y
 #
 # CONFIG_KEYS is not set
 CONFIG_SECURITY=y
+# CONFIG_SECURITYFS is not set
 # CONFIG_SECURITY_NETWORK is not set
-# CONFIG_SECURITY_CAPABILITIES is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
 # CONFIG_SECURITY_ROOTPLUG is not set
-# CONFIG_CRYPTO is not set
+CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
 
 #
 # Library routines
@@ -1174,6 +1370,7 @@ CONFIG_SECURITY=y
 CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
 # CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_CRC7 is not set
index f67289a..793581f 100644 (file)
@@ -63,23 +63,23 @@ static inline __wsum
 csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
                   unsigned short proto, __wsum sum)
 {
-
-       __asm__ ("%0 = %0 + %1;\n\t"
-                "CC = AC0;\n\t"
-                "if !CC jump 4;\n\t"
-                "%0 = %0 + %4;\n\t"
-                "%0 = %0 + %2;\n\t"
-                "CC = AC0;\n\t"
-                 "if !CC jump 4;\n\t"
-                 "%0 = %0 + %4;\n\t"
-                "%0 = %0 + %3;\n\t"
-                "CC = AC0;\n\t"
-                 "if !CC jump 4;\n\t"
-                 "%0 = %0 + %4;\n\t"
-                 "NOP;\n\t"
-                : "=d" (sum)
-                : "d" (daddr), "d" (saddr), "d" ((ntohs(len)<<16)+proto*256), "d" (1), "0"(sum)
-                : "CC");
+       unsigned int carry;
+
+       __asm__ ("%0 = %0 + %2;\n\t"
+               "CC = AC0;\n\t"
+               "%1 = CC;\n\t"
+               "%0 = %0 + %1;\n\t"
+               "%0 = %0 + %3;\n\t"
+               "CC = AC0;\n\t"
+               "%1 = CC;\n\t"
+               "%0 = %0 + %1;\n\t"
+               "%0 = %0 + %4;\n\t"
+               "CC = AC0;\n\t"
+               "%1 = CC;\n\t"
+               "%0 = %0 + %1;\n\t"
+               : "=d" (sum), "=&d" (carry)
+               : "d" (daddr), "d" (saddr), "d" ((len + proto) << 8), "0"(sum)
+               : "CC");
 
        return (sum);
 }
index 0889c3a..c31f91c 100644 (file)
 
 static inline void __delay(unsigned long loops)
 {
-       if (ANOMALY_05000312) {
-               /* Interrupted loads to loop registers -> bad */
-               unsigned long tmp;
-               __asm__ __volatile__(
-                       "[--SP] = LC0;"
-                       "[--SP] = LT0;"
-                       "[--SP] = LB0;"
-                       "LSETUP (1f,1f) LC0 = %1;"
-                       "1: NOP;"
-                       /* We take advantage of the fact that LC0 is 0 at
-                        * the end of the loop.  Otherwise we'd need some
-                        * NOPs after the CLI here.
-                        */
-                       "CLI %0;"
-                       "LB0 = [SP++];"
-                       "LT0 = [SP++];"
-                       "LC0 = [SP++];"
-                       "STI %0;"
-                       : "=d" (tmp)
-                       : "a" (loops)
-               );
-       } else
-               __asm__ __volatile__ (
+__asm__ __volatile__ (
                        "LSETUP(1f, 1f) LC0 = %0;"
                        "1: NOP;"
                        :
@@ -47,16 +25,15 @@ static inline void __delay(unsigned long loops)
 #include <linux/param.h>       /* needed for HZ */
 
 /*
- * Use only for very small delays ( < 1 msec).  Should probably use a
- * lookup table, really, as the multiplications take much too long with
- * short delays.  This is a "reasonable" implementation, though (and the
- * first constant multiplications gets optimized away if the delay is
- * a constant)
+ * close approximation borrowed from m68knommu to avoid 64-bit math
  */
+
+#define        HZSCALE         (268435456 / (1000000/HZ))
+
 static inline void udelay(unsigned long usecs)
 {
        extern unsigned long loops_per_jiffy;
-       __delay(usecs * loops_per_jiffy / (1000000 / HZ));
+       __delay((((usecs * HZSCALE) >> 11) * (loops_per_jiffy >> 11)) >> 6);
 }
 
 #endif
index 9477d82..d4a082e 100644 (file)
  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-/*
-*  Number     BF537/6/4    BF561    BF533/2/1
-*             BF527/5/2
-*
-*  GPIO_0       PF0         PF0        PF0
-*  GPIO_1       PF1         PF1        PF1
-*  GPIO_2       PF2         PF2        PF2
-*  GPIO_3       PF3         PF3        PF3
-*  GPIO_4       PF4         PF4        PF4
-*  GPIO_5       PF5         PF5        PF5
-*  GPIO_6       PF6         PF6        PF6
-*  GPIO_7       PF7         PF7        PF7
-*  GPIO_8       PF8         PF8        PF8
-*  GPIO_9       PF9         PF9        PF9
-*  GPIO_10      PF10        PF10       PF10
-*  GPIO_11      PF11        PF11       PF11
-*  GPIO_12      PF12        PF12       PF12
-*  GPIO_13      PF13        PF13       PF13
-*  GPIO_14      PF14        PF14       PF14
-*  GPIO_15      PF15        PF15       PF15
-*  GPIO_16      PG0         PF16
-*  GPIO_17      PG1         PF17
-*  GPIO_18      PG2         PF18
-*  GPIO_19      PG3         PF19
-*  GPIO_20      PG4         PF20
-*  GPIO_21      PG5         PF21
-*  GPIO_22      PG6         PF22
-*  GPIO_23      PG7         PF23
-*  GPIO_24      PG8         PF24
-*  GPIO_25      PG9         PF25
-*  GPIO_26      PG10        PF26
-*  GPIO_27      PG11        PF27
-*  GPIO_28      PG12        PF28
-*  GPIO_29      PG13        PF29
-*  GPIO_30      PG14        PF30
-*  GPIO_31      PG15        PF31
-*  GPIO_32      PH0         PF32
-*  GPIO_33      PH1         PF33
-*  GPIO_34      PH2         PF34
-*  GPIO_35      PH3         PF35
-*  GPIO_36      PH4         PF36
-*  GPIO_37      PH5         PF37
-*  GPIO_38      PH6         PF38
-*  GPIO_39      PH7         PF39
-*  GPIO_40      PH8         PF40
-*  GPIO_41      PH9         PF41
-*  GPIO_42      PH10        PF42
-*  GPIO_43      PH11        PF43
-*  GPIO_44      PH12        PF44
-*  GPIO_45      PH13        PF45
-*  GPIO_46      PH14        PF46
-*  GPIO_47      PH15        PF47
-*/
-
 #ifndef __ARCH_BLACKFIN_GPIO_H__
 #define __ARCH_BLACKFIN_GPIO_H__
 
@@ -295,10 +241,6 @@ int bfin_gpio_direction_output(unsigned gpio, int value);
 int bfin_gpio_get_value(unsigned gpio);
 void bfin_gpio_set_value(unsigned gpio, int value);
 
-#ifndef BF548_FAMILY
-#define bfin_gpio_set_value(gpio, value)    set_gpio_data(gpio, value)
-#endif
-
 #ifdef CONFIG_GPIOLIB
 #include <asm-generic/gpio.h>          /* cansleep wrappers */
 
index 26ebac6..c8b256d 100644 (file)
@@ -1,32 +1,8 @@
-/*
- * File:         include/asm-blackfin/kgdb.h
- * Based on:
- * Author:       Sonic Zhang
- *
- * Created:
- * Description:
- *
- * Rev:          $Id: kgdb_bfin_linux-2.6.x.patch 4934 2007-02-13 09:32:11Z sonicz $
- *
- * Modified:
- *               Copyright 2005-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+/* Blackfin KGDB header
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * Copyright 2005-2009 Analog Devices Inc.
  *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef __ASM_BLACKFIN_KGDB_H__
 /* gdb locks */
 #define KGDB_MAX_NO_CPUS 8
 
-/************************************************************************/
-/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
-/* at least NUMREGBYTES*2 are needed for register packets */
-/* Longer buffer is needed to list all threads */
+/*
+ * BUFMAX defines the maximum number of characters in inbound/outbound buffers.
+ * At least NUMREGBYTES*2 are needed for register packets.
+ * Longer buffer is needed to list all threads.
+ */
 #define BUFMAX 2048
 
 /*
- *  Note that this register image is different from
- *  the register image that Linux produces at interrupt time.
- *  
- *  Linux's register image is defined by struct pt_regs in ptrace.h.
+ * Note that this register image is different from
+ * the register image that Linux produces at interrupt time.
+ *
+ * Linux's register image is defined by struct pt_regs in ptrace.h.
  */
 enum regnames {
   /* Core Registers */
@@ -104,14 +81,14 @@ enum regnames {
   BFIN_RETX,
   BFIN_RETN,
   BFIN_RETE,
-  
+
   /* Pseudo Registers */
   BFIN_PC,
   BFIN_CC,
   BFIN_EXTRA1,         /* Address of .text section.  */
   BFIN_EXTRA2,         /* Address of .data section.  */
   BFIN_EXTRA3,         /* Address of .bss section.  */
-  BFIN_FDPIC_EXEC, 
+  BFIN_FDPIC_EXEC,
   BFIN_FDPIC_INTERP,
 
   /* MMRs */
@@ -126,7 +103,7 @@ enum regnames {
 
 static inline void arch_kgdb_breakpoint(void)
 {
-       asm("   EXCPT 2;");
+       asm("EXCPT 2;");
 }
 #define BREAK_INSTR_SIZE       2
 #define CACHE_FLUSH_IS_SAFE    1
index 255a931..61f7487 100644 (file)
 #define mem_SDRRC       (((CONFIG_SCLK_HZ / 1000) * SDRAM_Tref) / SDRAM_NRA) - (SDRAM_tRAS_num + SDRAM_tRP_num)
 
 /* Enable SCLK Out */
-#define mem_SDGCTL        (0x80000000 | SCTLE | SDRAM_CL | SDRAM_tRAS | SDRAM_tRP | SDRAM_tRCD | SDRAM_tWR | PSS)
+#define mem_SDGCTL        (SCTLE | SDRAM_CL | SDRAM_tRAS | SDRAM_tRP | SDRAM_tRCD | SDRAM_tWR | PSS)
 #else
 #define mem_SDRRC      CONFIG_MEM_SDRRC
 #define mem_SDGCTL     CONFIG_MEM_SDGCTL
index bd8d4a7..a671427 100644 (file)
@@ -59,6 +59,7 @@ struct blackfin_pda {                 /* Per-processor Data Area */
        unsigned long icplb_fault_addr;
        unsigned long retx;
        unsigned long seqstat;
+       unsigned int __nmi_count;       /* number of times NMI asserted on this CPU */
 };
 
 extern struct blackfin_pda cpu_pda[];
index 4856d62..ae1e363 100644 (file)
@@ -15,6 +15,6 @@ extern void native_machine_halt(void);
 extern void native_machine_power_off(void);
 
 /* common reboot workarounds */
-extern void bfin_gpio_reset_spi0_ssel1(void);
+extern void bfin_reset_boot_spi_cs(unsigned short pin);
 
 #endif
index 38a2333..4a92a86 100644 (file)
@@ -15,6 +15,8 @@ else
     obj-y += time.o
 endif
 
+CFLAGS_kgdb_test.o := -mlong-calls -O0
+
 obj-$(CONFIG_IPIPE)                  += ipipe.o
 obj-$(CONFIG_IPIPE_TRACE_MCOUNT)     += mcount.o
 obj-$(CONFIG_BFIN_GPTIMERS)          += gptimers.o
index 07e02c0..8531693 100644 (file)
@@ -249,6 +249,13 @@ static void __dma_memcpy(u32 daddr, s16 dmod, u32 saddr, s16 smod, size_t cnt, u
 
        spin_lock_irqsave(&mdma_lock, flags);
 
+       /* Force a sync in case a previous config reset on this channel
+        * occurred.  This is needed so subsequent writes to DMA registers
+        * are not spuriously lost/corrupted.  Do it under irq lock and
+        * without the anomaly version (because we are atomic already).
+        */
+       __builtin_bfin_ssync();
+
        if (bfin_read_MDMA_S0_CONFIG())
                while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE))
                        continue;
index 4c14331..51dac55 100644 (file)
  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-/*
-*  Number     BF537/6/4    BF561    BF533/2/1     BF549/8/4/2
-*
-*  GPIO_0       PF0         PF0        PF0        PA0...PJ13
-*  GPIO_1       PF1         PF1        PF1
-*  GPIO_2       PF2         PF2        PF2
-*  GPIO_3       PF3         PF3        PF3
-*  GPIO_4       PF4         PF4        PF4
-*  GPIO_5       PF5         PF5        PF5
-*  GPIO_6       PF6         PF6        PF6
-*  GPIO_7       PF7         PF7        PF7
-*  GPIO_8       PF8         PF8        PF8
-*  GPIO_9       PF9         PF9        PF9
-*  GPIO_10      PF10        PF10       PF10
-*  GPIO_11      PF11        PF11       PF11
-*  GPIO_12      PF12        PF12       PF12
-*  GPIO_13      PF13        PF13       PF13
-*  GPIO_14      PF14        PF14       PF14
-*  GPIO_15      PF15        PF15       PF15
-*  GPIO_16      PG0         PF16
-*  GPIO_17      PG1         PF17
-*  GPIO_18      PG2         PF18
-*  GPIO_19      PG3         PF19
-*  GPIO_20      PG4         PF20
-*  GPIO_21      PG5         PF21
-*  GPIO_22      PG6         PF22
-*  GPIO_23      PG7         PF23
-*  GPIO_24      PG8         PF24
-*  GPIO_25      PG9         PF25
-*  GPIO_26      PG10        PF26
-*  GPIO_27      PG11        PF27
-*  GPIO_28      PG12        PF28
-*  GPIO_29      PG13        PF29
-*  GPIO_30      PG14        PF30
-*  GPIO_31      PG15        PF31
-*  GPIO_32      PH0         PF32
-*  GPIO_33      PH1         PF33
-*  GPIO_34      PH2         PF34
-*  GPIO_35      PH3         PF35
-*  GPIO_36      PH4         PF36
-*  GPIO_37      PH5         PF37
-*  GPIO_38      PH6         PF38
-*  GPIO_39      PH7         PF39
-*  GPIO_40      PH8         PF40
-*  GPIO_41      PH9         PF41
-*  GPIO_42      PH10        PF42
-*  GPIO_43      PH11        PF43
-*  GPIO_44      PH12        PF44
-*  GPIO_45      PH13        PF45
-*  GPIO_46      PH14        PF46
-*  GPIO_47      PH15        PF47
-*/
-
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/err.h>
@@ -119,62 +66,61 @@ enum {
 #define AWA_DUMMY_READ(...)  do { } while (0)
 #endif
 
+static struct gpio_port_t * const gpio_array[] = {
 #if defined(BF533_FAMILY) || defined(BF538_FAMILY)
-static struct gpio_port_t *gpio_bankb[] = {
        (struct gpio_port_t *) FIO_FLAG_D,
-};
-#endif
-
-#if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY)
-static struct gpio_port_t *gpio_bankb[] = {
+#elif defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY)
        (struct gpio_port_t *) PORTFIO,
        (struct gpio_port_t *) PORTGIO,
        (struct gpio_port_t *) PORTHIO,
+#elif defined(BF561_FAMILY)
+       (struct gpio_port_t *) FIO0_FLAG_D,
+       (struct gpio_port_t *) FIO1_FLAG_D,
+       (struct gpio_port_t *) FIO2_FLAG_D,
+#elif defined(BF548_FAMILY)
+       (struct gpio_port_t *)PORTA_FER,
+       (struct gpio_port_t *)PORTB_FER,
+       (struct gpio_port_t *)PORTC_FER,
+       (struct gpio_port_t *)PORTD_FER,
+       (struct gpio_port_t *)PORTE_FER,
+       (struct gpio_port_t *)PORTF_FER,
+       (struct gpio_port_t *)PORTG_FER,
+       (struct gpio_port_t *)PORTH_FER,
+       (struct gpio_port_t *)PORTI_FER,
+       (struct gpio_port_t *)PORTJ_FER,
+#else
+# error no gpio arrays defined
+#endif
 };
 
-static unsigned short *port_fer[] = {
+#if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY)
+static unsigned short * const port_fer[] = {
        (unsigned short *) PORTF_FER,
        (unsigned short *) PORTG_FER,
        (unsigned short *) PORTH_FER,
 };
-#endif
 
-#if defined(BF527_FAMILY) || defined(BF518_FAMILY)
-static unsigned short *port_mux[] = {
+# if !defined(BF537_FAMILY)
+static unsigned short * const port_mux[] = {
        (unsigned short *) PORTF_MUX,
        (unsigned short *) PORTG_MUX,
        (unsigned short *) PORTH_MUX,
 };
 
 static const
-u8 pmux_offset[][16] =
-       {{ 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 4, 6, 8, 8, 10, 10 }, /* PORTF */
-        { 0, 0, 0, 0, 0, 2, 2, 4, 4, 6, 8, 10, 10, 10, 12, 12 }, /* PORTG */
-        { 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 4, 4, 4, 4, 4 }, /* PORTH */
-       };
-#endif
-
-#ifdef BF561_FAMILY
-static struct gpio_port_t *gpio_bankb[] = {
-       (struct gpio_port_t *) FIO0_FLAG_D,
-       (struct gpio_port_t *) FIO1_FLAG_D,
-       (struct gpio_port_t *) FIO2_FLAG_D,
+u8 pmux_offset[][16] = {
+#  if defined(BF527_FAMILY)
+       { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 4, 6, 8, 8, 10, 10 }, /* PORTF */
+       { 0, 0, 0, 0, 0, 2, 2, 4, 4, 6, 8, 10, 10, 10, 12, 12 }, /* PORTG */
+       { 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 4, 4, 4, 4, 4 }, /* PORTH */
+#  elif defined(BF518_FAMILY)
+       { 0, 2, 2, 2, 2, 2, 2, 4, 6, 6, 6, 8, 8, 8, 8, 10 }, /* PORTF */
+       { 0, 0, 0, 2, 4, 6, 6, 6, 8, 10, 10, 12, 14, 14, 14, 14 }, /* PORTG */
+       { 0, 0, 0, 0, 2, 2, 4, 6, 10, 10, 10, 10, 10, 10, 10, 10 }, /* PORTH */
+#  endif
 };
-#endif
+# endif
 
-#ifdef BF548_FAMILY
-static struct gpio_port_t *gpio_array[] = {
-       (struct gpio_port_t *)PORTA_FER,
-       (struct gpio_port_t *)PORTB_FER,
-       (struct gpio_port_t *)PORTC_FER,
-       (struct gpio_port_t *)PORTD_FER,
-       (struct gpio_port_t *)PORTE_FER,
-       (struct gpio_port_t *)PORTF_FER,
-       (struct gpio_port_t *)PORTG_FER,
-       (struct gpio_port_t *)PORTH_FER,
-       (struct gpio_port_t *)PORTI_FER,
-       (struct gpio_port_t *)PORTJ_FER,
-};
 #endif
 
 static unsigned short reserved_gpio_map[GPIO_BANK_NUM];
@@ -188,35 +134,9 @@ static struct str_ident {
 } str_ident[MAX_RESOURCES];
 
 #if defined(CONFIG_PM)
-#if defined(CONFIG_BF54x)
-static struct gpio_port_s gpio_bank_saved[GPIO_BANK_NUM];
-#else
-static unsigned short wakeup_map[GPIO_BANK_NUM];
-static unsigned char wakeup_flags_map[MAX_BLACKFIN_GPIOS];
 static struct gpio_port_s gpio_bank_saved[GPIO_BANK_NUM];
-
-#ifdef BF533_FAMILY
-static unsigned int sic_iwr_irqs[] = {IRQ_PROG_INTB};
-#endif
-
-#ifdef BF537_FAMILY
-static unsigned int sic_iwr_irqs[] = {IRQ_PROG_INTB, IRQ_PORTG_INTB, IRQ_MAC_TX};
-#endif
-
-#ifdef BF538_FAMILY
-static unsigned int sic_iwr_irqs[] = {IRQ_PORTF_INTB};
 #endif
 
-#if defined(BF527_FAMILY) || defined(BF518_FAMILY)
-static unsigned int sic_iwr_irqs[] = {IRQ_PORTF_INTB, IRQ_PORTG_INTB, IRQ_PORTH_INTB};
-#endif
-
-#ifdef BF561_FAMILY
-static unsigned int sic_iwr_irqs[] = {IRQ_PROG0_INTB, IRQ_PROG1_INTB, IRQ_PROG2_INTB};
-#endif
-#endif
-#endif /* CONFIG_PM */
-
 inline int check_gpio(unsigned gpio)
 {
 #if defined(BF548_FAMILY)
@@ -330,9 +250,10 @@ static struct {
        {.res = P_SPI0_SSEL3, .offset = 0},
 };
 
-static void portmux_setup(unsigned short per, unsigned short function)
+static void portmux_setup(unsigned short per)
 {
        u16 y, offset, muxreg;
+       u16 function = P_FUNCT2MUX(per);
 
        for (y = 0; y < ARRAY_SIZE(port_mux_lut); y++) {
                if (port_mux_lut[y].res == per) {
@@ -353,30 +274,33 @@ static void portmux_setup(unsigned short per, unsigned short function)
        }
 }
 #elif defined(BF548_FAMILY)
-inline void portmux_setup(unsigned short portno, unsigned short function)
+inline void portmux_setup(unsigned short per)
 {
        u32 pmux;
+       u16 ident = P_IDENT(per);
+       u16 function = P_FUNCT2MUX(per);
 
-       pmux = gpio_array[gpio_bank(portno)]->port_mux;
+       pmux = gpio_array[gpio_bank(ident)]->port_mux;
 
-       pmux &= ~(0x3 << (2 * gpio_sub_n(portno)));
-       pmux |= (function & 0x3) << (2 * gpio_sub_n(portno));
+       pmux &= ~(0x3 << (2 * gpio_sub_n(ident)));
+       pmux |= (function & 0x3) << (2 * gpio_sub_n(ident));
 
-       gpio_array[gpio_bank(portno)]->port_mux = pmux;
+       gpio_array[gpio_bank(ident)]->port_mux = pmux;
 }
 
-inline u16 get_portmux(unsigned short portno)
+inline u16 get_portmux(unsigned short per)
 {
        u32 pmux;
+       u16 ident = P_IDENT(per);
 
-       pmux = gpio_array[gpio_bank(portno)]->port_mux;
+       pmux = gpio_array[gpio_bank(ident)]->port_mux;
 
-       return (pmux >> (2 * gpio_sub_n(portno)) & 0x3);
+       return (pmux >> (2 * gpio_sub_n(ident)) & 0x3);
 }
 #elif defined(BF527_FAMILY) || defined(BF518_FAMILY)
-inline void portmux_setup(unsigned short portno, unsigned short function)
+inline void portmux_setup(unsigned short per)
 {
-       u16 pmux, ident = P_IDENT(portno);
+       u16 pmux, ident = P_IDENT(per), function = P_FUNCT2MUX(per);
        u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)];
 
        pmux = *port_mux[gpio_bank(ident)];
@@ -424,90 +348,71 @@ void set_gpio_ ## name(unsigned gpio, unsigned short arg) \
        unsigned long flags; \
        local_irq_save_hw(flags); \
        if (arg) \
-               gpio_bankb[gpio_bank(gpio)]->name |= gpio_bit(gpio); \
+               gpio_array[gpio_bank(gpio)]->name |= gpio_bit(gpio); \
        else \
-               gpio_bankb[gpio_bank(gpio)]->name &= ~gpio_bit(gpio); \
+               gpio_array[gpio_bank(gpio)]->name &= ~gpio_bit(gpio); \
        AWA_DUMMY_READ(name); \
        local_irq_restore_hw(flags); \
 } \
 EXPORT_SYMBOL(set_gpio_ ## name);
 
-SET_GPIO(dir)
-SET_GPIO(inen)
-SET_GPIO(polar)
-SET_GPIO(edge)
-SET_GPIO(both)
+SET_GPIO(dir)   /* set_gpio_dir() */
+SET_GPIO(inen)  /* set_gpio_inen() */
+SET_GPIO(polar) /* set_gpio_polar() */
+SET_GPIO(edge)  /* set_gpio_edge() */
+SET_GPIO(both)  /* set_gpio_both() */
 
 
-#if ANOMALY_05000311 || ANOMALY_05000323
 #define SET_GPIO_SC(name) \
 void set_gpio_ ## name(unsigned gpio, unsigned short arg) \
 { \
        unsigned long flags; \
-       local_irq_save_hw(flags); \
-       if (arg) \
-               gpio_bankb[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \
-       else \
-               gpio_bankb[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \
-       AWA_DUMMY_READ(name); \
-       local_irq_restore_hw(flags); \
-} \
-EXPORT_SYMBOL(set_gpio_ ## name);
-#else
-#define SET_GPIO_SC(name) \
-void set_gpio_ ## name(unsigned gpio, unsigned short arg) \
-{ \
+       if (ANOMALY_05000311 || ANOMALY_05000323) \
+               local_irq_save_hw(flags); \
        if (arg) \
-               gpio_bankb[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \
+               gpio_array[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \
        else \
-               gpio_bankb[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \
+               gpio_array[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \
+       if (ANOMALY_05000311 || ANOMALY_05000323) { \
+               AWA_DUMMY_READ(name); \
+               local_irq_restore_hw(flags); \
+       } \
 } \
 EXPORT_SYMBOL(set_gpio_ ## name);
-#endif
 
 SET_GPIO_SC(maska)
 SET_GPIO_SC(maskb)
 SET_GPIO_SC(data)
 
-#if ANOMALY_05000311 || ANOMALY_05000323
 void set_gpio_toggle(unsigned gpio)
 {
        unsigned long flags;
-       local_irq_save_hw(flags);
-       gpio_bankb[gpio_bank(gpio)]->toggle = gpio_bit(gpio);
-       AWA_DUMMY_READ(toggle);
-       local_irq_restore_hw(flags);
-}
-#else
-void set_gpio_toggle(unsigned gpio)
-{
-       gpio_bankb[gpio_bank(gpio)]->toggle = gpio_bit(gpio);
+       if (ANOMALY_05000311 || ANOMALY_05000323)
+               local_irq_save_hw(flags);
+       gpio_array[gpio_bank(gpio)]->toggle = gpio_bit(gpio);
+       if (ANOMALY_05000311 || ANOMALY_05000323) {
+               AWA_DUMMY_READ(toggle);
+               local_irq_restore_hw(flags);
+       }
 }
-#endif
 EXPORT_SYMBOL(set_gpio_toggle);
 
 
 /*Set current PORT date (16-bit word)*/
 
-#if ANOMALY_05000311 || ANOMALY_05000323
 #define SET_GPIO_P(name) \
 void set_gpiop_ ## name(unsigned gpio, unsigned short arg) \
 { \
        unsigned long flags; \
-       local_irq_save_hw(flags); \
-       gpio_bankb[gpio_bank(gpio)]->name = arg; \
-       AWA_DUMMY_READ(name); \
-       local_irq_restore_hw(flags); \
+       if (ANOMALY_05000311 || ANOMALY_05000323) \
+               local_irq_save_hw(flags); \
+       gpio_array[gpio_bank(gpio)]->name = arg; \
+       if (ANOMALY_05000311 || ANOMALY_05000323) { \
+               AWA_DUMMY_READ(name); \
+               local_irq_restore_hw(flags); \
+       } \
 } \
 EXPORT_SYMBOL(set_gpiop_ ## name);
-#else
-#define SET_GPIO_P(name) \
-void set_gpiop_ ## name(unsigned gpio, unsigned short arg) \
-{ \
-       gpio_bankb[gpio_bank(gpio)]->name = arg; \
-} \
-EXPORT_SYMBOL(set_gpiop_ ## name);
-#endif
 
 SET_GPIO_P(data)
 SET_GPIO_P(dir)
@@ -519,27 +424,21 @@ SET_GPIO_P(maska)
 SET_GPIO_P(maskb)
 
 /* Get a specific bit */
-#if ANOMALY_05000311 || ANOMALY_05000323
 #define GET_GPIO(name) \
 unsigned short get_gpio_ ## name(unsigned gpio) \
 { \
        unsigned long flags; \
        unsigned short ret; \
-       local_irq_save_hw(flags); \
-       ret = 0x01 & (gpio_bankb[gpio_bank(gpio)]->name >> gpio_sub_n(gpio)); \
-       AWA_DUMMY_READ(name); \
-       local_irq_restore_hw(flags); \
+       if (ANOMALY_05000311 || ANOMALY_05000323) \
+               local_irq_save_hw(flags); \
+       ret = 0x01 & (gpio_array[gpio_bank(gpio)]->name >> gpio_sub_n(gpio)); \
+       if (ANOMALY_05000311 || ANOMALY_05000323) { \
+               AWA_DUMMY_READ(name); \
+               local_irq_restore_hw(flags); \
+       } \
        return ret; \
 } \
 EXPORT_SYMBOL(get_gpio_ ## name);
-#else
-#define GET_GPIO(name) \
-unsigned short get_gpio_ ## name(unsigned gpio) \
-{ \
-       return (0x01 & (gpio_bankb[gpio_bank(gpio)]->name >> gpio_sub_n(gpio))); \
-} \
-EXPORT_SYMBOL(get_gpio_ ## name);
-#endif
 
 GET_GPIO(data)
 GET_GPIO(dir)
@@ -552,27 +451,21 @@ GET_GPIO(maskb)
 
 /*Get current PORT date (16-bit word)*/
 
-#if ANOMALY_05000311 || ANOMALY_05000323
 #define GET_GPIO_P(name) \
 unsigned short get_gpiop_ ## name(unsigned gpio) \
 { \
        unsigned long flags; \
        unsigned short ret; \
-       local_irq_save_hw(flags); \
-       ret = (gpio_bankb[gpio_bank(gpio)]->name); \
-       AWA_DUMMY_READ(name); \
-       local_irq_restore_hw(flags); \
+       if (ANOMALY_05000311 || ANOMALY_05000323) \
+               local_irq_save_hw(flags); \
+       ret = (gpio_array[gpio_bank(gpio)]->name); \
+       if (ANOMALY_05000311 || ANOMALY_05000323) { \
+               AWA_DUMMY_READ(name); \
+               local_irq_restore_hw(flags); \
+       } \
        return ret; \
 } \
 EXPORT_SYMBOL(get_gpiop_ ## name);
-#else
-#define GET_GPIO_P(name) \
-unsigned short get_gpiop_ ## name(unsigned gpio) \
-{ \
-       return (gpio_bankb[gpio_bank(gpio)]->name);\
-} \
-EXPORT_SYMBOL(get_gpiop_ ## name);
-#endif
 
 GET_GPIO_P(data)
 GET_GPIO_P(dir)
@@ -585,6 +478,26 @@ GET_GPIO_P(maskb)
 
 
 #ifdef CONFIG_PM
+
+static unsigned short wakeup_map[GPIO_BANK_NUM];
+static unsigned char wakeup_flags_map[MAX_BLACKFIN_GPIOS];
+
+static const unsigned int sic_iwr_irqs[] = {
+#if defined(BF533_FAMILY)
+       IRQ_PROG_INTB
+#elif defined(BF537_FAMILY)
+       IRQ_PROG_INTB, IRQ_PORTG_INTB, IRQ_MAC_TX
+#elif defined(BF538_FAMILY)
+       IRQ_PORTF_INTB
+#elif defined(BF527_FAMILY) || defined(BF518_FAMILY)
+       IRQ_PORTF_INTB, IRQ_PORTG_INTB, IRQ_PORTH_INTB
+#elif defined(BF561_FAMILY)
+       IRQ_PROG0_INTB, IRQ_PROG1_INTB, IRQ_PROG2_INTB
+#else
+# error no SIC_IWR defined
+#endif
+};
+
 /***********************************************************
 *
 * FUNCTIONS: Blackfin PM Setup API
@@ -669,18 +582,18 @@ u32 bfin_pm_standby_setup(void)
                mask = wakeup_map[gpio_bank(i)];
                bank = gpio_bank(i);
 
-               gpio_bank_saved[bank].maskb = gpio_bankb[bank]->maskb;
-               gpio_bankb[bank]->maskb = 0;
+               gpio_bank_saved[bank].maskb = gpio_array[bank]->maskb;
+               gpio_array[bank]->maskb = 0;
 
                if (mask) {
 #if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY)
                        gpio_bank_saved[bank].fer   = *port_fer[bank];
 #endif
-                       gpio_bank_saved[bank].inen  = gpio_bankb[bank]->inen;
-                       gpio_bank_saved[bank].polar = gpio_bankb[bank]->polar;
-                       gpio_bank_saved[bank].dir   = gpio_bankb[bank]->dir;
-                       gpio_bank_saved[bank].edge  = gpio_bankb[bank]->edge;
-                       gpio_bank_saved[bank].both  = gpio_bankb[bank]->both;
+                       gpio_bank_saved[bank].inen  = gpio_array[bank]->inen;
+                       gpio_bank_saved[bank].polar = gpio_array[bank]->polar;
+                       gpio_bank_saved[bank].dir   = gpio_array[bank]->dir;
+                       gpio_bank_saved[bank].edge  = gpio_array[bank]->edge;
+                       gpio_bank_saved[bank].both  = gpio_array[bank]->both;
                        gpio_bank_saved[bank].reserved =
                                                reserved_gpio_map[bank];
 
@@ -700,7 +613,7 @@ u32 bfin_pm_standby_setup(void)
                        }
 
                        bfin_internal_set_wake(sic_iwr_irqs[bank], 1);
-                       gpio_bankb[bank]->maskb_set = wakeup_map[gpio_bank(i)];
+                       gpio_array[bank]->maskb_set = wakeup_map[gpio_bank(i)];
                }
        }
 
@@ -721,18 +634,18 @@ void bfin_pm_standby_restore(void)
 #if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY)
                        *port_fer[bank]         = gpio_bank_saved[bank].fer;
 #endif
-                       gpio_bankb[bank]->inen  = gpio_bank_saved[bank].inen;
-                       gpio_bankb[bank]->dir   = gpio_bank_saved[bank].dir;
-                       gpio_bankb[bank]->polar = gpio_bank_saved[bank].polar;
-                       gpio_bankb[bank]->edge  = gpio_bank_saved[bank].edge;
-                       gpio_bankb[bank]->both  = gpio_bank_saved[bank].both;
+                       gpio_array[bank]->inen  = gpio_bank_saved[bank].inen;
+                       gpio_array[bank]->dir   = gpio_bank_saved[bank].dir;
+                       gpio_array[bank]->polar = gpio_bank_saved[bank].polar;
+                       gpio_array[bank]->edge  = gpio_bank_saved[bank].edge;
+                       gpio_array[bank]->both  = gpio_bank_saved[bank].both;
 
                        reserved_gpio_map[bank] =
                                        gpio_bank_saved[bank].reserved;
                        bfin_internal_set_wake(sic_iwr_irqs[bank], 0);
                }
 
-               gpio_bankb[bank]->maskb = gpio_bank_saved[bank].maskb;
+               gpio_array[bank]->maskb = gpio_bank_saved[bank].maskb;
        }
        AWA_DUMMY_READ(maskb);
 }
@@ -745,21 +658,21 @@ void bfin_gpio_pm_hibernate_suspend(void)
                bank = gpio_bank(i);
 
 #if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY)
-                       gpio_bank_saved[bank].fer   = *port_fer[bank];
+               gpio_bank_saved[bank].fer = *port_fer[bank];
 #if defined(BF527_FAMILY) || defined(BF518_FAMILY)
-                       gpio_bank_saved[bank].mux   = *port_mux[bank];
+               gpio_bank_saved[bank].mux = *port_mux[bank];
 #else
-                       if (bank == 0)
-                               gpio_bank_saved[bank].mux   = bfin_read_PORT_MUX();
+               if (bank == 0)
+                       gpio_bank_saved[bank].mux = bfin_read_PORT_MUX();
 #endif
 #endif
-                       gpio_bank_saved[bank].data  = gpio_bankb[bank]->data;
-                       gpio_bank_saved[bank].inen  = gpio_bankb[bank]->inen;
-                       gpio_bank_saved[bank].polar = gpio_bankb[bank]->polar;
-                       gpio_bank_saved[bank].dir   = gpio_bankb[bank]->dir;
-                       gpio_bank_saved[bank].edge  = gpio_bankb[bank]->edge;
-                       gpio_bank_saved[bank].both  = gpio_bankb[bank]->both;
-                       gpio_bank_saved[bank].maska  = gpio_bankb[bank]->maska;
+               gpio_bank_saved[bank].data  = gpio_array[bank]->data;
+               gpio_bank_saved[bank].inen  = gpio_array[bank]->inen;
+               gpio_bank_saved[bank].polar = gpio_array[bank]->polar;
+               gpio_bank_saved[bank].dir   = gpio_array[bank]->dir;
+               gpio_bank_saved[bank].edge  = gpio_array[bank]->edge;
+               gpio_bank_saved[bank].both  = gpio_array[bank]->both;
+               gpio_bank_saved[bank].maska = gpio_array[bank]->maska;
        }
 
        AWA_DUMMY_READ(maska);
@@ -770,27 +683,27 @@ void bfin_gpio_pm_hibernate_restore(void)
        int i, bank;
 
        for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
-                       bank = gpio_bank(i);
+               bank = gpio_bank(i);
 
 #if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY)
 #if defined(BF527_FAMILY) || defined(BF518_FAMILY)
-                       *port_mux[bank] = gpio_bank_saved[bank].mux;
+               *port_mux[bank] = gpio_bank_saved[bank].mux;
 #else
-                       if (bank == 0)
-                               bfin_write_PORT_MUX(gpio_bank_saved[bank].mux);
+               if (bank == 0)
+                       bfin_write_PORT_MUX(gpio_bank_saved[bank].mux);
 #endif
-                       *port_fer[bank]         = gpio_bank_saved[bank].fer;
+               *port_fer[bank] = gpio_bank_saved[bank].fer;
 #endif
-                       gpio_bankb[bank]->inen  = gpio_bank_saved[bank].inen;
-                       gpio_bankb[bank]->dir   = gpio_bank_saved[bank].dir;
-                       gpio_bankb[bank]->polar = gpio_bank_saved[bank].polar;
-                       gpio_bankb[bank]->edge  = gpio_bank_saved[bank].edge;
-                       gpio_bankb[bank]->both  = gpio_bank_saved[bank].both;
+               gpio_array[bank]->inen  = gpio_bank_saved[bank].inen;
+               gpio_array[bank]->dir   = gpio_bank_saved[bank].dir;
+               gpio_array[bank]->polar = gpio_bank_saved[bank].polar;
+               gpio_array[bank]->edge  = gpio_bank_saved[bank].edge;
+               gpio_array[bank]->both  = gpio_bank_saved[bank].both;
 
-                       gpio_bankb[bank]->data_set = gpio_bank_saved[bank].data
-                                                       | gpio_bank_saved[bank].dir;
+               gpio_array[bank]->data_set = gpio_bank_saved[bank].data
+                                               | gpio_bank_saved[bank].dir;
 
-                       gpio_bankb[bank]->maska = gpio_bank_saved[bank].maska;
+               gpio_array[bank]->maska = gpio_bank_saved[bank].maska;
        }
        AWA_DUMMY_READ(maska);
 }
@@ -817,12 +730,12 @@ void bfin_gpio_pm_hibernate_suspend(void)
        for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
                bank = gpio_bank(i);
 
-                       gpio_bank_saved[bank].fer  = gpio_array[bank]->port_fer;
-                       gpio_bank_saved[bank].mux  = gpio_array[bank]->port_mux;
-                       gpio_bank_saved[bank].data  = gpio_array[bank]->port_data;
-                       gpio_bank_saved[bank].data  = gpio_array[bank]->port_data;
-                       gpio_bank_saved[bank].inen  = gpio_array[bank]->port_inen;
-                       gpio_bank_saved[bank].dir   = gpio_array[bank]->port_dir_set;
+               gpio_bank_saved[bank].fer = gpio_array[bank]->port_fer;
+               gpio_bank_saved[bank].mux = gpio_array[bank]->port_mux;
+               gpio_bank_saved[bank].data = gpio_array[bank]->data;
+               gpio_bank_saved[bank].data = gpio_array[bank]->data;
+               gpio_bank_saved[bank].inen = gpio_array[bank]->inen;
+               gpio_bank_saved[bank].dir = gpio_array[bank]->dir_set;
        }
 }
 
@@ -831,21 +744,21 @@ void bfin_gpio_pm_hibernate_restore(void)
        int i, bank;
 
        for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
-                       bank = gpio_bank(i);
-
-                       gpio_array[bank]->port_mux  = gpio_bank_saved[bank].mux;
-                       gpio_array[bank]->port_fer  = gpio_bank_saved[bank].fer;
-                       gpio_array[bank]->port_inen  = gpio_bank_saved[bank].inen;
-                       gpio_array[bank]->port_dir_set   = gpio_bank_saved[bank].dir;
-                       gpio_array[bank]->port_set = gpio_bank_saved[bank].data
-                                                       | gpio_bank_saved[bank].dir;
+               bank = gpio_bank(i);
+
+               gpio_array[bank]->port_mux = gpio_bank_saved[bank].mux;
+               gpio_array[bank]->port_fer = gpio_bank_saved[bank].fer;
+               gpio_array[bank]->inen = gpio_bank_saved[bank].inen;
+               gpio_array[bank]->dir_set = gpio_bank_saved[bank].dir;
+               gpio_array[bank]->data_set = gpio_bank_saved[bank].data
+                                               | gpio_bank_saved[bank].dir;
        }
 }
 #endif
 
 unsigned short get_gpio_dir(unsigned gpio)
 {
-       return (0x01 & (gpio_array[gpio_bank(gpio)]->port_dir_clear >> gpio_sub_n(gpio)));
+       return (0x01 & (gpio_array[gpio_bank(gpio)]->dir_clear >> gpio_sub_n(gpio)));
 }
 EXPORT_SYMBOL(get_gpio_dir);
 
@@ -905,9 +818,7 @@ int peripheral_request(unsigned short per, const char *label)
                 */
 
 #ifdef BF548_FAMILY
-               u16 funct = get_portmux(ident);
-
-               if (!((per & P_MAYSHARE) && (funct == P_FUNCT2MUX(per)))) {
+               if (!((per & P_MAYSHARE) && get_portmux(per) == P_FUNCT2MUX(per))) {
 #else
                if (!(per & P_MAYSHARE)) {
 #endif
@@ -931,11 +842,7 @@ int peripheral_request(unsigned short per, const char *label)
  anyway:
        reserved_peri_map[gpio_bank(ident)] |= gpio_bit(ident);
 
-#ifdef BF548_FAMILY
-       portmux_setup(ident, P_FUNCT2MUX(per));
-#else
-       portmux_setup(per, P_FUNCT2MUX(per));
-#endif
+       portmux_setup(per);
        port_setup(ident, PERIPHERAL_USAGE);
 
        local_irq_restore_hw(flags);
@@ -977,9 +884,6 @@ void peripheral_free(unsigned short per)
        if (!(per & P_DEFINED))
                return;
 
-       if (check_gpio(ident) < 0)
-               return;
-
        local_irq_save_hw(flags);
 
        if (unlikely(!(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident)))) {
@@ -1056,9 +960,15 @@ int bfin_gpio_request(unsigned gpio, const char *label)
                local_irq_restore_hw(flags);
                return -EBUSY;
        }
-       if (unlikely(reserved_gpio_irq_map[gpio_bank(gpio)] & gpio_bit(gpio)))
+       if (unlikely(reserved_gpio_irq_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
                printk(KERN_NOTICE "bfin-gpio: GPIO %d is already reserved as gpio-irq!"
                       " (Documentation/blackfin/bfin-gpio-notes.txt)\n", gpio);
+       }
+#ifndef BF548_FAMILY
+       else {  /* Reset POLAR setting when acquiring a gpio for the first time */
+               set_gpio_polar(gpio, 0);
+       }
+#endif
 
        reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio);
        set_label(gpio, label);
@@ -1078,6 +988,8 @@ void bfin_gpio_free(unsigned gpio)
        if (check_gpio(gpio) < 0)
                return;
 
+       might_sleep();
+
        local_irq_save_hw(flags);
 
        if (unlikely(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))) {
@@ -1158,8 +1070,16 @@ void bfin_gpio_irq_free(unsigned gpio)
        local_irq_restore_hw(flags);
 }
 
-
+static inline void __bfin_gpio_direction_input(unsigned gpio)
+{
 #ifdef BF548_FAMILY
+       gpio_array[gpio_bank(gpio)]->dir_clear = gpio_bit(gpio);
+#else
+       gpio_array[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio);
+#endif
+       gpio_array[gpio_bank(gpio)]->inen |= gpio_bit(gpio);
+}
+
 int bfin_gpio_direction_input(unsigned gpio)
 {
        unsigned long flags;
@@ -1170,125 +1090,85 @@ int bfin_gpio_direction_input(unsigned gpio)
        }
 
        local_irq_save_hw(flags);
-       gpio_array[gpio_bank(gpio)]->port_dir_clear = gpio_bit(gpio);
-       gpio_array[gpio_bank(gpio)]->port_inen |= gpio_bit(gpio);
+       __bfin_gpio_direction_input(gpio);
+       AWA_DUMMY_READ(inen);
        local_irq_restore_hw(flags);
 
        return 0;
 }
 EXPORT_SYMBOL(bfin_gpio_direction_input);
 
-int bfin_gpio_direction_output(unsigned gpio, int value)
+void bfin_gpio_irq_prepare(unsigned gpio)
 {
+#ifdef BF548_FAMILY
        unsigned long flags;
+#endif
 
-       if (!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
-               gpio_error(gpio);
-               return -EINVAL;
-       }
+       port_setup(gpio, GPIO_USAGE);
 
+#ifdef BF548_FAMILY
        local_irq_save_hw(flags);
-       gpio_array[gpio_bank(gpio)]->port_inen &= ~gpio_bit(gpio);
-       gpio_set_value(gpio, value);
-       gpio_array[gpio_bank(gpio)]->port_dir_set = gpio_bit(gpio);
+       __bfin_gpio_direction_input(gpio);
        local_irq_restore_hw(flags);
-
-       return 0;
+#endif
 }
-EXPORT_SYMBOL(bfin_gpio_direction_output);
 
 void bfin_gpio_set_value(unsigned gpio, int arg)
 {
        if (arg)
-               gpio_array[gpio_bank(gpio)]->port_set = gpio_bit(gpio);
+               gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio);
        else
-               gpio_array[gpio_bank(gpio)]->port_clear = gpio_bit(gpio);
+               gpio_array[gpio_bank(gpio)]->data_clear = gpio_bit(gpio);
 }
 EXPORT_SYMBOL(bfin_gpio_set_value);
 
-int bfin_gpio_get_value(unsigned gpio)
-{
-       return (1 & (gpio_array[gpio_bank(gpio)]->port_data >> gpio_sub_n(gpio)));
-}
-EXPORT_SYMBOL(bfin_gpio_get_value);
-
-void bfin_gpio_irq_prepare(unsigned gpio)
+int bfin_gpio_direction_output(unsigned gpio, int value)
 {
        unsigned long flags;
 
-       port_setup(gpio, GPIO_USAGE);
+       if (!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
+               gpio_error(gpio);
+               return -EINVAL;
+       }
 
        local_irq_save_hw(flags);
-       gpio_array[gpio_bank(gpio)]->port_dir_clear = gpio_bit(gpio);
-       gpio_array[gpio_bank(gpio)]->port_inen |= gpio_bit(gpio);
-       local_irq_restore_hw(flags);
-}
 
+       gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio);
+       gpio_set_value(gpio, value);
+#ifdef BF548_FAMILY
+       gpio_array[gpio_bank(gpio)]->dir_set = gpio_bit(gpio);
 #else
+       gpio_array[gpio_bank(gpio)]->dir |= gpio_bit(gpio);
+#endif
+
+       AWA_DUMMY_READ(dir);
+       local_irq_restore_hw(flags);
+
+       return 0;
+}
+EXPORT_SYMBOL(bfin_gpio_direction_output);
 
 int bfin_gpio_get_value(unsigned gpio)
 {
+#ifdef BF548_FAMILY
+       return (1 & (gpio_array[gpio_bank(gpio)]->data >> gpio_sub_n(gpio)));
+#else
        unsigned long flags;
-       int ret;
 
        if (unlikely(get_gpio_edge(gpio))) {
+               int ret;
                local_irq_save_hw(flags);
                set_gpio_edge(gpio, 0);
                ret = get_gpio_data(gpio);
                set_gpio_edge(gpio, 1);
                local_irq_restore_hw(flags);
-
                return ret;
        } else
                return get_gpio_data(gpio);
+#endif
 }
 EXPORT_SYMBOL(bfin_gpio_get_value);
 
-
-int bfin_gpio_direction_input(unsigned gpio)
-{
-       unsigned long flags;
-
-       if (!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
-               gpio_error(gpio);
-               return -EINVAL;
-       }
-
-       local_irq_save_hw(flags);
-       gpio_bankb[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio);
-       gpio_bankb[gpio_bank(gpio)]->inen |= gpio_bit(gpio);
-       AWA_DUMMY_READ(inen);
-       local_irq_restore_hw(flags);
-
-       return 0;
-}
-EXPORT_SYMBOL(bfin_gpio_direction_input);
-
-int bfin_gpio_direction_output(unsigned gpio, int value)
-{
-       unsigned long flags;
-
-       if (!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
-               gpio_error(gpio);
-               return -EINVAL;
-       }
-
-       local_irq_save_hw(flags);
-       gpio_bankb[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio);
-
-       if (value)
-               gpio_bankb[gpio_bank(gpio)]->data_set = gpio_bit(gpio);
-       else
-               gpio_bankb[gpio_bank(gpio)]->data_clear = gpio_bit(gpio);
-
-       gpio_bankb[gpio_bank(gpio)]->dir |= gpio_bit(gpio);
-       AWA_DUMMY_READ(dir);
-       local_irq_restore_hw(flags);
-
-       return 0;
-}
-EXPORT_SYMBOL(bfin_gpio_direction_output);
-
 /* If we are booting from SPI and our board lacks a strong enough pull up,
  * the core can reset and execute the bootrom faster than the resistor can
  * pull the signal logically high.  To work around this (common) error in
@@ -1299,23 +1179,15 @@ EXPORT_SYMBOL(bfin_gpio_direction_output);
  * lives here as we need to force all the GPIO states w/out going through
  * BUG() checks and such.
  */
-void bfin_gpio_reset_spi0_ssel1(void)
+void bfin_reset_boot_spi_cs(unsigned short pin)
 {
-       u16 gpio = P_IDENT(P_SPI0_SSEL1);
-
+       unsigned short gpio = P_IDENT(pin);
        port_setup(gpio, GPIO_USAGE);
-       gpio_bankb[gpio_bank(gpio)]->data_set = gpio_bit(gpio);
+       gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio);
        AWA_DUMMY_READ(data_set);
        udelay(1);
 }
 
-void bfin_gpio_irq_prepare(unsigned gpio)
-{
-       port_setup(gpio, GPIO_USAGE);
-}
-
-#endif /*BF548_FAMILY */
-
 #if defined(CONFIG_PROC_FS)
 static int gpio_proc_read(char *buf, char **start, off_t offset,
                          int len, int *unused_i, void *unused_v)
@@ -1369,11 +1241,7 @@ int bfin_gpiolib_get_value(struct gpio_chip *chip, unsigned gpio)
 
 void bfin_gpiolib_set_value(struct gpio_chip *chip, unsigned gpio, int value)
 {
-#ifdef BF548_FAMILY
        return bfin_gpio_set_value(gpio, value);
-#else
-       return set_gpio_data(gpio, value);
-#endif
 }
 
 int bfin_gpiolib_gpio_request(struct gpio_chip *chip, unsigned gpio)
index bdb9584..3e329a6 100644 (file)
@@ -63,10 +63,8 @@ void __init generate_cplb_tables_cpu(unsigned int cpu)
        dcplb_tbl[cpu][i_d].addr = 0;
        dcplb_tbl[cpu][i_d++].data = SDRAM_OOPS | PAGE_SIZE_1KB;
 
-#if 0
        icplb_tbl[cpu][i_i].addr = 0;
-       icplb_tbl[cpu][i_i++].data = i_cache | CPLB_USER_RD | PAGE_SIZE_4KB;
-#endif
+       icplb_tbl[cpu][i_i++].data = i_cache | CPLB_USER_RD | PAGE_SIZE_1KB;
 
        /* Cover kernel memory with 4M pages.  */
        addr = 0;
index 376249a..8cbb47c 100644 (file)
@@ -163,12 +163,14 @@ MGR_ATTR static int icplb_miss(int cpu)
                nr_icplb_supv_miss[cpu]++;
 
        base = 0;
-       for (idx = 0; idx < icplb_nr_bounds; idx++) {
+       idx = 0;
+       do {
                eaddr = icplb_bounds[idx].eaddr;
                if (addr < eaddr)
                        break;
                base = eaddr;
-       }
+       } while (++idx < icplb_nr_bounds);
+
        if (unlikely(idx == icplb_nr_bounds))
                return CPLB_NO_ADDR_MATCH;
 
@@ -208,12 +210,14 @@ MGR_ATTR static int dcplb_miss(int cpu)
                nr_dcplb_supv_miss[cpu]++;
 
        base = 0;
-       for (idx = 0; idx < dcplb_nr_bounds; idx++) {
+       idx = 0;
+       do {
                eaddr = dcplb_bounds[idx].eaddr;
                if (addr < eaddr)
                        break;
                base = eaddr;
-       }
+       } while (++idx < dcplb_nr_bounds);
+
        if (unlikely(idx == dcplb_nr_bounds))
                return CPLB_NO_ADDR_MATCH;
 
index ab8209c..75724ee 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <asm/trace.h>
+#include <asm/pda.h>
 
 static atomic_t irq_err_count;
 static spinlock_t irq_controller_lock;
@@ -91,8 +92,13 @@ int show_interrupts(struct seq_file *p, void *v)
                seq_putc(p, '\n');
  skip:
                spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-       } else if (i == NR_IRQS)
+       } else if (i == NR_IRQS) {
+               seq_printf(p, "NMI: ");
+               for_each_online_cpu(j)
+                       seq_printf(p, "%10u ", cpu_pda[j].__nmi_count);
+               seq_printf(p, "     CORE  Non Maskable Interrupt\n");
                seq_printf(p, "Err: %10u\n",  atomic_read(&irq_err_count));
+       }
        return 0;
 }
 
index eeee8cb..53d08de 100644 (file)
@@ -20,8 +20,8 @@
  * reset while the Core B bit (on dual core parts) is cleared by
  * the core reset.
  */
-__attribute__((l1_text))
-static void _bfin_reset(void)
+__attribute__ ((__l1_text__, __noreturn__))
+static void bfin_reset(void)
 {
        /* Wait for completion of "system" events such as cache line
         * line fills so that we avoid infinite stalls later on as
@@ -30,7 +30,11 @@ static void _bfin_reset(void)
         */
        __builtin_bfin_ssync();
 
-       while (1) {
+       /* The bootrom checks to see how it was reset and will
+        * automatically perform a software reset for us when
+        * it starts executing after the core reset.
+        */
+       if (ANOMALY_05000353 || ANOMALY_05000386) {
                /* Initiate System software reset. */
                bfin_write_SWRST(0x7);
 
@@ -50,6 +54,11 @@ static void _bfin_reset(void)
                /* Clear System software reset */
                bfin_write_SWRST(0);
 
+               /* The BF526 ROM will crash during reset */
+#if defined(__ADSPBF522__) || defined(__ADSPBF524__) || defined(__ADSPBF526__)
+               bfin_read_SWRST();
+#endif
+
                /* Wait for the SWRST write to complete.  Cannot rely on SSYNC
                 * though as the System state is all reset now.
                 */
@@ -60,22 +69,11 @@ static void _bfin_reset(void)
                        : "a" (15 * 1)
                        : "LC1", "LB1", "LT1"
                );
+       }
 
+       while (1)
                /* Issue core reset */
                asm("raise 1");
-       }
-}
-
-static void bfin_reset(void)
-{
-       if (ANOMALY_05000353 || ANOMALY_05000386)
-               _bfin_reset();
-       else
-               /* the bootrom checks to see how it was reset and will
-                * automatically perform a software reset for us when
-                * it starts executing boot
-                */
-               asm("raise 1;");
 }
 
 __attribute__((weak))
index b2a8113..e5c1162 100644 (file)
@@ -60,7 +60,7 @@ void __initdata *init_retx, *init_saved_retx, *init_saved_seqstat,
 #define BFIN_MEMMAP_MAX                128 /* number of entries in bfin_memmap */
 #define BFIN_MEMMAP_RAM                1
 #define BFIN_MEMMAP_RESERVED   2
-struct bfin_memmap {
+static struct bfin_memmap {
        int nr_map;
        struct bfin_memmap_entry {
                unsigned long long addr; /* start of memory segment */
@@ -824,7 +824,15 @@ void __init setup_arch(char **cmdline_p)
        flash_probe();
 #endif
 
+       printk(KERN_INFO "Boot Mode: %i\n", bfin_read_SYSCR() & 0xF);
+
+       /* Newer parts mirror SWRST bits in SYSCR */
+#if defined(CONFIG_BF53x) || defined(CONFIG_BF561) || \
+    defined(CONFIG_BF538) || defined(CONFIG_BF539)
        _bfin_swrst = bfin_read_SWRST();
+#else
+       _bfin_swrst = bfin_read_SYSCR();
+#endif
 
 #ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT
        bfin_write_SWRST(_bfin_swrst & ~DOUBLE_FAULT);
@@ -853,7 +861,7 @@ void __init setup_arch(char **cmdline_p)
        else if (_bfin_swrst & RESET_SOFTWARE)
                printk(KERN_NOTICE "Reset caused by Software reset\n");
 
-       printk(KERN_INFO "Blackfin support (C) 2004-2008 Analog Devices, Inc.\n");
+       printk(KERN_INFO "Blackfin support (C) 2004-2009 Analog Devices, Inc.\n");
        if (bfin_compiled_revid() == 0xffff)
                printk(KERN_INFO "Compiled for ADSP-%s Rev any\n", CPU);
        else if (bfin_compiled_revid() == -1)
index 5b0667d..ffe7fb5 100644 (file)
@@ -673,6 +673,14 @@ static void decode_instruction(unsigned short *address)
                        verbose_printk("RTI");
                else if (opcode == 0x0012)
                        verbose_printk("RTX");
+               else if (opcode == 0x0013)
+                       verbose_printk("RTN");
+               else if (opcode == 0x0014)
+                       verbose_printk("RTE");
+               else if (opcode == 0x0025)
+                       verbose_printk("EMUEXCPT");
+               else if (opcode == 0x0040 && opcode <= 0x0047)
+                       verbose_printk("STI R%i", opcode & 7);
                else if (opcode >= 0x0050 && opcode <= 0x0057)
                        verbose_printk("JUMP (P%i)", opcode & 7);
                else if (opcode >= 0x0060 && opcode <= 0x0067)
@@ -681,6 +689,10 @@ static void decode_instruction(unsigned short *address)
                        verbose_printk("CALL (PC+P%i)", opcode & 7);
                else if (opcode >= 0x0080 && opcode <= 0x0087)
                        verbose_printk("JUMP (PC+P%i)", opcode & 7);
+               else if (opcode >= 0x0090 && opcode <= 0x009F)
+                       verbose_printk("RAISE 0x%x", opcode & 0xF);
+               else if (opcode >= 0x00A0 && opcode <= 0x00AF)
+                       verbose_printk("EXCPT 0x%x", opcode & 0xF);
                else if ((opcode >= 0x1000 && opcode <= 0x13FF) || (opcode >= 0x1800 && opcode <= 0x1BFF))
                        verbose_printk("IF !CC JUMP");
                else if ((opcode >= 0x1400 && opcode <= 0x17ff) || (opcode >= 0x1c00 && opcode <= 0x1fff))
@@ -820,11 +832,8 @@ void show_stack(struct task_struct *task, unsigned long *stack)
        decode_address(buf, (unsigned int)stack);
        printk(KERN_NOTICE " SP: [0x%p] %s\n", stack, buf);
 
-       addr = (unsigned int *)((unsigned int)stack & ~0x3F);
-
        /* First thing is to look for a frame pointer */
-       for (addr = (unsigned int *)((unsigned int)stack & ~0xF), i = 0;
-               addr < endstack; addr++, i++) {
+       for (addr = (unsigned int *)((unsigned int)stack & ~0xF); addr < endstack; addr++) {
                if (*addr & 0x1)
                        continue;
                ins_addr = (unsigned short *)*addr;
@@ -834,7 +843,8 @@ void show_stack(struct task_struct *task, unsigned long *stack)
 
                if (fp) {
                        /* Let's check to see if it is a frame pointer */
-                       while (fp >= (addr - 1) && fp < endstack && fp)
+                       while (fp >= (addr - 1) && fp < endstack
+                              && fp && ((unsigned int) fp & 0x3) == 0)
                                fp = (unsigned int *)*fp;
                        if (fp == 0 || fp == endstack) {
                                fp = addr - 1;
@@ -1052,8 +1062,9 @@ void show_regs(struct pt_regs *fp)
        char buf [150];
        struct irqaction *action;
        unsigned int i;
-       unsigned long flags;
+       unsigned long flags = 0;
        unsigned int cpu = smp_processor_id();
+       unsigned char in_atomic = (bfin_read_IPEND() & 0x10) || in_atomic();
 
        verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\t\t%s\n", print_tainted());
        verbose_printk(KERN_NOTICE " SEQSTAT: %08lx  IPEND: %04lx  SYSCFG: %04lx\n",
@@ -1073,17 +1084,22 @@ void show_regs(struct pt_regs *fp)
        }
        verbose_printk(KERN_NOTICE "  EXCAUSE   : 0x%lx\n",
                fp->seqstat & SEQSTAT_EXCAUSE);
-       for (i = 6; i <= 15 ; i++) {
+       for (i = 2; i <= 15 ; i++) {
                if (fp->ipend & (1 << i)) {
-                       decode_address(buf, bfin_read32(EVT0 + 4*i));
-                       verbose_printk(KERN_NOTICE "  physical IVG%i asserted : %s\n", i, buf);
+                       if (i != 4) {
+                               decode_address(buf, bfin_read32(EVT0 + 4*i));
+                               verbose_printk(KERN_NOTICE "  physical IVG%i asserted : %s\n", i, buf);
+                       } else
+                               verbose_printk(KERN_NOTICE "  interrupts disabled\n");
                }
        }
 
        /* if no interrupts are going off, don't print this out */
        if (fp->ipend & ~0x3F) {
                for (i = 0; i < (NR_IRQS - 1); i++) {
-                       spin_lock_irqsave(&irq_desc[i].lock, flags);
+                       if (!in_atomic)
+                               spin_lock_irqsave(&irq_desc[i].lock, flags);
+
                        action = irq_desc[i].action;
                        if (!action)
                                goto unlock;
@@ -1096,7 +1112,8 @@ void show_regs(struct pt_regs *fp)
                        }
                        verbose_printk("\n");
 unlock:
-                       spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+                       if (!in_atomic)
+                               spin_unlock_irqrestore(&irq_desc[i].lock, flags);
                }
        }
 
index 15f1351..0e17534 100644 (file)
@@ -46,6 +46,7 @@
 #include <asm/dpmc.h>
 #include <asm/bfin_sdh.h>
 #include <linux/spi/ad7877.h>
+#include <net/dsa.h>
 
 /*
  * Name the Board for the /proc/cpuinfo
@@ -104,8 +105,31 @@ static struct platform_device rtc_device = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+static struct platform_device bfin_mii_bus = {
+       .name = "bfin_mii_bus",
+};
+
 static struct platform_device bfin_mac_device = {
        .name = "bfin_mac",
+       .dev.platform_data = &bfin_mii_bus,
+};
+#endif
+
+#if defined(CONFIG_NET_DSA_KSZ8893M) || defined(CONFIG_NET_DSA_KSZ8893M_MODULE)
+static struct dsa_platform_data ksz8893m_switch_data = {
+       .mii_bus = &bfin_mii_bus.dev,
+       .netdev = &bfin_mac_device.dev,
+       .port_names[0]  = NULL,
+       .port_names[1]  = "eth%d",
+       .port_names[2]  = "eth%d",
+       .port_names[3]  = "cpu",
+};
+
+static struct platform_device ksz8893m_switch_device = {
+       .name           = "dsa",
+       .id             = 0,
+       .num_resources  = 0,
+       .dev.platform_data = &ksz8893m_switch_data,
 };
 #endif
 
@@ -147,6 +171,15 @@ static struct bfin5xx_spi_chip spi_adc_chip_info = {
 };
 #endif
 
+#if defined(CONFIG_NET_DSA_KSZ8893M) \
+       || defined(CONFIG_NET_DSA_KSZ8893M_MODULE)
+/* SPI SWITCH CHIP */
+static struct bfin5xx_spi_chip spi_switch_info = {
+       .enable_dma = 0,
+       .bits_per_word = 8,
+};
+#endif
+
 #if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
 static struct bfin5xx_spi_chip spi_mmc_chip_info = {
        .enable_dma = 1,
@@ -226,6 +259,19 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
        },
 #endif
 
+#if defined(CONFIG_NET_DSA_KSZ8893M) \
+       || defined(CONFIG_NET_DSA_KSZ8893M_MODULE)
+       {
+               .modalias = "ksz8893m",
+               .max_speed_hz = 5000000,
+               .bus_num = 0,
+               .chip_select = 1,
+               .platform_data = NULL,
+               .controller_data = &spi_switch_info,
+               .mode = SPI_MODE_3,
+       },
+#endif
+
 #if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
        {
                .modalias = "spi_mmc_dummy",
@@ -473,7 +519,6 @@ static struct platform_device i2c_bfin_twi_device = {
 };
 #endif
 
-#ifdef CONFIG_I2C_BOARDINFO
 static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
 #if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
        {
@@ -487,7 +532,6 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
        },
 #endif
 };
-#endif
 
 #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
 static struct platform_device bfin_sport0_uart_device = {
@@ -584,9 +628,14 @@ static struct platform_device *stamp_devices[] __initdata = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+       &bfin_mii_bus,
        &bfin_mac_device,
 #endif
 
+#if defined(CONFIG_NET_DSA_KSZ8893M) || defined(CONFIG_NET_DSA_KSZ8893M_MODULE)
+       &ksz8893m_switch_device,
+#endif
+
 #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
        &bfin_spi0_device,
        &bfin_spi1_device,
@@ -632,12 +681,8 @@ static struct platform_device *stamp_devices[] __initdata = {
 static int __init ezbrd_init(void)
 {
        printk(KERN_INFO "%s(): registering device resources\n", __func__);
-
-#ifdef CONFIG_I2C_BOARDINFO
        i2c_register_board_info(0, bfin_i2c_board_info,
                                ARRAY_SIZE(bfin_i2c_board_info));
-#endif
-
        platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
        spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
        return 0;
@@ -649,7 +694,7 @@ void native_machine_restart(char *cmd)
 {
        /* workaround reboot hang when booting from SPI */
        if ((bfin_read_SYSCR() & 0x7) == 0x3)
-               bfin_gpio_reset_spi0_ssel1();
+               bfin_reset_boot_spi_cs(P_DEFAULT_BOOT_SPI_CS);
 }
 
 void bfin_get_ether_addr(char *addr)
index ac16d54..f618b48 100644 (file)
 #define P_SPI1_SSEL4   (P_DEFINED | P_IDENT(GPIO_PF8) | P_FUNCT(2))
 #define P_SPI1_SSEL5   (P_DEFINED | P_IDENT(GPIO_PG11) | P_FUNCT(2))
 
+#define P_DEFAULT_BOOT_SPI_CS P_SPI0_SSEL2
+
 /* SPORT Port Mux */
 #define P_SPORT0_DRPRI (P_DEFINED | P_IDENT(GPIO_PG3) | P_FUNCT(0))
 #define P_SPORT0_RSCLK (P_DEFINED | P_IDENT(GPIO_PG4) | P_FUNCT(0))
index a2c3578..856c097 100644 (file)
@@ -403,8 +403,13 @@ static struct platform_device isp1362_hcd_device = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+static struct platform_device bfin_mii_bus = {
+       .name = "bfin_mii_bus",
+};
+
 static struct platform_device bfin_mac_device = {
        .name = "bfin_mac",
+       .dev.platform_data = &bfin_mii_bus,
 };
 #endif
 
@@ -793,7 +798,6 @@ static struct platform_device i2c_bfin_twi_device = {
 };
 #endif
 
-#ifdef CONFIG_I2C_BOARDINFO
 static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
 #if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
        {
@@ -809,7 +813,6 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
        },
 #endif
 };
-#endif
 
 #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
 static struct platform_device bfin_sport0_uart_device = {
@@ -920,6 +923,7 @@ static struct platform_device *stamp_devices[] __initdata = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+       &bfin_mii_bus,
        &bfin_mac_device,
 #endif
 
@@ -968,27 +972,23 @@ static struct platform_device *stamp_devices[] __initdata = {
        &bfin_gpios_device,
 };
 
-static int __init stamp_init(void)
+static int __init cm_init(void)
 {
        printk(KERN_INFO "%s(): registering device resources\n", __func__);
-
-#ifdef CONFIG_I2C_BOARDINFO
        i2c_register_board_info(0, bfin_i2c_board_info,
                                ARRAY_SIZE(bfin_i2c_board_info));
-#endif
-
        platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
        spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
        return 0;
 }
 
-arch_initcall(stamp_init);
+arch_initcall(cm_init);
 
 void native_machine_restart(char *cmd)
 {
        /* workaround reboot hang when booting from SPI */
        if ((bfin_read_SYSCR() & 0x7) == 0x3)
-               bfin_gpio_reset_spi0_ssel1();
+               bfin_reset_boot_spi_cs(P_DEFAULT_BOOT_SPI_CS);
 }
 
 void bfin_get_ether_addr(char *addr)
index 0314bd3..83606fc 100644 (file)
@@ -208,8 +208,13 @@ static struct platform_device rtc_device = {
 
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+static struct platform_device bfin_mii_bus = {
+       .name = "bfin_mii_bus",
+};
+
 static struct platform_device bfin_mac_device = {
        .name = "bfin_mac",
+       .dev.platform_data = &bfin_mii_bus,
 };
 #endif
 
@@ -590,7 +595,6 @@ static struct platform_device i2c_bfin_twi_device = {
 };
 #endif
 
-#ifdef CONFIG_I2C_BOARDINFO
 static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
 #if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
        {
@@ -604,7 +608,6 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
        },
 #endif
 };
-#endif
 
 #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
 static struct platform_device bfin_sport0_uart_device = {
@@ -720,6 +723,7 @@ static struct platform_device *stamp_devices[] __initdata = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+       &bfin_mii_bus,
        &bfin_mac_device,
 #endif
 
@@ -764,27 +768,23 @@ static struct platform_device *stamp_devices[] __initdata = {
        &bfin_gpios_device,
 };
 
-static int __init stamp_init(void)
+static int __init ezbrd_init(void)
 {
        printk(KERN_INFO "%s(): registering device resources\n", __func__);
-
-#ifdef CONFIG_I2C_BOARDINFO
        i2c_register_board_info(0, bfin_i2c_board_info,
                                ARRAY_SIZE(bfin_i2c_board_info));
-#endif
-
        platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
        spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
        return 0;
 }
 
-arch_initcall(stamp_init);
+arch_initcall(ezbrd_init);
 
 void native_machine_restart(char *cmd)
 {
        /* workaround reboot hang when booting from SPI */
        if ((bfin_read_SYSCR() & 0x7) == 0x3)
-               bfin_gpio_reset_spi0_ssel1();
+               bfin_reset_boot_spi_cs(P_DEFAULT_BOOT_SPI_CS);
 }
 
 void bfin_get_ether_addr(char *addr)
index 9454fb7..d086411 100644 (file)
@@ -425,8 +425,13 @@ static struct platform_device isp1362_hcd_device = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+static struct platform_device bfin_mii_bus = {
+       .name = "bfin_mii_bus",
+};
+
 static struct platform_device bfin_mac_device = {
        .name = "bfin_mac",
+       .dev.platform_data = &bfin_mii_bus,
 };
 #endif
 
@@ -830,7 +835,6 @@ static struct platform_device i2c_bfin_twi_device = {
 };
 #endif
 
-#ifdef CONFIG_I2C_BOARDINFO
 static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
 #if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
        {
@@ -844,7 +848,6 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
        },
 #endif
 };
-#endif
 
 #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
 static struct platform_device bfin_sport0_uart_device = {
@@ -988,6 +991,7 @@ static struct platform_device *stamp_devices[] __initdata = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+       &bfin_mii_bus,
        &bfin_mac_device,
 #endif
 
@@ -1048,27 +1052,23 @@ static struct platform_device *stamp_devices[] __initdata = {
        &bfin_gpios_device,
 };
 
-static int __init stamp_init(void)
+static int __init ezkit_init(void)
 {
        printk(KERN_INFO "%s(): registering device resources\n", __func__);
-
-#ifdef CONFIG_I2C_BOARDINFO
        i2c_register_board_info(0, bfin_i2c_board_info,
                                ARRAY_SIZE(bfin_i2c_board_info));
-#endif
-
        platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
        spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
        return 0;
 }
 
-arch_initcall(stamp_init);
+arch_initcall(ezkit_init);
 
 void native_machine_restart(char *cmd)
 {
        /* workaround reboot hang when booting from SPI */
        if ((bfin_read_SYSCR() & 0x7) == 0x3)
-               bfin_gpio_reset_spi0_ssel1();
+               bfin_reset_boot_spi_cs(P_DEFAULT_BOOT_SPI_CS);
 }
 
 void bfin_get_ether_addr(char *addr)
index 7f6da2c..72b1652 100644 (file)
@@ -73,6 +73,8 @@
 
 #define P_HWAIT                (P_DONTCARE)
 
+#define P_DEFAULT_BOOT_SPI_CS P_SPI0_SSEL1
+
 #define P_SPI0_SS      (P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(0))
 #define P_SPI0_SSEL1   (P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(2))
 #define P_SPI0_SCK     (P_DEFINED | P_IDENT(GPIO_PG2) | P_FUNCT(2))
index 6ee607c..015c18f 100644 (file)
@@ -309,10 +309,8 @@ static struct platform_device i2c_gpio_device = {
 };
 #endif
 
-#ifdef CONFIG_I2C_BOARDINFO
 static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
 };
-#endif
 
 static const unsigned int cclk_vlev_datasheet[] =
 {
@@ -390,10 +388,8 @@ static int __init blackstamp_init(void)
 
        printk(KERN_INFO "%s(): registering device resources\n", __func__);
 
-#ifdef CONFIG_I2C_BOARDINFO
        i2c_register_board_info(0, bfin_i2c_board_info,
                                ARRAY_SIZE(bfin_i2c_board_info));
-#endif
 
        ret = platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
        if (ret < 0)
index 07f9ad1..db96f33 100644 (file)
@@ -441,7 +441,6 @@ static struct platform_device i2c_gpio_device = {
 };
 #endif
 
-#ifdef CONFIG_I2C_BOARDINFO
 static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
 #if defined(CONFIG_JOYSTICK_AD7142) || defined(CONFIG_JOYSTICK_AD7142_MODULE)
        {
@@ -461,7 +460,6 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
        },
 #endif
 };
-#endif
 
 static const unsigned int cclk_vlev_datasheet[] =
 {
@@ -550,10 +548,8 @@ static int __init stamp_init(void)
 
        printk(KERN_INFO "%s(): registering device resources\n", __func__);
 
-#ifdef CONFIG_I2C_BOARDINFO
        i2c_register_board_info(0, bfin_i2c_board_info,
                                ARRAY_SIZE(bfin_i2c_board_info));
-#endif
 
        ret = platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
        if (ret < 0)
index 685a265..2f59ce0 100644 (file)
 #define P_SPI0_SSEL2   (P_DEFINED | P_IDENT(GPIO_PF2))
 #define P_SPI0_SSEL1   (P_DEFINED | P_IDENT(GPIO_PF1))
 #define P_SPI0_SS      (P_DEFINED | P_IDENT(GPIO_PF0))
+#define P_DEFAULT_BOOT_SPI_CS P_SPI0_SSEL2
 
 #define P_TMR2         (P_DONTCARE)
 #define P_TMR1         (P_DONTCARE)
 #define P_TMR0         (P_DONTCARE)
 #define P_TMRCLK       (P_DEFINED | P_IDENT(GPIO_PF1))
 
-
-
-
-
 #endif /* _MACH_PORTMUX_H_ */
index 6ac8e4d..9cd8fb2 100644 (file)
@@ -479,8 +479,13 @@ static struct platform_device bfin_sport1_uart_device = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+static struct platform_device bfin_mii_bus = {
+       .name = "bfin_mii_bus",
+};
+
 static struct platform_device bfin_mac_device = {
        .name = "bfin_mac",
+       .dev.platform_data = &bfin_mii_bus,
 };
 #endif
 
@@ -591,6 +596,7 @@ static struct platform_device *cm_bf537_devices[] __initdata = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+       &bfin_mii_bus,
        &bfin_mac_device,
 #endif
 
index dd6e6bf..da710fd 100644 (file)
@@ -262,8 +262,13 @@ static struct platform_device isp1362_hcd_device = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+static struct platform_device bfin_mii_bus = {
+       .name = "bfin_mii_bus",
+};
+
 static struct platform_device bfin_mac_device = {
        .name = "bfin_mac",
+       .dev.platform_data = &bfin_mii_bus,
 };
 #endif
 
@@ -662,6 +667,7 @@ static struct platform_device *stamp_devices[] __initdata = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+       &bfin_mii_bus,
        &bfin_mac_device,
 #endif
 
@@ -708,7 +714,7 @@ static struct platform_device *stamp_devices[] __initdata = {
 #endif
 };
 
-static int __init stamp_init(void)
+static int __init generic_init(void)
 {
        printk(KERN_INFO "%s(): registering device resources\n", __func__);
        platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
@@ -720,13 +726,13 @@ static int __init stamp_init(void)
        return 0;
 }
 
-arch_initcall(stamp_init);
+arch_initcall(generic_init);
 
 void native_machine_restart(char *cmd)
 {
        /* workaround reboot hang when booting from SPI */
        if ((bfin_read_SYSCR() & 0x7) == 0x3)
-               bfin_gpio_reset_spi0_ssel1();
+               bfin_reset_boot_spi_cs(P_DEFAULT_BOOT_SPI_CS);
 }
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
index bb79534..db7d3a3 100644 (file)
@@ -61,8 +61,13 @@ static struct platform_device rtc_device = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+static struct platform_device bfin_mii_bus = {
+       .name = "bfin_mii_bus",
+};
+
 static struct platform_device bfin_mac_device = {
        .name = "bfin_mac",
+       .dev.platform_data = &bfin_mii_bus,
 };
 #endif
 
@@ -324,6 +329,7 @@ static struct platform_device *minotaur_devices[] __initdata = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+       &bfin_mii_bus,
        &bfin_mac_device,
 #endif
 
@@ -377,5 +383,5 @@ void native_machine_restart(char *cmd)
 {
        /* workaround reboot hang when booting from SPI */
        if ((bfin_read_SYSCR() & 0x7) == 0x3)
-               bfin_gpio_reset_spi0_ssel1();
+               bfin_reset_boot_spi_cs(P_DEFAULT_BOOT_SPI_CS);
 }
index 89de94f..590eb3a 100644 (file)
@@ -198,8 +198,13 @@ static struct platform_device isp1362_hcd_device = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+static struct platform_device bfin_mii_bus = {
+       .name = "bfin_mii_bus",
+};
+
 static struct platform_device bfin_mac_device = {
        .name = "bfin_mac",
+       .dev.platform_data = &bfin_mii_bus,
 };
 #endif
 
@@ -529,6 +534,7 @@ static struct platform_device *stamp_devices[] __initdata = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+       &bfin_mii_bus,
        &bfin_mac_device,
 #endif
 
@@ -558,7 +564,7 @@ static struct platform_device *stamp_devices[] __initdata = {
 #endif
 };
 
-static int __init stamp_init(void)
+static int __init pnav_init(void)
 {
        printk(KERN_INFO "%s(): registering device resources\n", __func__);
        platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
@@ -569,7 +575,7 @@ static int __init stamp_init(void)
        return 0;
 }
 
-arch_initcall(stamp_init);
+arch_initcall(pnav_init);
 
 void bfin_get_ether_addr(char *addr)
 {
index d812e25..cd04c5e 100644 (file)
@@ -321,8 +321,13 @@ static struct platform_device isp1362_hcd_device = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+static struct platform_device bfin_mii_bus = {
+       .name = "bfin_mii_bus",
+};
+
 static struct platform_device bfin_mac_device = {
        .name = "bfin_mac",
+       .dev.platform_data = &bfin_mii_bus,
 };
 #endif
 
@@ -1068,7 +1073,6 @@ static struct adp5588_kpad_platform_data adp5588_kpad_data = {
 };
 #endif
 
-#ifdef CONFIG_I2C_BOARDINFO
 static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
 #if defined(CONFIG_JOYSTICK_AD7142) || defined(CONFIG_JOYSTICK_AD7142_MODULE)
        {
@@ -1102,7 +1106,6 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
        },
 #endif
 };
-#endif
 
 #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
 static struct platform_device bfin_sport0_uart_device = {
@@ -1217,6 +1220,7 @@ static struct platform_device *stamp_devices[] __initdata = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+       &bfin_mii_bus,
        &bfin_mac_device,
 #endif
 
@@ -1284,12 +1288,8 @@ static struct platform_device *stamp_devices[] __initdata = {
 static int __init stamp_init(void)
 {
        printk(KERN_INFO "%s(): registering device resources\n", __func__);
-
-#ifdef CONFIG_I2C_BOARDINFO
        i2c_register_board_info(0, bfin_i2c_board_info,
                                ARRAY_SIZE(bfin_i2c_board_info));
-#endif
-
        bfin_plat_nand_init();
        platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
        spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
@@ -1307,7 +1307,7 @@ void native_machine_restart(char *cmd)
 {
        /* workaround reboot hang when booting from SPI */
        if ((bfin_read_SYSCR() & 0x7) == 0x3)
-               bfin_gpio_reset_spi0_ssel1();
+               bfin_reset_boot_spi_cs(P_DEFAULT_BOOT_SPI_CS);
 }
 
 /*
index 2f4b066..3f4f203 100644 (file)
@@ -481,8 +481,13 @@ static struct platform_device bfin_sport1_uart_device = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+static struct platform_device bfin_mii_bus = {
+       .name = "bfin_mii_bus",
+};
+
 static struct platform_device bfin_mac_device = {
        .name = "bfin_mac",
+       .dev.platform_data = &bfin_mii_bus,
 };
 #endif
 
@@ -593,6 +598,7 @@ static struct platform_device *cm_bf537_devices[] __initdata = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+       &bfin_mii_bus,
        &bfin_mac_device,
 #endif
 
@@ -615,7 +621,7 @@ static struct platform_device *cm_bf537_devices[] __initdata = {
        &bfin_gpios_device,
 };
 
-static int __init cm_bf537_init(void)
+static int __init tcm_bf537_init(void)
 {
        printk(KERN_INFO "%s(): registering device resources\n", __func__);
        platform_add_devices(cm_bf537_devices, ARRAY_SIZE(cm_bf537_devices));
@@ -629,7 +635,7 @@ static int __init cm_bf537_init(void)
        return 0;
 }
 
-arch_initcall(cm_bf537_init);
+arch_initcall(tcm_bf537_init);
 
 void bfin_get_ether_addr(char *addr)
 {
index 78fee6e..87285e7 100644 (file)
@@ -31,6 +31,7 @@
 #define P_PPI0_FS1     (P_DEFINED | P_IDENT(GPIO_PF9) | P_FUNCT(1))
 #define P_TACLK0       (P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(1))
 #define P_TMRCLK       (P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(1))
+#define P_DEFAULT_BOOT_SPI_CS P_SPI0_SSEL1
 
 #define P_PPI0_D0      (P_DEFINED | P_IDENT(GPIO_PG0) | P_FUNCT(0))
 #define P_PPI0_D1      (P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(0))
index 1e031b5..c8db264 100644 (file)
 #define P_SPI0_SSEL2   (P_DEFINED | P_IDENT(GPIO_PF2))
 #define P_SPI0_SSEL1   (P_DEFINED | P_IDENT(GPIO_PF1))
 #define P_SPI0_SS      (P_DEFINED | P_IDENT(GPIO_PF0))
+#define P_DEFAULT_BOOT_SPI_CS P_SPI0_SSEL2
 
 #endif /* _MACH_PORTMUX_H_ */
index 309c160..096e661 100644 (file)
@@ -781,7 +781,6 @@ static struct platform_device i2c_bfin_twi1_device = {
 #endif
 #endif
 
-#ifdef CONFIG_I2C_BOARDINFO
 static struct i2c_board_info __initdata bfin_i2c_board_info0[] = {
 };
 
@@ -800,7 +799,6 @@ static struct i2c_board_info __initdata bfin_i2c_board_info1[] = {
 #endif
 };
 #endif
-#endif
 
 #if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
 #include <linux/gpio_keys.h>
@@ -956,13 +954,11 @@ static int __init ezkit_init(void)
 {
        printk(KERN_INFO "%s(): registering device resources\n", __func__);
 
-#ifdef CONFIG_I2C_BOARDINFO
        i2c_register_board_info(0, bfin_i2c_board_info0,
                                ARRAY_SIZE(bfin_i2c_board_info0));
 #if !defined(CONFIG_BF542)     /* The BF542 only has 1 TWI */
        i2c_register_board_info(1, bfin_i2c_board_info1,
                                ARRAY_SIZE(bfin_i2c_board_info1));
-#endif
 #endif
 
        platform_add_devices(ezkit_devices, ARRAY_SIZE(ezkit_devices));
index 3b54309..23d03c5 100644 (file)
 #define ANOMALY_05000311 (0)
 #define ANOMALY_05000323 (0)
 #define ANOMALY_05000363 (0)
+#define ANOMALY_05000380 (0)
 #define ANOMALY_05000412 (0)
 #define ANOMALY_05000432 (0)
 #define ANOMALY_05000435 (0)
index f0e5699..cd31f72 100644 (file)
 
 #define AMGCTLVAL      (V_AMBEN | V_AMCKEN)
 
+#if defined(CONFIG_BF542M)
+# define CONFIG_BF542
+#elif defined(CONFIG_BF544M)
+# define CONFIG_BF544
+#elif defined(CONFIG_BF547M)
+# define CONFIG_BF547
+#elif defined(CONFIG_BF548M)
+# define CONFIG_BF548
+#elif defined(CONFIG_BF549M)
+# define CONFIG_BF549
+#endif
+
 #if defined(CONFIG_BF542)
 # define CPU   "BF542"
 # define CPUID 0x27de
index bba82dc..3a20517 100644 (file)
 struct gpio_port_t {
        unsigned short port_fer;
        unsigned short dummy1;
-       unsigned short port_data;
+       unsigned short data;
        unsigned short dummy2;
-       unsigned short port_set;
+       unsigned short data_set;
        unsigned short dummy3;
-       unsigned short port_clear;
+       unsigned short data_clear;
        unsigned short dummy4;
-       unsigned short port_dir_set;
+       unsigned short dir_set;
        unsigned short dummy5;
-       unsigned short port_dir_clear;
+       unsigned short dir_clear;
        unsigned short dummy6;
-       unsigned short port_inen;
+       unsigned short inen;
        unsigned short dummy7;
        unsigned int port_mux;
 };
index 8177a56..ffb1d0a 100644 (file)
 #define P_KEY_COL2     (P_DEFINED | P_IDENT(GPIO_PD14) | P_FUNCT(3))
 #define P_KEY_COL3     (P_DEFINED | P_IDENT(GPIO_PD15) | P_FUNCT(3))
 
+#define P_DEFAULT_BOOT_SPI_CS P_SPI0_SSEL1
 #define P_SPI0_SCK     (P_DEFINED | P_IDENT(GPIO_PE0) | P_FUNCT(0))
 #define P_SPI0_MISO    (P_DEFINED | P_IDENT(GPIO_PE1) | P_FUNCT(0))
 #define P_SPI0_MOSI    (P_DEFINED | P_IDENT(GPIO_PE2) | P_FUNCT(0))
index d7c5097..cf92229 100644 (file)
 #define DLEN_8              0x0        /* PPI Data Length mask for DLEN=8 */
 #define DLEN(x)        (((x-9) & 0x07) << 11)  /* PPI Data Length (only works for x=10-->x=16) */
 #define POL                  0x0000C000        /* PPI Signal Polarities       */
+#define        POLC            0x4000          /* PPI Clock Polarity */
+#define        POLS            0x8000          /* PPI Frame Sync Polarity */
 
 /* PPI_STATUS Masks */
 #define FLD                 0x00000400 /* Field Indicator   */
index a6ee820..2e5ad63 100644 (file)
@@ -85,5 +85,6 @@
 #define P_SPI0_MOSI    (P_DONTCARE)
 #define P_SPI0_MISO    (P_DONTCARE)
 #define P_SPI0_SCK     (P_DONTCARE)
+#define P_DEFAULT_BOOT_SPI_CS P_SPI0_SSEL2
 
 #endif /* _MACH_PORTMUX_H_ */
index 5d182ab..9dddb6f 100644 (file)
@@ -14,6 +14,7 @@
 #include <asm/clocks.h>
 #include <asm/mem_init.h>
 
+#define SDGCTL_WIDTH (1 << 31) /* SDRAM external data path width */
 #define PLL_CTL_VAL \
        (((CONFIG_VCO_MULT & 63) << 9) | CLKIN_HALF | \
         (PLL_BYPASS << 8) | (ANOMALY_05000265 ? 0x8000 : 0))
@@ -76,7 +77,7 @@ void init_clocks(void)
        bfin_write_PLL_DIV(CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV);
 #ifdef EBIU_SDGCTL
        bfin_write_EBIU_SDRRC(mem_SDRRC);
-       bfin_write_EBIU_SDGCTL(mem_SDGCTL);
+       bfin_write_EBIU_SDGCTL((bfin_read_EBIU_SDGCTL() & SDGCTL_WIDTH) | mem_SDGCTL);
 #else
        bfin_write_EBIU_RSTCTL(bfin_read_EBIU_RSTCTL() & ~(SRREQ));
        do_sync();
index fae7746..88de053 100644 (file)
@@ -151,13 +151,6 @@ ENTRY(_ex_syscall)
        jump.s _bfin_return_from_exception;
 ENDPROC(_ex_syscall)
 
-ENTRY(_ex_soft_bp)
-       r7 = retx;
-       r7 += -2;
-       retx = r7;
-       jump.s _ex_trap_c;
-ENDPROC(_ex_soft_bp)
-
 ENTRY(_ex_single_step)
        /* If we just returned from an interrupt, the single step event is
           for the RTI instruction.  */
@@ -1087,7 +1080,7 @@ ENTRY(_ex_table)
         * EXCPT instruction can provide 4 bits of EXCAUSE, allowing 16 to be user defined
         */
        .long _ex_syscall       /* 0x00 - User Defined - Linux Syscall */
-       .long _ex_soft_bp       /* 0x01 - User Defined - Software breakpoint */
+       .long _ex_trap_c        /* 0x01 - User Defined - Software breakpoint */
 #ifdef CONFIG_KGDB
        .long _ex_trap_c        /* 0x02 - User Defined - KGDB initial connection
                                                         and break signal trap */
index e1e42c0..698d4c0 100644 (file)
 
 __INIT
 
+ENTRY(__init_clear_bss)
+       r2 = r2 - r1;
+       cc = r2 == 0;
+       if cc jump .L_bss_done;
+       r2 >>= 2;
+       p1 = r1;
+       p2 = r2;
+       lsetup (1f, 1f) lc0 = p2;
+1:     [p1++] = r0;
+.L_bss_done:
+       rts;
+ENDPROC(__init_clear_bss)
+
 #define INITIAL_STACK  (L1_SCRATCH_START + L1_SCRATCH_LENGTH - 12)
 
 ENTRY(__start)
@@ -144,6 +157,35 @@ ENTRY(__start)
        call _init_early_exception_vectors;
 #endif
 
+       r0 = 0 (x);
+       /* Zero out all of the fun bss regions */
+#if L1_DATA_A_LENGTH > 0
+       r1.l = __sbss_l1;
+       r1.h = __sbss_l1;
+       r2.l = __ebss_l1;
+       r2.h = __ebss_l1;
+       call __init_clear_bss
+#endif
+#if L1_DATA_B_LENGTH > 0
+       r1.l = __sbss_b_l1;
+       r1.h = __sbss_b_l1;
+       r2.l = __ebss_b_l1;
+       r2.h = __ebss_b_l1;
+       call __init_clear_bss
+#endif
+#if L2_LENGTH > 0
+       r1.l = __sbss_l2;
+       r1.h = __sbss_l2;
+       r2.l = __ebss_l2;
+       r2.h = __ebss_l2;
+       call __init_clear_bss
+#endif
+       r1.l = ___bss_start;
+       r1.h = ___bss_start;
+       r2.l = ___bss_stop;
+       r2.h = ___bss_stop;
+       call __init_clear_bss
+
        /* Put The Code for PLL Programming and SDRAM Programming in L1 ISRAM */
        call _bfin_relocate_l1_mem;
 #ifdef CONFIG_BFIN_KERNEL_CLOCK
@@ -185,19 +227,6 @@ ENDPROC(__start)
 # define WDOG_CTL WDOGA_CTL
 #endif
 
-ENTRY(__init_clear_bss)
-       r2 = r2 - r1;
-       cc = r2 == 0;
-       if cc jump .L_bss_done;
-       r2 >>= 2;
-       p1 = r1;
-       p2 = r2;
-       lsetup (1f, 1f) lc0 = p2;
-1:     [p1++] = r0;
-.L_bss_done:
-       rts;
-ENDPROC(__init_clear_bss)
-
 ENTRY(_real_start)
        /* Enable nested interrupts */
        [--sp] = reti;
@@ -209,35 +238,6 @@ ENTRY(_real_start)
        w[p0] = r0;
        ssync;
 
-       r0 = 0 (x);
-       /* Zero out all of the fun bss regions */
-#if L1_DATA_A_LENGTH > 0
-       r1.l = __sbss_l1;
-       r1.h = __sbss_l1;
-       r2.l = __ebss_l1;
-       r2.h = __ebss_l1;
-       call __init_clear_bss
-#endif
-#if L1_DATA_B_LENGTH > 0
-       r1.l = __sbss_b_l1;
-       r1.h = __sbss_b_l1;
-       r2.l = __ebss_b_l1;
-       r2.h = __ebss_b_l1;
-       call __init_clear_bss
-#endif
-#if L2_LENGTH > 0
-       r1.l = __sbss_l2;
-       r1.h = __sbss_l2;
-       r2.l = __ebss_l2;
-       r2.h = __ebss_l2;
-       call __init_clear_bss
-#endif
-       r1.l = ___bss_start;
-       r1.h = ___bss_start;
-       r2.l = ___bss_stop;
-       r2.h = ___bss_stop;
-       call __init_clear_bss
-
        /* Pass the u-boot arguments to the global value command line */
        R0 = R7;
        call _cmdline_init;
index 473df0f..43c4eb9 100644 (file)
@@ -195,7 +195,7 @@ ENDPROC(_evt_ivhw)
 /* Interrupt routine for evt2 (NMI).
  * We don't actually use this, so just return.
  * For inner circle type details, please see:
- * http://docs.blackfin.uclinux.org/doku.php?id=linux:nmi
+ * http://docs.blackfin.uclinux.org/doku.php?id=linux-kernel:nmi
  */
 ENTRY(_evt_nmi)
 .weak _evt_nmi
index 1bba603..2024945 100644 (file)
@@ -1101,10 +1101,9 @@ int __init init_arch_irq(void)
            IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 |
            IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW;
 
-#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) \
-       || defined(BF538_FAMILY) || defined(CONFIG_BF51x)
+#ifdef SIC_IWR0
        bfin_write_SIC_IWR0(IWR_DISABLE_ALL);
-#if defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
+# ifdef SIC_IWR1
        /* BF52x/BF51x system reset does not properly reset SIC_IWR1 which
         * will screw up the bootrom as it relies on MDMA0/1 waking it
         * up from IDLE instructions.  See this report for more info:
@@ -1114,10 +1113,8 @@ int __init init_arch_irq(void)
                bfin_write_SIC_IWR1(IWR_ENABLE(10) | IWR_ENABLE(11));
        else
                bfin_write_SIC_IWR1(IWR_DISABLE_ALL);
-#else
-       bfin_write_SIC_IWR1(IWR_DISABLE_ALL);
-#endif
-# ifdef CONFIG_BF54x
+# endif
+# ifdef SIC_IWR2
        bfin_write_SIC_IWR2(IWR_DISABLE_ALL);
 # endif
 #else
index d3d70fd..f48a6ae 100644 (file)
@@ -82,10 +82,9 @@ void bfin_pm_suspend_standby_enter(void)
 
        bfin_pm_standby_restore();
 
-#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x)  || defined(CONFIG_BF561) || \
-       defined(CONFIG_BF538) || defined(CONFIG_BF539) || defined(CONFIG_BF51x)
+#ifdef SIC_IWR0
        bfin_write_SIC_IWR0(IWR_DISABLE_ALL);
-#if defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
+# ifdef SIC_IWR1
        /* BF52x system reset does not properly reset SIC_IWR1 which
         * will screw up the bootrom as it relies on MDMA0/1 waking it
         * up from IDLE instructions.  See this report for more info:
@@ -95,10 +94,8 @@ void bfin_pm_suspend_standby_enter(void)
                bfin_write_SIC_IWR1(IWR_ENABLE(10) | IWR_ENABLE(11));
        else
                bfin_write_SIC_IWR1(IWR_DISABLE_ALL);
-#else
-       bfin_write_SIC_IWR1(IWR_DISABLE_ALL);
-#endif
-# ifdef CONFIG_BF54x
+# endif
+# ifdef SIC_IWR2
        bfin_write_SIC_IWR2(IWR_DISABLE_ALL);
 # endif
 #else
index caf4c33..7c35787 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/gpio.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi_gpio.h>
+#include <media/ov772x.h>
 #include <media/soc_camera_platform.h>
 #include <media/sh_mobile_ceu.h>
 #include <video/sh_mobile_lcdc.h>
@@ -216,7 +217,14 @@ static struct platform_device lcdc_device = {
        },
 };
 
+static void camera_power(int val)
+{
+       gpio_set_value(GPIO_PTZ5, val); /* RST_CAM/RSTB */
+       mdelay(10);
+}
+
 #ifdef CONFIG_I2C
+/* support for the old ncm03j camera */
 static unsigned char camera_ncm03j_magic[] =
 {
        0x87, 0x00, 0x88, 0x08, 0x89, 0x01, 0x8A, 0xE8,
@@ -237,6 +245,23 @@ static unsigned char camera_ncm03j_magic[] =
        0x63, 0xD4, 0x64, 0xEA, 0xD6, 0x0F,
 };
 
+static int camera_probe(void)
+{
+       struct i2c_adapter *a = i2c_get_adapter(0);
+       struct i2c_msg msg;
+       int ret;
+
+       camera_power(1);
+       msg.addr = 0x6e;
+       msg.buf = camera_ncm03j_magic;
+       msg.len = 2;
+       msg.flags = 0;
+       ret = i2c_transfer(a, &msg, 1);
+       camera_power(0);
+
+       return ret;
+}
+
 static int camera_set_capture(struct soc_camera_platform_info *info,
                              int enable)
 {
@@ -245,9 +270,11 @@ static int camera_set_capture(struct soc_camera_platform_info *info,
        int ret = 0;
        int i;
 
+       camera_power(0);
        if (!enable)
                return 0; /* no disable for now */
 
+       camera_power(1);
        for (i = 0; i < ARRAY_SIZE(camera_ncm03j_magic); i += 2) {
                u_int8_t buf[8];
 
@@ -286,8 +313,35 @@ static struct platform_device camera_device = {
                .platform_data  = &camera_info,
        },
 };
+
+static int __init camera_setup(void)
+{
+       if (camera_probe() > 0)
+               platform_device_register(&camera_device);
+
+       return 0;
+}
+late_initcall(camera_setup);
+
 #endif /* CONFIG_I2C */
 
+static int ov7725_power(struct device *dev, int mode)
+{
+       camera_power(0);
+       if (mode)
+               camera_power(1);
+
+       return 0;
+}
+
+static struct ov772x_camera_info ov7725_info = {
+       .buswidth  = SOCAM_DATAWIDTH_8,
+       .flags = OV772X_FLAG_VFLIP | OV772X_FLAG_HFLIP,
+       .link = {
+               .power  = ov7725_power,
+       },
+};
+
 static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
        .flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH |
        SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8,
@@ -338,9 +392,6 @@ static struct platform_device *ap325rxa_devices[] __initdata = {
        &ap325rxa_nor_flash_device,
        &lcdc_device,
        &ceu_device,
-#ifdef CONFIG_I2C
-       &camera_device,
-#endif
        &nand_flash_device,
        &sdcard_cn3_device,
 };
@@ -349,6 +400,10 @@ static struct i2c_board_info __initdata ap325rxa_i2c_devices[] = {
        {
                I2C_BOARD_INFO("pcf8563", 0x51),
        },
+       {
+               I2C_BOARD_INFO("ov772x", 0x21),
+               .platform_data = &ov7725_info,
+       },
 };
 
 static struct spi_board_info ap325rxa_spi_devices[] = {
@@ -426,7 +481,7 @@ static int __init ap325rxa_devices_setup(void)
        gpio_request(GPIO_PTZ6, NULL);
        gpio_direction_output(GPIO_PTZ6, 0); /* STBY_CAM */
        gpio_request(GPIO_PTZ5, NULL);
-       gpio_direction_output(GPIO_PTZ5, 1); /* RST_CAM */
+       gpio_direction_output(GPIO_PTZ5, 0); /* RST_CAM */
        gpio_request(GPIO_PTZ4, NULL);
        gpio_direction_output(GPIO_PTZ4, 0); /* SADDR */
 
index 5c423fa..352f87d 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28
-# Fri Jan  9 16:54:19 2009
+# Linux kernel version: 2.6.29-rc2
+# Tue Jan 27 11:45:08 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
@@ -45,12 +45,12 @@ CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
 CONFIG_GROUP_SCHED=y
 CONFIG_FAIR_GROUP_SCHED=y
 # CONFIG_RT_GROUP_SCHED is not set
 CONFIG_USER_SCHED=y
 # CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
 CONFIG_SYSFS_DEPRECATED=y
 CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_RELAY is not set
@@ -378,6 +378,7 @@ CONFIG_WIRELESS=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
 # CONFIG_MAC80211 is not set
+# CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
 
@@ -400,6 +401,7 @@ CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
 CONFIG_MTD_CONCAT=y
 CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
 # CONFIG_MTD_REDBOOT_PARTS is not set
 CONFIG_MTD_CMDLINE_PARTS=y
 # CONFIG_MTD_AR7_PARTS is not set
@@ -447,9 +449,7 @@ CONFIG_MTD_CFI_UTIL=y
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
 CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0xffffffff
-CONFIG_MTD_PHYSMAP_LEN=0
-CONFIG_MTD_PHYSMAP_BANKWIDTH=0
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
 # CONFIG_MTD_PLATRAM is not set
 
 #
@@ -479,6 +479,12 @@ CONFIG_MTD_NAND_IDS=y
 CONFIG_MTD_NAND_SH_FLCTL=y
 # CONFIG_MTD_ONENAND is not set
 
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
 #
 # UBI - Unsorted block images
 #
@@ -607,6 +613,10 @@ CONFIG_SMSC911X=y
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
 # CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
 # CONFIG_WAN is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
@@ -790,6 +800,7 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_PMIC_DA903X is not set
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
 # CONFIG_REGULATOR is not set
 
 #
@@ -837,7 +848,7 @@ CONFIG_SOC_CAMERA=y
 # CONFIG_SOC_CAMERA_MT9V022 is not set
 # CONFIG_SOC_CAMERA_TW9910 is not set
 CONFIG_SOC_CAMERA_PLATFORM=y
-# CONFIG_SOC_CAMERA_OV772X is not set
+CONFIG_SOC_CAMERA_OV772X=y
 CONFIG_VIDEO_SH_MOBILE_CEU=y
 # CONFIG_RADIO_ADAPTERS is not set
 # CONFIG_DAB is not set
@@ -1012,6 +1023,7 @@ CONFIG_FS_POSIX_ACL=y
 CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1060,6 +1072,7 @@ CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_JFFS2_FS is not set
 # CONFIG_UBIFS_FS is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_OMFS_FS is not set
index 7758263..6785767 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28
-# Fri Jan  9 17:09:35 2009
+# Linux kernel version: 2.6.29-rc1
+# Thu Jan 22 09:16:16 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
@@ -45,8 +45,12 @@ CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
 # CONFIG_GROUP_SCHED is not set
+
+#
+# Control Group support
+#
+# CONFIG_CGROUPS is not set
 CONFIG_SYSFS_DEPRECATED=y
 CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_RELAY is not set
@@ -389,6 +393,7 @@ CONFIG_WIRELESS_EXT=y
 CONFIG_WIRELESS_EXT_SYSFS=y
 # CONFIG_LIB80211 is not set
 # CONFIG_MAC80211 is not set
+# CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
 
@@ -411,6 +416,7 @@ CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
 CONFIG_MTD_CONCAT=y
 CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
 # CONFIG_MTD_REDBOOT_PARTS is not set
 CONFIG_MTD_CMDLINE_PARTS=y
 # CONFIG_MTD_AR7_PARTS is not set
@@ -458,9 +464,7 @@ CONFIG_MTD_CFI_UTIL=y
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
 CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0xffffffff
-CONFIG_MTD_PHYSMAP_LEN=0
-CONFIG_MTD_PHYSMAP_BANKWIDTH=0
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
 # CONFIG_MTD_PLATRAM is not set
 
 #
@@ -487,6 +491,12 @@ CONFIG_MTD_NAND_IDS=y
 CONFIG_MTD_NAND_PLATFORM=y
 # CONFIG_MTD_ONENAND is not set
 
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
 #
 # UBI - Unsorted block images
 #
@@ -587,6 +597,10 @@ CONFIG_SMC91X=y
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
 # CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
 # CONFIG_WAN is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
@@ -761,6 +775,7 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_PMIC_DA903X is not set
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
 # CONFIG_REGULATOR is not set
 
 #
@@ -806,9 +821,9 @@ CONFIG_SOC_CAMERA=y
 # CONFIG_SOC_CAMERA_MT9M111 is not set
 # CONFIG_SOC_CAMERA_MT9T031 is not set
 # CONFIG_SOC_CAMERA_MT9V022 is not set
-# CONFIG_SOC_CAMERA_TW9910 is not set
-CONFIG_SOC_CAMERA_PLATFORM=y
-# CONFIG_SOC_CAMERA_OV772X is not set
+CONFIG_SOC_CAMERA_TW9910=y
+# CONFIG_SOC_CAMERA_PLATFORM is not set
+CONFIG_SOC_CAMERA_OV772X=y
 CONFIG_VIDEO_SH_MOBILE_CEU=y
 # CONFIG_RADIO_ADAPTERS is not set
 # CONFIG_DAB is not set
@@ -866,11 +881,13 @@ CONFIG_USB_GADGET_SELECTED=y
 # CONFIG_USB_GADGET_PXA25X is not set
 # CONFIG_USB_GADGET_PXA27X is not set
 # CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_IMX is not set
 CONFIG_USB_GADGET_M66592=y
 CONFIG_USB_M66592=y
 CONFIG_SUPERH_BUILT_IN_M66592=y
 # CONFIG_USB_GADGET_AMD5536UDC is not set
 # CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
 # CONFIG_USB_GADGET_NET2280 is not set
 # CONFIG_USB_GADGET_GOKU is not set
 # CONFIG_USB_GADGET_DUMMY_HCD is not set
@@ -883,6 +900,11 @@ CONFIG_USB_G_SERIAL=y
 # CONFIG_USB_MIDI_GADGET is not set
 # CONFIG_USB_G_PRINTER is not set
 # CONFIG_USB_CDC_COMPOSITE is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
 # CONFIG_MMC is not set
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
@@ -961,6 +983,7 @@ CONFIG_UIO_PDRV_GENIRQ=y
 CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY is not set
 # CONFIG_QUOTA is not set
@@ -1004,6 +1027,7 @@ CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS2_FS is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_OMFS_FS is not set
index ee839ee..090358a 100644 (file)
 static inline void
 __mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
 {
-       int __ex_flag, __res;
+       int __done, __res;
 
        __asm__ __volatile__ (
                "movli.l        @%2, %0 \n"
                "add            #-1, %0 \n"
                "movco.l        %0, @%2 \n"
                "movt           %1      \n"
-               : "=&z" (__res), "=&r" (__ex_flag)
+               : "=&z" (__res), "=&r" (__done)
                : "r" (&(count)->counter)
                : "t");
 
-       __res |= !__ex_flag;
-       if (unlikely(__res != 0))
+       if (unlikely(!__done || __res != 0))
                fail_fn(count);
 }
 
 static inline int
 __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
 {
-       int __ex_flag, __res;
+       int __done, __res;
 
        __asm__ __volatile__ (
                "movli.l        @%2, %0 \n"
                "add            #-1, %0 \n"
                "movco.l        %0, @%2 \n"
                "movt           %1      \n"
-               : "=&z" (__res), "=&r" (__ex_flag)
+               : "=&z" (__res), "=&r" (__done)
                : "r" (&(count)->counter)
                : "t");
 
-       __res |= !__ex_flag;
-       if (unlikely(__res != 0))
+       if (unlikely(!__done || __res != 0))
                __res = fail_fn(count);
 
        return __res;
@@ -61,19 +59,18 @@ __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
 static inline void
 __mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *))
 {
-       int __ex_flag, __res;
+       int __done, __res;
 
        __asm__ __volatile__ (
                "movli.l        @%2, %0 \n\t"
                "add            #1, %0  \n\t"
                "movco.l        %0, @%2 \n\t"
                "movt           %1      \n\t"
-               : "=&z" (__res), "=&r" (__ex_flag)
+               : "=&z" (__res), "=&r" (__done)
                : "r" (&(count)->counter)
                : "t");
 
-       __res |= !__ex_flag;
-       if (unlikely(__res <= 0))
+       if (unlikely(!__done || __res <= 0))
                fail_fn(count);
 }
 
index 05a868a..5bc3468 100644 (file)
@@ -21,23 +21,10 @@ static inline void syscall_rollback(struct task_struct *task,
         */
 }
 
-static inline bool syscall_has_error(struct pt_regs *regs)
-{
-       return (regs->sr & 0x1) ? true : false;
-}
-static inline void syscall_set_error(struct pt_regs *regs)
-{
-       regs->sr |= 0x1;
-}
-static inline void syscall_clear_error(struct pt_regs *regs)
-{
-       regs->sr &= ~0x1;
-}
-
 static inline long syscall_get_error(struct task_struct *task,
                                     struct pt_regs *regs)
 {
-       return syscall_has_error(regs) ? regs->regs[0] : 0;
+       return IS_ERR_VALUE(regs->regs[0]) ? regs->regs[0] : 0;
 }
 
 static inline long syscall_get_return_value(struct task_struct *task,
@@ -50,13 +37,10 @@ static inline void syscall_set_return_value(struct task_struct *task,
                                            struct pt_regs *regs,
                                            int error, long val)
 {
-       if (error) {
-               syscall_set_error(regs);
+       if (error)
                regs->regs[0] = -error;
-       } else {
-               syscall_clear_error(regs);
+       else
                regs->regs[0] = val;
-       }
 }
 
 static inline void syscall_get_arguments(struct task_struct *task,
index e1143b9..c3561ca 100644 (file)
@@ -21,23 +21,10 @@ static inline void syscall_rollback(struct task_struct *task,
         */
 }
 
-static inline bool syscall_has_error(struct pt_regs *regs)
-{
-       return (regs->sr & 0x1) ? true : false;
-}
-static inline void syscall_set_error(struct pt_regs *regs)
-{
-       regs->sr |= 0x1;
-}
-static inline void syscall_clear_error(struct pt_regs *regs)
-{
-       regs->sr &= ~0x1;
-}
-
 static inline long syscall_get_error(struct task_struct *task,
                                     struct pt_regs *regs)
 {
-       return syscall_has_error(regs) ? regs->regs[9] : 0;
+       return IS_ERR_VALUE(regs->regs[9]) ? regs->regs[9] : 0;
 }
 
 static inline long syscall_get_return_value(struct task_struct *task,
@@ -50,13 +37,10 @@ static inline void syscall_set_return_value(struct task_struct *task,
                                            struct pt_regs *regs,
                                            int error, long val)
 {
-       if (error) {
-               syscall_set_error(regs);
+       if (error)
                regs->regs[9] = -error;
-       } else {
-               syscall_clear_error(regs);
+       else
                regs->regs[9] = val;
-       }
 }
 
 static inline void syscall_get_arguments(struct task_struct *task,
index 2780917..e3ea541 100644 (file)
@@ -423,7 +423,7 @@ static int ieee_fpe_handler(struct pt_regs *regs)
                int m;
                unsigned int hx;
 
-               m = (finsn >> 9) & 0x7;
+               m = (finsn >> 8) & 0x7;
                hx = tsk->thread.fpu.hard.fp_regs[m];
 
                if ((tsk->thread.fpu.hard.fpscr & FPSCR_CAUSE_ERROR)
index 5342475..370d2cf 100644 (file)
@@ -262,11 +262,11 @@ void __init setup_bootmem_allocator(unsigned long free_pfn)
                        BOOTMEM_DEFAULT);
 
        /*
-        * reserve physical page 0 - it's a special BIOS page on many boxes,
-        * enabling clean reboots, SMP operation, laptop functions.
+        * Reserve physical pages below CONFIG_ZERO_PAGE_OFFSET.
         */
-       reserve_bootmem(__MEMORY_START, CONFIG_ZERO_PAGE_OFFSET,
-                       BOOTMEM_DEFAULT);
+       if (CONFIG_ZERO_PAGE_OFFSET != 0)
+               reserve_bootmem(__MEMORY_START, CONFIG_ZERO_PAGE_OFFSET,
+                               BOOTMEM_DEFAULT);
 
        sparse_memory_present_with_active_regions(0);
 
index 77c21bd..17784e1 100644 (file)
@@ -510,7 +510,6 @@ handle_syscall_restart(unsigned long save_r0, struct pt_regs *regs,
                case -ERESTARTNOHAND:
                no_system_call_restart:
                        regs->regs[0] = -EINTR;
-                       regs->sr |= 1;
                        break;
 
                case -ERESTARTSYS:
@@ -589,8 +588,7 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
 
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
        if (signr > 0) {
-               if (regs->sr & 1)
-                       handle_syscall_restart(save_r0, regs, &ka.sa);
+               handle_syscall_restart(save_r0, regs, &ka.sa);
 
                /* Whee!  Actually deliver the signal.  */
                if (handle_signal(signr, &ka, &info, oldset,
index b22fdfa..0663a0e 100644 (file)
@@ -60,7 +60,6 @@ handle_syscall_restart(struct pt_regs *regs, struct sigaction *sa)
                case -ERESTARTNOHAND:
                no_system_call_restart:
                        regs->regs[REG_RET] = -EINTR;
-                       regs->sr |= 1;
                        break;
 
                case -ERESTARTSYS:
@@ -109,8 +108,7 @@ static int do_signal(struct pt_regs *regs, sigset_t *oldset)
 
        signr = get_signal_to_deliver(&info, &ka, regs, 0);
        if (signr > 0) {
-               if (regs->sr & 1)
-                       handle_syscall_restart(regs, &ka.sa);
+               handle_syscall_restart(regs, &ka.sa);
 
                /* Whee!  Actually deliver the signal.  */
                if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
index cbdd0d4..356c8ec 100644 (file)
@@ -36,8 +36,7 @@
  */
 
 /*     
- * unsigned int csum_partial(const unsigned char *buf, int len,
- *                           unsigned int sum);
+ * asmlinkage __wsum csum_partial(const void *buf, int len, __wsum sum);
  */
 
 .text
@@ -49,11 +48,31 @@ ENTRY(csum_partial)
           * Fortunately, it is easy to convert 2-byte alignment to 4-byte
           * alignment for the unrolled loop.
           */
-       mov     r5, r1
        mov     r4, r0
-       tst     #2, r0          ! Check alignment.
-       bt      2f              ! Jump if alignment is ok.
+       tst     #3, r0          ! Check alignment.
+       bt/s    2f              ! Jump if alignment is ok.
+        mov    r4, r7          ! Keep a copy to check for alignment
        !
+       tst     #1, r0          ! Check alignment.
+       bt      21f             ! Jump if alignment is boundary of 2bytes.
+
+       ! buf is odd
+       tst     r5, r5
+       add     #-1, r5
+       bt      9f
+       mov.b   @r4+, r0
+       extu.b  r0, r0
+       addc    r0, r6          ! t=0 from previous tst
+       mov     r6, r0
+       shll8   r6
+       shlr16  r0
+       shlr8   r0
+       or      r0, r6
+       mov     r4, r0
+       tst     #2, r0
+       bt      2f
+21:
+       ! buf is 2 byte aligned (len could be 0)
        add     #-2, r5         ! Alignment uses up two bytes.
        cmp/pz  r5              !
        bt/s    1f              ! Jump if we had at least two bytes.
@@ -61,16 +80,17 @@ ENTRY(csum_partial)
        bra     6f
         add    #2, r5          ! r5 was < 2.  Deal with it.
 1:
-       mov     r5, r1          ! Save new len for later use.
        mov.w   @r4+, r0
        extu.w  r0, r0
        addc    r0, r6
        bf      2f
        add     #1, r6
 2:
+       ! buf is 4 byte aligned (len could be 0)
+       mov     r5, r1
        mov     #-5, r0
-       shld    r0, r5
-       tst     r5, r5
+       shld    r0, r1
+       tst     r1, r1
        bt/s    4f              ! if it's =0, go to 4f
         clrt
        .align  2
@@ -92,30 +112,31 @@ ENTRY(csum_partial)
        addc    r0, r6
        addc    r2, r6
        movt    r0
-       dt      r5
+       dt      r1
        bf/s    3b
         cmp/eq #1, r0
-       ! here, we know r5==0
-       addc    r5, r6                  ! add carry to r6
+       ! here, we know r1==0
+       addc    r1, r6                  ! add carry to r6
 4:
-       mov     r1, r0
+       mov     r5, r0
        and     #0x1c, r0
        tst     r0, r0
-       bt/s    6f
-        mov    r0, r5
-       shlr2   r5
+       bt      6f
+       ! 4 bytes or more remaining
+       mov     r0, r1
+       shlr2   r1
        mov     #0, r2
 5:
        addc    r2, r6
        mov.l   @r4+, r2
        movt    r0
-       dt      r5
+       dt      r1
        bf/s    5b
         cmp/eq #1, r0
        addc    r2, r6
-       addc    r5, r6          ! r5==0 here, so it means add carry-bit
+       addc    r1, r6          ! r1==0 here, so it means add carry-bit
 6:
-       mov     r1, r5
+       ! 3 bytes or less remaining
        mov     #3, r0
        and     r0, r5
        tst     r5, r5
@@ -139,8 +160,18 @@ ENTRY(csum_partial)
 8:
        addc    r0, r6
        mov     #0, r0
-       addc    r0, r6 
+       addc    r0, r6
 9:
+       ! Check if the buffer was misaligned, if so realign sum
+       mov     r7, r0
+       tst     #1, r0
+       bt      10f
+       mov     r6, r0
+       shll8   r6
+       shlr16  r0
+       shlr8   r0
+       or      r0, r6
+10:
        rts
         mov    r6, r0
 
index 7da7c13..a11b89e 100644 (file)
@@ -17,7 +17,7 @@
 typedef struct {
        /* Dcache line 1 */
        unsigned int    __softirq_pending; /* must be 1st, see rtrap.S */
-       unsigned int    __pad0;
+       unsigned int    __nmi_count;
        unsigned long   clock_tick;     /* %tick's per second */
        unsigned long   __pad;
        unsigned int    __pad1;
index d47d4a1..1934f2c 100644 (file)
@@ -66,9 +66,6 @@ extern void virt_irq_free(unsigned int virt_irq);
 extern void __init init_IRQ(void);
 extern void fixup_irqs(void);
 
-extern int register_perfctr_intr(void (*handler)(struct pt_regs *));
-extern void release_perfctr_intr(void (*handler)(struct pt_regs *));
-
 static inline void set_softint(unsigned long bits)
 {
        __asm__ __volatile__("wr        %0, 0x0, %%set_softint"
@@ -98,5 +95,6 @@ void __trigger_all_cpu_backtrace(void);
 extern void *hardirq_stack[NR_CPUS];
 extern void *softirq_stack[NR_CPUS];
 #define __ARCH_HAS_DO_SOFTIRQ
+#define ARCH_HAS_NMI_WATCHDOG
 
 #endif
index f905b77..feb3578 100644 (file)
@@ -14,6 +14,8 @@ enum die_val {
        DIE_TRAP,
        DIE_TRAP_TL1,
        DIE_CALL,
+       DIE_NMI,
+       DIE_NMIWATCHDOG,
 };
 
 #endif
diff --git a/arch/sparc/include/asm/nmi.h b/arch/sparc/include/asm/nmi.h
new file mode 100644 (file)
index 0000000..fbd546d
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __NMI_H
+#define __NMI_H
+
+extern int __init nmi_init(void);
+extern void perfctr_irq(int irq, struct pt_regs *regs);
+extern void nmi_adjust_hz(unsigned int new_hz);
+
+extern int nmi_usable;
+
+#endif /* __NMI_H */
diff --git a/arch/sparc/include/asm/pcr.h b/arch/sparc/include/asm/pcr.h
new file mode 100644 (file)
index 0000000..a2f5c61
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef __PCR_H
+#define __PCR_H
+
+struct pcr_ops {
+       u64 (*read)(void);
+       void (*write)(u64);
+};
+extern const struct pcr_ops *pcr_ops;
+
+extern void deferred_pcr_work_irq(int irq, struct pt_regs *regs);
+extern void schedule_deferred_pcr_work(void);
+
+#define PCR_PIC_PRIV           0x00000001 /* PIC access is privileged */
+#define PCR_STRACE             0x00000002 /* Trace supervisor events  */
+#define PCR_UTRACE             0x00000004 /* Trace user events        */
+#define PCR_N2_HTRACE          0x00000008 /* Trace hypervisor events  */
+#define PCR_N2_TOE_OV0         0x00000010 /* Trap if PIC 0 overflows  */
+#define PCR_N2_TOE_OV1         0x00000020 /* Trap if PIC 1 overflows  */
+#define PCR_N2_MASK0           0x00003fc0
+#define PCR_N2_MASK0_SHIFT     6
+#define PCR_N2_SL0             0x0003c000
+#define PCR_N2_SL0_SHIFT       14
+#define PCR_N2_OV0             0x00040000
+#define PCR_N2_MASK1           0x07f80000
+#define PCR_N2_MASK1_SHIFT     19
+#define PCR_N2_SL1             0x78000000
+#define PCR_N2_SL1_SHIFT       27
+#define PCR_N2_OV1             0x80000000
+
+extern unsigned int picl_shift;
+
+/* In order to commonize as much of the implementation as
+ * possible, we use PICH as our counter.  Mostly this is
+ * to accomodate Niagara-1 which can only count insn cycles
+ * in PICH.
+ */
+static inline u64 picl_value(unsigned int nmi_hz)
+{
+       u32 delta = local_cpu_data().clock_tick / (nmi_hz << picl_shift);
+
+       return ((u64)((0 - delta) & 0xffffffff)) << 32;
+}
+
+extern u64 pcr_enable;
+
+#endif /* __PCR_H */
index d573820..32a7efe 100644 (file)
@@ -23,6 +23,7 @@
 #define PIL_SMP_CTX_NEW_VERSION        4
 #define PIL_DEVICE_IRQ         5
 #define PIL_SMP_CALL_FUNC_SNGL 6
+#define PIL_DEFERRED_PCR_WORK  7
 #define PIL_NORMAL_MAX         14
 #define PIL_NMI                        15
 
index 53adcaa..54742e5 100644 (file)
@@ -52,6 +52,8 @@ obj-$(CONFIG_SPARC64)   += visemul.o
 obj-$(CONFIG_SPARC64)   += hvapi.o
 obj-$(CONFIG_SPARC64)   += sstate.o
 obj-$(CONFIG_SPARC64)   += mdesc.o
+obj-$(CONFIG_SPARC64)  += pcr.o
+obj-$(CONFIG_SPARC64)  += nmi.o
 
 # sparc32 do not use GENERIC_HARDIRQS but uses the generic devres implementation
 obj-$(CONFIG_SPARC32)     += devres.o
index 32d32b4..d85c3dc 100644 (file)
@@ -26,6 +26,7 @@ EXPORT_PER_CPU_SYMBOL(__cpu_data);
 struct cpu_info {
        int psr_vers;
        const char *name;
+       const char *pmu_name;
 };
 
 struct fpu_info {
@@ -45,6 +46,9 @@ struct manufacturer_info {
 #define CPU(ver, _name) \
 { .psr_vers = ver, .name = _name }
 
+#define CPU_PMU(ver, _name, _pmu_name) \
+{ .psr_vers = ver, .name = _name, .pmu_name = _pmu_name }
+
 #define FPU(ver, _name) \
 { .fp_vers = ver, .name = _name }
 
@@ -183,10 +187,10 @@ static const struct manufacturer_info __initconst manufacturer_info[] = {
 },{
        0x17,
        .cpu_info = {
-               CPU(0x10, "TI UltraSparc I   (SpitFire)"),
-               CPU(0x11, "TI UltraSparc II  (BlackBird)"),
-               CPU(0x12, "TI UltraSparc IIi (Sabre)"),
-               CPU(0x13, "TI UltraSparc IIe (Hummingbird)"),
+               CPU_PMU(0x10, "TI UltraSparc I   (SpitFire)", "ultra12"),
+               CPU_PMU(0x11, "TI UltraSparc II  (BlackBird)", "ultra12"),
+               CPU_PMU(0x12, "TI UltraSparc IIi (Sabre)", "ultra12"),
+               CPU_PMU(0x13, "TI UltraSparc IIe (Hummingbird)", "ultra12"),
                CPU(-1, NULL)
        },
        .fpu_info = {
@@ -199,7 +203,7 @@ static const struct manufacturer_info __initconst manufacturer_info[] = {
 },{
        0x22,
        .cpu_info = {
-               CPU(0x10, "TI UltraSparc I   (SpitFire)"),
+               CPU_PMU(0x10, "TI UltraSparc I   (SpitFire)", "ultra12"),
                CPU(-1, NULL)
        },
        .fpu_info = {
@@ -209,12 +213,12 @@ static const struct manufacturer_info __initconst manufacturer_info[] = {
 },{
        0x3e,
        .cpu_info = {
-               CPU(0x14, "TI UltraSparc III (Cheetah)"),
-               CPU(0x15, "TI UltraSparc III+ (Cheetah+)"),
-               CPU(0x16, "TI UltraSparc IIIi (Jalapeno)"),
-               CPU(0x18, "TI UltraSparc IV (Jaguar)"),
-               CPU(0x19, "TI UltraSparc IV+ (Panther)"),
-               CPU(0x22, "TI UltraSparc IIIi+ (Serrano)"),
+               CPU_PMU(0x14, "TI UltraSparc III (Cheetah)", "ultra3"),
+               CPU_PMU(0x15, "TI UltraSparc III+ (Cheetah+)", "ultra3+"),
+               CPU_PMU(0x16, "TI UltraSparc IIIi (Jalapeno)", "ultra3i"),
+               CPU_PMU(0x18, "TI UltraSparc IV (Jaguar)", "ultra3+"),
+               CPU_PMU(0x19, "TI UltraSparc IV+ (Panther)", "ultra4+"),
+               CPU_PMU(0x22, "TI UltraSparc IIIi+ (Serrano)", "ultra3i"),
                CPU(-1, NULL)
        },
        .fpu_info = {
@@ -234,6 +238,7 @@ static const struct manufacturer_info __initconst manufacturer_info[] = {
 
 const char *sparc_cpu_type;
 const char *sparc_fpu_type;
+const char *sparc_pmu_type;
 
 unsigned int fsr_storage;
 
@@ -244,6 +249,7 @@ static void set_cpu_and_fpu(int psr_impl, int psr_vers, int fpu_vers)
 
        sparc_cpu_type = NULL;
        sparc_fpu_type = NULL;
+       sparc_pmu_type = NULL;
        manuf = NULL;
 
        for (i = 0; i < ARRAY_SIZE(manufacturer_info); i++)
@@ -263,6 +269,7 @@ static void set_cpu_and_fpu(int psr_impl, int psr_vers, int fpu_vers)
                {
                        if (cpu->psr_vers == psr_vers) {
                                sparc_cpu_type = cpu->name;
+                               sparc_pmu_type = cpu->pmu_name;
                                sparc_fpu_type = "No FPU";
                                break;
                        }
@@ -290,6 +297,8 @@ static void set_cpu_and_fpu(int psr_impl, int psr_vers, int fpu_vers)
                       psr_impl, fpu_vers);
                sparc_fpu_type = "Unknown FPU";
        }
+       if (sparc_pmu_type == NULL)
+               sparc_pmu_type = "Unknown PMU";
 }
 
 #ifdef CONFIG_SPARC32
@@ -315,11 +324,13 @@ static void __init sun4v_cpu_probe(void)
        case SUN4V_CHIP_NIAGARA1:
                sparc_cpu_type = "UltraSparc T1 (Niagara)";
                sparc_fpu_type = "UltraSparc T1 integrated FPU";
+               sparc_pmu_type = "niagara";
                break;
 
        case SUN4V_CHIP_NIAGARA2:
                sparc_cpu_type = "UltraSparc T2 (Niagara2)";
                sparc_fpu_type = "UltraSparc T2 integrated FPU";
+               sparc_pmu_type = "niagara2";
                break;
 
        default:
index cab8e02..e289376 100644 (file)
@@ -196,6 +196,11 @@ int show_interrupts(struct seq_file *p, void *v)
                seq_putc(p, '\n');
 skip:
                spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+       } else if (i == NR_IRQS) {
+               seq_printf(p, "NMI: ");
+               for_each_online_cpu(j)
+                       seq_printf(p, "%10u ", cpu_data(j).__nmi_count);
+               seq_printf(p, "     Non-maskable interrupts\n");
        }
        return 0;
 }
@@ -778,69 +783,6 @@ void do_softirq(void)
        local_irq_restore(flags);
 }
 
-static void unhandled_perf_irq(struct pt_regs *regs)
-{
-       unsigned long pcr, pic;
-
-       read_pcr(pcr);
-       read_pic(pic);
-
-       write_pcr(0);
-
-       printk(KERN_EMERG "CPU %d: Got unexpected perf counter IRQ.\n",
-              smp_processor_id());
-       printk(KERN_EMERG "CPU %d: PCR[%016lx] PIC[%016lx]\n",
-              smp_processor_id(), pcr, pic);
-}
-
-/* Almost a direct copy of the powerpc PMC code.  */
-static DEFINE_SPINLOCK(perf_irq_lock);
-static void *perf_irq_owner_caller; /* mostly for debugging */
-static void (*perf_irq)(struct pt_regs *regs) = unhandled_perf_irq;
-
-/* Invoked from level 15 PIL handler in trap table.  */
-void perfctr_irq(int irq, struct pt_regs *regs)
-{
-       clear_softint(1 << irq);
-       perf_irq(regs);
-}
-
-int register_perfctr_intr(void (*handler)(struct pt_regs *))
-{
-       int ret;
-
-       if (!handler)
-               return -EINVAL;
-
-       spin_lock(&perf_irq_lock);
-       if (perf_irq != unhandled_perf_irq) {
-               printk(KERN_WARNING "register_perfctr_intr: "
-                      "perf IRQ busy (reserved by caller %p)\n",
-                      perf_irq_owner_caller);
-               ret = -EBUSY;
-               goto out;
-       }
-
-       perf_irq_owner_caller = __builtin_return_address(0);
-       perf_irq = handler;
-
-       ret = 0;
-out:
-       spin_unlock(&perf_irq_lock);
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(register_perfctr_intr);
-
-void release_perfctr_intr(void (*handler)(struct pt_regs *))
-{
-       spin_lock(&perf_irq_lock);
-       perf_irq_owner_caller = NULL;
-       perf_irq = unhandled_perf_irq;
-       spin_unlock(&perf_irq_lock);
-}
-EXPORT_SYMBOL_GPL(release_perfctr_intr);
-
 #ifdef CONFIG_HOTPLUG_CPU
 void fixup_irqs(void)
 {
index 81a972e..15d8a3f 100644 (file)
@@ -5,6 +5,7 @@
 
 /* cpu.c */
 extern const char *sparc_cpu_type;
+extern const char *sparc_pmu_type;
 extern const char *sparc_fpu_type;
 
 extern unsigned int fsr_storage;
diff --git a/arch/sparc/kernel/nmi.c b/arch/sparc/kernel/nmi.c
new file mode 100644 (file)
index 0000000..09f088e
--- /dev/null
@@ -0,0 +1,224 @@
+/* Pseudo NMI support on sparc64 systems.
+ *
+ * Copyright (C) 2009 David S. Miller <davem@davemloft.net>
+ *
+ * The NMI watchdog support and infrastructure is based almost
+ * entirely upon the x86 NMI support code.
+ */
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <linux/percpu.h>
+#include <linux/nmi.h>
+#include <linux/module.h>
+#include <linux/kprobes.h>
+#include <linux/kernel_stat.h>
+#include <linux/slab.h>
+#include <linux/kdebug.h>
+#include <linux/delay.h>
+#include <linux/smp.h>
+
+#include <asm/ptrace.h>
+#include <asm/local.h>
+#include <asm/pcr.h>
+
+/* We don't have a real NMI on sparc64, but we can fake one
+ * up using profiling counter overflow interrupts and interrupt
+ * levels.
+ *
+ * The profile overflow interrupts at level 15, so we use
+ * level 14 as our IRQ off level.
+ */
+
+static int nmi_watchdog_active;
+static int panic_on_timeout;
+
+int nmi_usable;
+EXPORT_SYMBOL_GPL(nmi_usable);
+
+static unsigned int nmi_hz = HZ;
+
+static DEFINE_PER_CPU(unsigned int, last_irq_sum);
+static DEFINE_PER_CPU(local_t, alert_counter);
+static DEFINE_PER_CPU(int, nmi_touch);
+
+void touch_nmi_watchdog(void)
+{
+       if (nmi_watchdog_active) {
+               int cpu;
+
+               for_each_present_cpu(cpu) {
+                       if (per_cpu(nmi_touch, cpu) != 1)
+                               per_cpu(nmi_touch, cpu) = 1;
+               }
+       }
+
+       touch_softlockup_watchdog();
+}
+EXPORT_SYMBOL(touch_nmi_watchdog);
+
+static void die_nmi(const char *str, struct pt_regs *regs, int do_panic)
+{
+       if (notify_die(DIE_NMIWATCHDOG, str, regs, 0,
+                      pt_regs_trap_type(regs), SIGINT) == NOTIFY_STOP)
+               return;
+
+       console_verbose();
+       bust_spinlocks(1);
+
+       printk(KERN_EMERG "%s", str);
+       printk(" on CPU%d, ip %08lx, registers:\n",
+              smp_processor_id(), regs->tpc);
+       show_regs(regs);
+
+       bust_spinlocks(0);
+
+       if (do_panic || panic_on_oops)
+               panic("Non maskable interrupt");
+
+       local_irq_enable();
+       do_exit(SIGBUS);
+}
+
+notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs)
+{
+       unsigned int sum, touched = 0;
+       int cpu = smp_processor_id();
+
+       clear_softint(1 << irq);
+       pcr_ops->write(PCR_PIC_PRIV);
+
+       local_cpu_data().__nmi_count++;
+
+       if (notify_die(DIE_NMI, "nmi", regs, 0,
+                      pt_regs_trap_type(regs), SIGINT) == NOTIFY_STOP)
+               touched = 1;
+
+       sum = kstat_irqs_cpu(0, cpu);
+       if (__get_cpu_var(nmi_touch)) {
+               __get_cpu_var(nmi_touch) = 0;
+               touched = 1;
+       }
+       if (!touched && __get_cpu_var(last_irq_sum) == sum) {
+               local_inc(&__get_cpu_var(alert_counter));
+               if (local_read(&__get_cpu_var(alert_counter)) == 5 * nmi_hz)
+                       die_nmi("BUG: NMI Watchdog detected LOCKUP",
+                               regs, panic_on_timeout);
+       } else {
+               __get_cpu_var(last_irq_sum) = sum;
+               local_set(&__get_cpu_var(alert_counter), 0);
+       }
+       if (nmi_usable) {
+               write_pic(picl_value(nmi_hz));
+               pcr_ops->write(pcr_enable);
+       }
+}
+
+static inline unsigned int get_nmi_count(int cpu)
+{
+       return cpu_data(cpu).__nmi_count;
+}
+
+static int endflag __initdata;
+
+static __init void nmi_cpu_busy(void *data)
+{
+       local_irq_enable_in_hardirq();
+       while (endflag == 0)
+               mb();
+}
+
+static void report_broken_nmi(int cpu, int *prev_nmi_count)
+{
+       printk(KERN_CONT "\n");
+
+       printk(KERN_WARNING
+               "WARNING: CPU#%d: NMI appears to be stuck (%d->%d)!\n",
+                       cpu, prev_nmi_count[cpu], get_nmi_count(cpu));
+
+       printk(KERN_WARNING
+               "Please report this to bugzilla.kernel.org,\n");
+       printk(KERN_WARNING
+               "and attach the output of the 'dmesg' command.\n");
+
+       nmi_usable = 0;
+}
+
+static void stop_watchdog(void *unused)
+{
+       pcr_ops->write(PCR_PIC_PRIV);
+}
+
+static int __init check_nmi_watchdog(void)
+{
+       unsigned int *prev_nmi_count;
+       int cpu, err;
+
+       prev_nmi_count = kmalloc(nr_cpu_ids * sizeof(unsigned int), GFP_KERNEL);
+       if (!prev_nmi_count) {
+               err = -ENOMEM;
+               goto error;
+       }
+
+       printk(KERN_INFO "Testing NMI watchdog ... ");
+
+       smp_call_function(nmi_cpu_busy, (void *)&endflag, 0);
+
+       for_each_possible_cpu(cpu)
+               prev_nmi_count[cpu] = get_nmi_count(cpu);
+       local_irq_enable();
+       mdelay((20 * 1000) / nmi_hz); /* wait 20 ticks */
+
+       for_each_online_cpu(cpu) {
+               if (get_nmi_count(cpu) - prev_nmi_count[cpu] <= 5)
+                       report_broken_nmi(cpu, prev_nmi_count);
+       }
+       endflag = 1;
+       if (!nmi_usable) {
+               kfree(prev_nmi_count);
+               err = -ENODEV;
+               goto error;
+       }
+       printk("OK.\n");
+
+       nmi_hz = 1;
+
+       kfree(prev_nmi_count);
+       return 0;
+error:
+       on_each_cpu(stop_watchdog, NULL, 1);
+       return err;
+}
+
+static void start_watchdog(void *unused)
+{
+       pcr_ops->write(PCR_PIC_PRIV);
+       write_pic(picl_value(nmi_hz));
+
+       pcr_ops->write(pcr_enable);
+}
+
+void nmi_adjust_hz(unsigned int new_hz)
+{
+       nmi_hz = new_hz;
+       on_each_cpu(start_watchdog, NULL, 1);
+}
+EXPORT_SYMBOL_GPL(nmi_adjust_hz);
+
+int __init nmi_init(void)
+{
+       nmi_usable = 1;
+
+       on_each_cpu(start_watchdog, NULL, 1);
+
+       return check_nmi_watchdog();
+}
+
+static int __init setup_nmi_watchdog(char *str)
+{
+       if (!strncmp(str, "panic", 5))
+               panic_on_timeout = 1;
+
+       return 0;
+}
+__setup("nmi_watchdog=", setup_nmi_watchdog);
diff --git a/arch/sparc/kernel/pcr.c b/arch/sparc/kernel/pcr.c
new file mode 100644 (file)
index 0000000..92e0dda
--- /dev/null
@@ -0,0 +1,153 @@
+/* pcr.c: Generic sparc64 performance counter infrastructure.
+ *
+ * Copyright (C) 2009 David S. Miller (davem@davemloft.net)
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/pil.h>
+#include <asm/pcr.h>
+#include <asm/nmi.h>
+
+/* This code is shared between various users of the performance
+ * counters.  Users will be oprofile, pseudo-NMI watchdog, and the
+ * perf_counter support layer.
+ */
+
+#define PCR_SUN4U_ENABLE       (PCR_PIC_PRIV | PCR_STRACE | PCR_UTRACE)
+#define PCR_N2_ENABLE          (PCR_PIC_PRIV | PCR_STRACE | PCR_UTRACE | \
+                                PCR_N2_TOE_OV1 | \
+                                (2 << PCR_N2_SL1_SHIFT) | \
+                                (0xff << PCR_N2_MASK1_SHIFT))
+
+u64 pcr_enable;
+unsigned int picl_shift;
+
+/* Performance counter interrupts run unmasked at PIL level 15.
+ * Therefore we can't do things like wakeups and other work
+ * that expects IRQ disabling to be adhered to in locking etc.
+ *
+ * Therefore in such situations we defer the work by signalling
+ * a lower level cpu IRQ.
+ */
+void deferred_pcr_work_irq(int irq, struct pt_regs *regs)
+{
+       clear_softint(1 << PIL_DEFERRED_PCR_WORK);
+}
+
+void schedule_deferred_pcr_work(void)
+{
+       set_softint(1 << PIL_DEFERRED_PCR_WORK);
+}
+
+const struct pcr_ops *pcr_ops;
+EXPORT_SYMBOL_GPL(pcr_ops);
+
+static u64 direct_pcr_read(void)
+{
+       u64 val;
+
+       read_pcr(val);
+       return val;
+}
+
+static void direct_pcr_write(u64 val)
+{
+       write_pcr(val);
+}
+
+static const struct pcr_ops direct_pcr_ops = {
+       .read   = direct_pcr_read,
+       .write  = direct_pcr_write,
+};
+
+static void n2_pcr_write(u64 val)
+{
+       unsigned long ret;
+
+       ret = sun4v_niagara2_setperf(HV_N2_PERF_SPARC_CTL, val);
+       if (val != HV_EOK)
+               write_pcr(val);
+}
+
+static const struct pcr_ops n2_pcr_ops = {
+       .read   = direct_pcr_read,
+       .write  = n2_pcr_write,
+};
+
+static unsigned long perf_hsvc_group;
+static unsigned long perf_hsvc_major;
+static unsigned long perf_hsvc_minor;
+
+static int __init register_perf_hsvc(void)
+{
+       if (tlb_type == hypervisor) {
+               switch (sun4v_chip_type) {
+               case SUN4V_CHIP_NIAGARA1:
+                       perf_hsvc_group = HV_GRP_NIAG_PERF;
+                       break;
+
+               case SUN4V_CHIP_NIAGARA2:
+                       perf_hsvc_group = HV_GRP_N2_CPU;
+                       break;
+
+               default:
+                       return -ENODEV;
+               }
+
+
+               perf_hsvc_major = 1;
+               perf_hsvc_minor = 0;
+               if (sun4v_hvapi_register(perf_hsvc_group,
+                                        perf_hsvc_major,
+                                        &perf_hsvc_minor)) {
+                       printk("perfmon: Could not register hvapi.\n");
+                       return -ENODEV;
+               }
+       }
+       return 0;
+}
+
+static void __init unregister_perf_hsvc(void)
+{
+       if (tlb_type != hypervisor)
+               return;
+       sun4v_hvapi_unregister(perf_hsvc_group);
+}
+
+int __init pcr_arch_init(void)
+{
+       int err = register_perf_hsvc();
+
+       if (err)
+               return err;
+
+       switch (tlb_type) {
+       case hypervisor:
+               pcr_ops = &n2_pcr_ops;
+               pcr_enable = PCR_N2_ENABLE;
+               picl_shift = 2;
+               break;
+
+       case cheetah:
+       case cheetah_plus:
+       case spitfire:
+               pcr_ops = &direct_pcr_ops;
+               pcr_enable = PCR_SUN4U_ENABLE;
+               break;
+
+       default:
+               err = -ENODEV;
+               goto out_unregister;
+       }
+
+       return nmi_init();
+
+out_unregister:
+       unregister_perf_hsvc();
+       return err;
+}
+
+arch_initcall(pcr_arch_init);
index cc8b560..a73954b 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/cpu.h>
 #include <linux/elfcore.h>
 #include <linux/sysrq.h>
+#include <linux/nmi.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
 static void sparc64_yield(int cpu)
 {
-       if (tlb_type != hypervisor)
+       if (tlb_type != hypervisor) {
+               touch_nmi_watchdog();
                return;
+       }
 
        clear_thread_flag(TIF_POLLING_NRFLAG);
        smp_mb__after_clear_bit();
index 49d061f..f2bcfd2 100644 (file)
@@ -354,6 +354,7 @@ static int show_cpuinfo(struct seq_file *m, void *__unused)
        seq_printf(m, 
                   "cpu\t\t: %s\n"
                   "fpu\t\t: %s\n"
+                  "pmu\t\t: %s\n"
                   "prom\t\t: %s\n"
                   "type\t\t: %s\n"
                   "ncpus probed\t: %d\n"
@@ -366,6 +367,7 @@ static int show_cpuinfo(struct seq_file *m, void *__unused)
                   ,
                   sparc_cpu_type,
                   sparc_fpu_type,
+                  sparc_pmu_type,
                   prom_version,
                   ((tlb_type == hypervisor) ?
                    "sun4v" :
index ea92550..d9bdfb9 100644 (file)
@@ -63,7 +63,8 @@ tl0_irq6:     TRAP_IRQ(smp_call_function_single_client, 6)
 #else
 tl0_irq6:      BTRAP(0x46)
 #endif
-tl0_irq7:      BTRAP(0x47) BTRAP(0x48) BTRAP(0x49)
+tl0_irq7:      TRAP_IRQ(deferred_pcr_work_irq, 7)
+tl0_irq8:      BTRAP(0x48) BTRAP(0x49)
 tl0_irq10:     BTRAP(0x4a) BTRAP(0x4b) BTRAP(0x4c) BTRAP(0x4d)
 tl0_irq14:     TRAP_IRQ(timer_interrupt, 14)
 tl0_irq15:     TRAP_NMI_IRQ(perfctr_irq, 15)
index a9e474b..4ab8993 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/interrupt.h>
 #include <linux/kprobes.h>
 #include <linux/kdebug.h>
+#include <linux/percpu.h>
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
@@ -224,6 +225,30 @@ cannot_handle:
        unhandled_fault (address, current, regs);
 }
 
+static void noinline bogus_32bit_fault_tpc(struct pt_regs *regs)
+{
+       static int times;
+
+       if (times++ < 10)
+               printk(KERN_ERR "FAULT[%s:%d]: 32-bit process reports "
+                      "64-bit TPC [%lx]\n",
+                      current->comm, current->pid,
+                      regs->tpc);
+       show_regs(regs);
+}
+
+static void noinline bogus_32bit_fault_address(struct pt_regs *regs,
+                                              unsigned long addr)
+{
+       static int times;
+
+       if (times++ < 10)
+               printk(KERN_ERR "FAULT[%s:%d]: 32-bit process "
+                      "reports 64-bit fault address [%lx]\n",
+                      current->comm, current->pid, addr);
+       show_regs(regs);
+}
+
 asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
 {
        struct mm_struct *mm = current->mm;
@@ -244,6 +269,19 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
            (fault_code & FAULT_CODE_DTLB))
                BUG();
 
+       if (test_thread_flag(TIF_32BIT)) {
+               if (!(regs->tstate & TSTATE_PRIV)) {
+                       if (unlikely((regs->tpc >> 32) != 0)) {
+                               bogus_32bit_fault_tpc(regs);
+                               goto intr_or_no_mm;
+                       }
+               }
+               if (unlikely((address >> 32) != 0)) {
+                       bogus_32bit_fault_address(regs, address);
+                       goto intr_or_no_mm;
+               }
+       }
+
        if (regs->tstate & TSTATE_PRIV) {
                unsigned long tpc = regs->tpc;
 
@@ -264,12 +302,6 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
        if (in_atomic() || !mm)
                goto intr_or_no_mm;
 
-       if (test_thread_flag(TIF_32BIT)) {
-               if (!(regs->tstate & TSTATE_PRIV))
-                       regs->tpc &= 0xffffffff;
-               address &= 0xffffffff;
-       }
-
        if (!down_read_trylock(&mm->mmap_sem)) {
                if ((regs->tstate & TSTATE_PRIV) &&
                    !search_exception_tables(regs->tpc)) {
index d6e170c..d172f86 100644 (file)
 #include <linux/init.h>
  
 #ifdef CONFIG_SPARC64
-#include <asm/hypervisor.h>
-#include <asm/spitfire.h>
-#include <asm/cpudata.h>
-#include <asm/irq.h>
+#include <linux/notifier.h>
+#include <linux/rcupdate.h>
+#include <linux/kdebug.h>
+#include <asm/nmi.h>
 
-static int nmi_enabled;
-
-struct pcr_ops {
-       u64 (*read)(void);
-       void (*write)(u64);
-};
-static const struct pcr_ops *pcr_ops;
-
-static u64 direct_pcr_read(void)
-{
-       u64 val;
-
-       read_pcr(val);
-       return val;
-}
-
-static void direct_pcr_write(u64 val)
-{
-       write_pcr(val);
-}
-
-static const struct pcr_ops direct_pcr_ops = {
-       .read   = direct_pcr_read,
-       .write  = direct_pcr_write,
-};
-
-static void n2_pcr_write(u64 val)
+static int profile_timer_exceptions_notify(struct notifier_block *self,
+                                          unsigned long val, void *data)
 {
-       unsigned long ret;
-
-       ret = sun4v_niagara2_setperf(HV_N2_PERF_SPARC_CTL, val);
-       if (val != HV_EOK)
-               write_pcr(val);
-}
-
-static const struct pcr_ops n2_pcr_ops = {
-       .read   = direct_pcr_read,
-       .write  = n2_pcr_write,
-};
-
-/* In order to commonize as much of the implementation as
- * possible, we use PICH as our counter.  Mostly this is
- * to accomodate Niagara-1 which can only count insn cycles
- * in PICH.
- */
-static u64 picl_value(void)
-{
-       u32 delta = local_cpu_data().clock_tick / HZ;
-
-       return ((u64)((0 - delta) & 0xffffffff)) << 32;
-}
-
-#define PCR_PIC_PRIV           0x00000001 /* PIC access is privileged */
-#define PCR_STRACE             0x00000002 /* Trace supervisor events  */
-#define PCR_UTRACE             0x00000004 /* Trace user events        */
-#define PCR_N2_HTRACE          0x00000008 /* Trace hypervisor events  */
-#define PCR_N2_TOE_OV0         0x00000010 /* Trap if PIC 0 overflows  */
-#define PCR_N2_TOE_OV1         0x00000020 /* Trap if PIC 1 overflows  */
-#define PCR_N2_MASK0           0x00003fc0
-#define PCR_N2_MASK0_SHIFT     6
-#define PCR_N2_SL0             0x0003c000
-#define PCR_N2_SL0_SHIFT       14
-#define PCR_N2_OV0             0x00040000
-#define PCR_N2_MASK1           0x07f80000
-#define PCR_N2_MASK1_SHIFT     19
-#define PCR_N2_SL1             0x78000000
-#define PCR_N2_SL1_SHIFT       27
-#define PCR_N2_OV1             0x80000000
-
-#define PCR_SUN4U_ENABLE       (PCR_PIC_PRIV | PCR_STRACE | PCR_UTRACE)
-#define PCR_N2_ENABLE          (PCR_PIC_PRIV | PCR_STRACE | PCR_UTRACE | \
-                                PCR_N2_TOE_OV1 | \
-                                (2 << PCR_N2_SL1_SHIFT) | \
-                                (0xff << PCR_N2_MASK1_SHIFT))
-
-static u64 pcr_enable = PCR_SUN4U_ENABLE;
-
-static void nmi_handler(struct pt_regs *regs)
-{
-       pcr_ops->write(PCR_PIC_PRIV);
-
-       if (nmi_enabled) {
-               oprofile_add_sample(regs, 0);
-
-               write_pic(picl_value());
-               pcr_ops->write(pcr_enable);
-       }
-}
-
-/* We count "clock cycle" events in the lower 32-bit PIC.
- * Then configure it such that it overflows every HZ, and thus
- * generates a level 15 interrupt at that frequency.
- */
-static void cpu_nmi_start(void *_unused)
-{
-       pcr_ops->write(PCR_PIC_PRIV);
-       write_pic(picl_value());
-
-       pcr_ops->write(pcr_enable);
-}
+       struct die_args *args = (struct die_args *)data;
+       int ret = NOTIFY_DONE;
 
-static void cpu_nmi_stop(void *_unused)
-{
-       pcr_ops->write(PCR_PIC_PRIV);
-}
-
-static int nmi_start(void)
-{
-       int err = register_perfctr_intr(nmi_handler);
-
-       if (!err) {
-               nmi_enabled = 1;
-               wmb();
-               err = on_each_cpu(cpu_nmi_start, NULL, 1);
-               if (err) {
-                       nmi_enabled = 0;
-                       wmb();
-                       on_each_cpu(cpu_nmi_stop, NULL, 1);
-                       release_perfctr_intr(nmi_handler);
-               }
+       switch (val) {
+       case DIE_NMI:
+               oprofile_add_sample(args->regs, 0);
+               ret = NOTIFY_STOP;
+               break;
+       default:
+               break;
        }
-
-       return err;
-}
-
-static void nmi_stop(void)
-{
-       nmi_enabled = 0;
-       wmb();
-
-       on_each_cpu(cpu_nmi_stop, NULL, 1);
-       release_perfctr_intr(nmi_handler);
-       synchronize_sched();
+       return ret;
 }
 
-static unsigned long perf_hsvc_group;
-static unsigned long perf_hsvc_major;
-static unsigned long perf_hsvc_minor;
+static struct notifier_block profile_timer_exceptions_nb = {
+       .notifier_call  = profile_timer_exceptions_notify,
+};
 
-static int __init register_perf_hsvc(void)
+static int timer_start(void)
 {
-       if (tlb_type == hypervisor) {
-               switch (sun4v_chip_type) {
-               case SUN4V_CHIP_NIAGARA1:
-                       perf_hsvc_group = HV_GRP_NIAG_PERF;
-                       break;
-
-               case SUN4V_CHIP_NIAGARA2:
-                       perf_hsvc_group = HV_GRP_N2_CPU;
-                       break;
-
-               default:
-                       return -ENODEV;
-               }
-
-
-               perf_hsvc_major = 1;
-               perf_hsvc_minor = 0;
-               if (sun4v_hvapi_register(perf_hsvc_group,
-                                        perf_hsvc_major,
-                                        &perf_hsvc_minor)) {
-                       printk("perfmon: Could not register N2 hvapi.\n");
-                       return -ENODEV;
-               }
-       }
+       if (register_die_notifier(&profile_timer_exceptions_nb))
+               return 1;
+       nmi_adjust_hz(HZ);
        return 0;
 }
 
-static void unregister_perf_hsvc(void)
+
+static void timer_stop(void)
 {
-       if (tlb_type != hypervisor)
-               return;
-       sun4v_hvapi_unregister(perf_hsvc_group);
+       nmi_adjust_hz(1);
+       unregister_die_notifier(&profile_timer_exceptions_nb);
+       synchronize_sched();  /* Allow already-started NMIs to complete. */
 }
 
-static int oprofile_nmi_init(struct oprofile_operations *ops)
+static int op_nmi_timer_init(struct oprofile_operations *ops)
 {
-       int err = register_perf_hsvc();
-
-       if (err)
-               return err;
-
-       switch (tlb_type) {
-       case hypervisor:
-               pcr_ops = &n2_pcr_ops;
-               pcr_enable = PCR_N2_ENABLE;
-               break;
-
-       case cheetah:
-       case cheetah_plus:
-               pcr_ops = &direct_pcr_ops;
-               break;
-
-       default:
+       if (!nmi_usable)
                return -ENODEV;
-       }
 
-       ops->create_files = NULL;
-       ops->setup = NULL;
-       ops->shutdown = NULL;
-       ops->start = nmi_start;
-       ops->stop = nmi_stop;
+       ops->start = timer_start;
+       ops->stop = timer_stop;
        ops->cpu_type = "timer";
-
-       printk(KERN_INFO "oprofile: Using perfctr based NMI timer interrupt.\n");
-
+       printk(KERN_INFO "oprofile: Using perfctr NMI timer interrupt.\n");
        return 0;
 }
 #endif
@@ -233,7 +73,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
        int ret = -ENODEV;
 
 #ifdef CONFIG_SPARC64
-       ret = oprofile_nmi_init(ops);
+       ret = op_nmi_timer_init(ops);
        if (!ret)
                return ret;
 #endif
@@ -241,10 +81,6 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
        return ret;
 }
 
-
 void oprofile_arch_exit(void)
 {
-#ifdef CONFIG_SPARC64
-       unregister_perf_hsvc();
-#endif
 }
index 256b00b..5a0d76d 100644 (file)
@@ -418,9 +418,9 @@ ENTRY(ia32_syscall)
        orl   $TS_COMPAT,TI_status(%r10)
        testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
        jnz ia32_tracesys
-ia32_do_syscall:       
        cmpl $(IA32_NR_syscalls-1),%eax
-       ja  int_ret_from_sys_call       /* ia32_tracesys has set RAX(%rsp) */
+       ja ia32_badsys
+ia32_do_call:
        IA32_ARG_FIXUP
        call *ia32_sys_call_table(,%rax,8) # xxx: rip relative
 ia32_sysret:
@@ -435,7 +435,9 @@ ia32_tracesys:
        call syscall_trace_enter
        LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
        RESTORE_REST
-       jmp ia32_do_syscall
+       cmpl $(IA32_NR_syscalls-1),%eax
+       ja  int_ret_from_sys_call       /* ia32_tracesys has set RAX(%rsp) */
+       jmp ia32_do_call
 END(ia32_syscall)
 
 ia32_badsys:
index 4b6df24..115449f 100644 (file)
@@ -1436,7 +1436,7 @@ static int __init detect_init_APIC(void)
        switch (boot_cpu_data.x86_vendor) {
        case X86_VENDOR_AMD:
                if ((boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model > 1) ||
-                   (boot_cpu_data.x86 == 15))
+                   (boot_cpu_data.x86 >= 15))
                        break;
                goto no_apic;
        case X86_VENDOR_INTEL:
index 48533d7..da299eb 100644 (file)
@@ -36,8 +36,11 @@ static struct _cache_table cache_table[] __cpuinitdata =
 {
        { 0x06, LVL_1_INST, 8 },        /* 4-way set assoc, 32 byte line size */
        { 0x08, LVL_1_INST, 16 },       /* 4-way set assoc, 32 byte line size */
+       { 0x09, LVL_1_INST, 32 },       /* 4-way set assoc, 64 byte line size */
        { 0x0a, LVL_1_DATA, 8 },        /* 2 way set assoc, 32 byte line size */
        { 0x0c, LVL_1_DATA, 16 },       /* 4-way set assoc, 32 byte line size */
+       { 0x0d, LVL_1_DATA, 16 },       /* 4-way set assoc, 64 byte line size */
+       { 0x21, LVL_2,      256 },      /* 8-way set assoc, 64 byte line size */
        { 0x22, LVL_3,      512 },      /* 4-way set assoc, sectored cache, 64 byte line size */
        { 0x23, LVL_3,      1024 },     /* 8-way set assoc, sectored cache, 64 byte line size */
        { 0x25, LVL_3,      2048 },     /* 8-way set assoc, sectored cache, 64 byte line size */
@@ -85,6 +88,18 @@ static struct _cache_table cache_table[] __cpuinitdata =
        { 0x85, LVL_2,    2048 },       /* 8-way set assoc, 32 byte line size */
        { 0x86, LVL_2,     512 },       /* 4-way set assoc, 64 byte line size */
        { 0x87, LVL_2,    1024 },       /* 8-way set assoc, 64 byte line size */
+       { 0xd0, LVL_3,     512 },       /* 4-way set assoc, 64 byte line size */
+       { 0xd1, LVL_3,    1024 },       /* 4-way set assoc, 64 byte line size */
+       { 0xd2, LVL_3,    2048 },       /* 4-way set assoc, 64 byte line size */
+       { 0xd6, LVL_3,    1024 },       /* 8-way set assoc, 64 byte line size */
+       { 0xd7, LVL_3,    2038 },       /* 8-way set assoc, 64 byte line size */
+       { 0xd8, LVL_3,    4096 },       /* 12-way set assoc, 64 byte line size */
+       { 0xdc, LVL_3,    2048 },       /* 12-way set assoc, 64 byte line size */
+       { 0xdd, LVL_3,    4096 },       /* 12-way set assoc, 64 byte line size */
+       { 0xde, LVL_3,    8192 },       /* 12-way set assoc, 64 byte line size */
+       { 0xe2, LVL_3,    2048 },       /* 16-way set assoc, 64 byte line size */
+       { 0xe3, LVL_3,    4096 },       /* 16-way set assoc, 64 byte line size */
+       { 0xe4, LVL_3,    8192 },       /* 16-way set assoc, 64 byte line size */
        { 0x00, 0, 0}
 };
 
index e28c7a9..a134621 100644 (file)
@@ -346,6 +346,7 @@ ENTRY(save_args)
        popq_cfi %rax                   /* move return address... */
        mov %gs:pda_irqstackptr,%rsp
        EMPTY_FRAME 0
+       pushq_cfi %rbp                  /* backlink for unwinder */
        pushq_cfi %rax                  /* ... to the new stack */
        /*
         * We entered an interrupt context - irqs are off:
index 1c4a130..9b0c480 100644 (file)
@@ -2528,14 +2528,15 @@ static void irq_complete_move(struct irq_desc **descp)
 
        vector = ~get_irq_regs()->orig_ax;
        me = smp_processor_id();
+
+       if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain)) {
 #ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
                *descp = desc = move_irq_desc(desc, me);
                /* get the new one */
                cfg = desc->chip_data;
 #endif
-
-       if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain))
                send_cleanup_vector(cfg);
+       }
 }
 #else
 static inline void irq_complete_move(struct irq_desc **descp) {}
index 1507ad4..10a09c2 100644 (file)
@@ -78,15 +78,6 @@ void __init init_ISA_irqs(void)
        }
 }
 
-/*
- * IRQ2 is cascade interrupt to second interrupt controller
- */
-static struct irqaction irq2 = {
-       .handler = no_action,
-       .mask = CPU_MASK_NONE,
-       .name = "cascade",
-};
-
 DEFINE_PER_CPU(vector_irq_t, vector_irq) = {
        [0 ... IRQ0_VECTOR - 1] = -1,
        [IRQ0_VECTOR] = 0,
@@ -178,9 +169,6 @@ void __init native_init_IRQ(void)
        alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
 #endif
 
-       if (!acpi_ioapic)
-               setup_irq(2, &irq2);
-
        /* setup after call gates are initialised (usually add in
         * the architecture specific gates)
         */
index 309949e..697d1b7 100644 (file)
@@ -172,7 +172,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_4,
                         ich_force_enable_hpet);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_7,
                         ich_force_enable_hpet);
-
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x3a16,  /* ICH10 */
+                        ich_force_enable_hpet);
 
 static struct pci_dev *cached_dev;
 
index df167f2..a265a7c 100644 (file)
@@ -38,6 +38,15 @@ void __init pre_intr_init_hook(void)
        init_ISA_irqs();
 }
 
+/*
+ * IRQ2 is cascade interrupt to second interrupt controller
+ */
+static struct irqaction irq2 = {
+       .handler = no_action,
+       .mask = CPU_MASK_NONE,
+       .name = "cascade",
+};
+
 /**
  * intr_init_hook - post gate setup interrupt initialisation
  *
@@ -53,6 +62,9 @@ void __init intr_init_hook(void)
                if (x86_quirks->arch_intr_init())
                        return;
        }
+       if (!acpi_ioapic)
+               setup_irq(2, &irq2);
+
 }
 
 /**
index a580b95..d914a79 100644 (file)
@@ -33,13 +33,23 @@ void __init intr_init_hook(void)
        setup_irq(2, &irq2);
 }
 
-void __init pre_setup_arch_hook(void)
+static void voyager_disable_tsc(void)
 {
        /* Voyagers run their CPUs from independent clocks, so disable
         * the TSC code because we can't sync them */
        setup_clear_cpu_cap(X86_FEATURE_TSC);
 }
 
+void __init pre_setup_arch_hook(void)
+{
+       voyager_disable_tsc();
+}
+
+void __init pre_time_init_hook(void)
+{
+       voyager_disable_tsc();
+}
+
 void __init trap_init_hook(void)
 {
 }
index 9840b7e..7ffcdee 100644 (file)
@@ -81,7 +81,7 @@ static void enable_local_vic_irq(unsigned int irq);
 static void disable_local_vic_irq(unsigned int irq);
 static void before_handle_vic_irq(unsigned int irq);
 static void after_handle_vic_irq(unsigned int irq);
-static void set_vic_irq_affinity(unsigned int irq, cpumask_t mask);
+static void set_vic_irq_affinity(unsigned int irq, const struct cpumask *mask);
 static void ack_vic_irq(unsigned int irq);
 static void vic_enable_cpi(void);
 static void do_boot_cpu(__u8 cpuid);
@@ -211,8 +211,6 @@ static __u32 cpu_booted_map;
 static cpumask_t smp_commenced_mask = CPU_MASK_NONE;
 
 /* This is for the new dynamic CPU boot code */
-cpumask_t cpu_callin_map = CPU_MASK_NONE;
-cpumask_t cpu_callout_map = CPU_MASK_NONE;
 
 /* The per processor IRQ masks (these are usually kept in sync) */
 static __u16 vic_irq_mask[NR_CPUS] __cacheline_aligned;
@@ -378,7 +376,7 @@ void __init find_smp_config(void)
        cpus_addr(phys_cpu_present_map)[0] |=
            voyager_extended_cmos_read(VOYAGER_PROCESSOR_PRESENT_MASK +
                                       3) << 24;
-       cpu_possible_map = phys_cpu_present_map;
+       init_cpu_possible(&phys_cpu_present_map);
        printk("VOYAGER SMP: phys_cpu_present_map = 0x%lx\n",
               cpus_addr(phys_cpu_present_map)[0]);
        /* Here we set up the VIC to enable SMP */
@@ -1599,16 +1597,16 @@ static void after_handle_vic_irq(unsigned int irq)
  * change the mask and then do an interrupt enable CPI to re-enable on
  * the selected processors */
 
-void set_vic_irq_affinity(unsigned int irq, cpumask_t mask)
+void set_vic_irq_affinity(unsigned int irq, const struct cpumask *mask)
 {
        /* Only extended processors handle interrupts */
        unsigned long real_mask;
        unsigned long irq_mask = 1 << irq;
        int cpu;
 
-       real_mask = cpus_addr(mask)[0] & voyager_extended_vic_processors;
+       real_mask = cpus_addr(*mask)[0] & voyager_extended_vic_processors;
 
-       if (cpus_addr(mask)[0] == 0)
+       if (cpus_addr(*mask)[0] == 0)
                /* can't have no CPUs to accept the interrupt -- extremely
                 * bad things will happen */
                return;
@@ -1750,10 +1748,11 @@ static void __cpuinit voyager_smp_prepare_boot_cpu(void)
        init_gdt(smp_processor_id());
        switch_to_new_gdt();
 
-       cpu_set(smp_processor_id(), cpu_online_map);
-       cpu_set(smp_processor_id(), cpu_callout_map);
-       cpu_set(smp_processor_id(), cpu_possible_map);
-       cpu_set(smp_processor_id(), cpu_present_map);
+       cpu_online_map = cpumask_of_cpu(smp_processor_id());
+       cpu_callout_map = cpumask_of_cpu(smp_processor_id());
+       cpu_callin_map = CPU_MASK_NONE;
+       cpu_present_map = cpumask_of_cpu(smp_processor_id());
+
 }
 
 static int __cpuinit voyager_cpu_up(unsigned int cpu)
@@ -1783,9 +1782,9 @@ void __init smp_setup_processor_id(void)
        x86_write_percpu(cpu_number, hard_smp_processor_id());
 }
 
-static void voyager_send_call_func(cpumask_t callmask)
+static void voyager_send_call_func(const struct cpumask *callmask)
 {
-       __u32 mask = cpus_addr(callmask)[0] & ~(1 << smp_processor_id());
+       __u32 mask = cpus_addr(*callmask)[0] & ~(1 << smp_processor_id());
        send_CPI(mask, VIC_CALL_FUNCTION_CPI);
 }
 
index 90dfae5..c76ef1d 100644 (file)
@@ -603,8 +603,6 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
 
        si_code = SEGV_MAPERR;
 
-       if (notify_page_fault(regs))
-               return;
        if (unlikely(kmmio_fault(regs, address)))
                return;
 
@@ -634,6 +632,9 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
                if (spurious_fault(address, error_code))
                        return;
 
+               /* kprobes don't want to hook the spurious faults. */
+               if (notify_page_fault(regs))
+                       return;
                /*
                 * Don't take the mm semaphore here. If we fixup a prefetch
                 * fault we could otherwise deadlock.
@@ -641,6 +642,9 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
                goto bad_area_nosemaphore;
        }
 
+       /* kprobes don't want to hook the spurious faults. */
+       if (notify_page_fault(regs))
+               return;
 
        /*
         * It's safe to allow irq's after cr2 has been saved and the
index 8589382..fa3e107 100644 (file)
@@ -19,8 +19,10 @@ DECLARE_PER_CPU(unsigned long, xen_mc_irq_flags);
    paired with xen_mc_issue() */
 static inline void xen_mc_batch(void)
 {
+       unsigned long flags;
        /* need to disable interrupts until this entry is complete */
-       local_irq_save(__get_cpu_var(xen_mc_irq_flags));
+       local_irq_save(flags);
+       __get_cpu_var(xen_mc_irq_flags) = flags;
 }
 
 static inline struct multicall_space xen_mc_entry(size_t args)
index 77bba4c..a603bbf 100644 (file)
 #define EM_MSG_LED_VALUE_ON           0x00010000
 
 static int ahci_skip_host_reset;
+static int ahci_ignore_sss;
+
 module_param_named(skip_host_reset, ahci_skip_host_reset, int, 0444);
 MODULE_PARM_DESC(skip_host_reset, "skip global host reset (0=don't skip, 1=skip)");
 
+module_param_named(ignore_sss, ahci_ignore_sss, int, 0444);
+MODULE_PARM_DESC(ignore_sss, "Ignore staggered spinup flag (0=don't ignore, 1=ignore)");
+
 static int ahci_enable_alpm(struct ata_port *ap,
                enum link_pm policy);
 static void ahci_disable_alpm(struct ata_port *ap);
@@ -2692,8 +2697,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        host->iomap = pcim_iomap_table(pdev);
        host->private_data = hpriv;
 
-       if (!(hpriv->cap & HOST_CAP_SSS))
+       if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
                host->flags |= ATA_HOST_PARALLEL_SCAN;
+       else
+               printk(KERN_INFO "ahci: SSS flag set, parallel bus scan disabled\n");
 
        if (pi.flags & ATA_FLAG_EM)
                ahci_reset_em(host);
index 88c2428..9fbf059 100644 (file)
@@ -164,6 +164,11 @@ MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 
 
+static bool ata_sstatus_online(u32 sstatus)
+{
+       return (sstatus & 0xf) == 0x3;
+}
+
 /**
  *     ata_link_next - link iteration helper
  *     @link: the previous link, NULL to start
@@ -1015,18 +1020,6 @@ static const char *sata_spd_string(unsigned int spd)
        return spd_str[spd - 1];
 }
 
-void ata_dev_disable(struct ata_device *dev)
-{
-       if (ata_dev_enabled(dev)) {
-               if (ata_msg_drv(dev->link->ap))
-                       ata_dev_printk(dev, KERN_WARNING, "disabled\n");
-               ata_acpi_on_disable(dev);
-               ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO0 |
-                                            ATA_DNXFER_QUIET);
-               dev->class++;
-       }
-}
-
 static int ata_dev_set_dipm(struct ata_device *dev, enum link_pm policy)
 {
        struct ata_link *link = dev->link;
@@ -2239,6 +2232,40 @@ retry:
        return rc;
 }
 
+static int ata_do_link_spd_horkage(struct ata_device *dev)
+{
+       struct ata_link *plink = ata_dev_phys_link(dev);
+       u32 target, target_limit;
+
+       if (!sata_scr_valid(plink))
+               return 0;
+
+       if (dev->horkage & ATA_HORKAGE_1_5_GBPS)
+               target = 1;
+       else
+               return 0;
+
+       target_limit = (1 << target) - 1;
+
+       /* if already on stricter limit, no need to push further */
+       if (plink->sata_spd_limit <= target_limit)
+               return 0;
+
+       plink->sata_spd_limit = target_limit;
+
+       /* Request another EH round by returning -EAGAIN if link is
+        * going faster than the target speed.  Forward progress is
+        * guaranteed by setting sata_spd_limit to target_limit above.
+        */
+       if (plink->sata_spd > target) {
+               ata_dev_printk(dev, KERN_INFO,
+                              "applying link speed limit horkage to %s\n",
+                              sata_spd_string(target));
+               return -EAGAIN;
+       }
+       return 0;
+}
+
 static inline u8 ata_dev_knobble(struct ata_device *dev)
 {
        struct ata_port *ap = dev->link->ap;
@@ -2329,6 +2356,10 @@ int ata_dev_configure(struct ata_device *dev)
                return 0;
        }
 
+       rc = ata_do_link_spd_horkage(dev);
+       if (rc)
+               return rc;
+
        /* let ACPI work its magic */
        rc = ata_acpi_on_devcfg(dev);
        if (rc)
@@ -2784,7 +2815,7 @@ int ata_bus_probe(struct ata_port *ap)
                        /* This is the last chance, better to slow
                         * down than lose it.
                         */
-                       sata_down_spd_limit(&ap->link);
+                       sata_down_spd_limit(&ap->link, 0);
                        ata_down_xfermask_limit(dev, ATA_DNXFER_PIO);
                }
        }
@@ -2880,21 +2911,27 @@ void ata_port_disable(struct ata_port *ap)
 /**
  *     sata_down_spd_limit - adjust SATA spd limit downward
  *     @link: Link to adjust SATA spd limit for
+ *     @spd_limit: Additional limit
  *
  *     Adjust SATA spd limit of @link downward.  Note that this
  *     function only adjusts the limit.  The change must be applied
  *     using sata_set_spd().
  *
+ *     If @spd_limit is non-zero, the speed is limited to equal to or
+ *     lower than @spd_limit if such speed is supported.  If
+ *     @spd_limit is slower than any supported speed, only the lowest
+ *     supported speed is allowed.
+ *
  *     LOCKING:
  *     Inherited from caller.
  *
  *     RETURNS:
  *     0 on success, negative errno on failure
  */
-int sata_down_spd_limit(struct ata_link *link)
+int sata_down_spd_limit(struct ata_link *link, u32 spd_limit)
 {
        u32 sstatus, spd, mask;
-       int rc, highbit;
+       int rc, bit;
 
        if (!sata_scr_valid(link))
                return -EOPNOTSUPP;
@@ -2903,7 +2940,7 @@ int sata_down_spd_limit(struct ata_link *link)
         * If not, use cached value in link->sata_spd.
         */
        rc = sata_scr_read(link, SCR_STATUS, &sstatus);
-       if (rc == 0)
+       if (rc == 0 && ata_sstatus_online(sstatus))
                spd = (sstatus >> 4) & 0xf;
        else
                spd = link->sata_spd;
@@ -2913,8 +2950,8 @@ int sata_down_spd_limit(struct ata_link *link)
                return -EINVAL;
 
        /* unconditionally mask off the highest bit */
-       highbit = fls(mask) - 1;
-       mask &= ~(1 << highbit);
+       bit = fls(mask) - 1;
+       mask &= ~(1 << bit);
 
        /* Mask off all speeds higher than or equal to the current
         * one.  Force 1.5Gbps if current SPD is not available.
@@ -2928,6 +2965,15 @@ int sata_down_spd_limit(struct ata_link *link)
        if (!mask)
                return -EINVAL;
 
+       if (spd_limit) {
+               if (mask & ((1 << spd_limit) - 1))
+                       mask &= (1 << spd_limit) - 1;
+               else {
+                       bit = ffs(mask) - 1;
+                       mask = 1 << bit;
+               }
+       }
+
        link->sata_spd_limit = mask;
 
        ata_link_printk(link, KERN_WARNING, "limiting SATA link speed to %s\n",
@@ -4215,6 +4261,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        /* Devices that do not need bridging limits applied */
        { "MTRON MSP-SATA*",            NULL,   ATA_HORKAGE_BRIDGE_OK, },
 
+       /* Devices which aren't very happy with higher link speeds */
+       { "WD My Book",                 NULL,   ATA_HORKAGE_1_5_GBPS, },
+
        /* End Marker */
        { }
 };
@@ -4709,8 +4758,7 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
 
 /**
  *     ata_qc_new - Request an available ATA command, for queueing
- *     @ap: Port associated with device @dev
- *     @dev: Device from whom we request an available command structure
+ *     @ap: target port
  *
  *     LOCKING:
  *     None.
@@ -5175,7 +5223,7 @@ bool ata_phys_link_online(struct ata_link *link)
        u32 sstatus;
 
        if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0 &&
-           (sstatus & 0xf) == 0x3)
+           ata_sstatus_online(sstatus))
                return true;
        return false;
 }
@@ -5199,7 +5247,7 @@ bool ata_phys_link_offline(struct ata_link *link)
        u32 sstatus;
 
        if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0 &&
-           (sstatus & 0xf) != 0x3)
+           !ata_sstatus_online(sstatus))
                return true;
        return false;
 }
@@ -5412,8 +5460,8 @@ void ata_dev_init(struct ata_device *dev)
        dev->horkage = 0;
        spin_unlock_irqrestore(ap->lock, flags);
 
-       memset((void *)dev + ATA_DEVICE_CLEAR_OFFSET, 0,
-              sizeof(*dev) - ATA_DEVICE_CLEAR_OFFSET);
+       memset((void *)dev + ATA_DEVICE_CLEAR_BEGIN, 0,
+              ATA_DEVICE_CLEAR_END - ATA_DEVICE_CLEAR_BEGIN);
        dev->pio_mask = UINT_MAX;
        dev->mwdma_mask = UINT_MAX;
        dev->udma_mask = UINT_MAX;
index 8147a83..ce2ef04 100644 (file)
@@ -82,6 +82,10 @@ enum {
        ATA_EH_FASTDRAIN_INTERVAL       =  3000,
 
        ATA_EH_UA_TRIES                 = 5,
+
+       /* probe speed down parameters, see ata_eh_schedule_probe() */
+       ATA_EH_PROBE_TRIAL_INTERVAL     = 60000,        /* 1 min */
+       ATA_EH_PROBE_TRIALS             = 2,
 };
 
 /* The following table determines how we sequence resets.  Each entry
@@ -1175,6 +1179,32 @@ void ata_eh_qc_retry(struct ata_queued_cmd *qc)
        __ata_eh_qc_complete(qc);
 }
 
+/**
+ *     ata_dev_disable - disable ATA device
+ *     @dev: ATA device to disable
+ *
+ *     Disable @dev.
+ *
+ *     Locking:
+ *     EH context.
+ */
+void ata_dev_disable(struct ata_device *dev)
+{
+       if (!ata_dev_enabled(dev))
+               return;
+
+       if (ata_msg_drv(dev->link->ap))
+               ata_dev_printk(dev, KERN_WARNING, "disabled\n");
+       ata_acpi_on_disable(dev);
+       ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO0 | ATA_DNXFER_QUIET);
+       dev->class++;
+
+       /* From now till the next successful probe, ering is used to
+        * track probe failures.  Clear accumulated device error info.
+        */
+       ata_ering_clear(&dev->ering);
+}
+
 /**
  *     ata_eh_detach_dev - detach ATA device
  *     @dev: ATA device to detach
@@ -1849,7 +1879,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev,
        /* speed down? */
        if (verdict & ATA_EH_SPDN_SPEED_DOWN) {
                /* speed down SATA link speed if possible */
-               if (sata_down_spd_limit(link) == 0) {
+               if (sata_down_spd_limit(link, 0) == 0) {
                        action |= ATA_EH_RESET;
                        goto done;
                }
@@ -2601,11 +2631,11 @@ int ata_eh_reset(struct ata_link *link, int classify,
        }
 
        if (try == max_tries - 1) {
-               sata_down_spd_limit(link);
+               sata_down_spd_limit(link, 0);
                if (slave)
-                       sata_down_spd_limit(slave);
+                       sata_down_spd_limit(slave, 0);
        } else if (rc == -EPIPE)
-               sata_down_spd_limit(failed_link);
+               sata_down_spd_limit(failed_link, 0);
 
        if (hardreset)
                reset = hardreset;
@@ -2744,6 +2774,8 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
                                                     readid_flags, dev->id);
                        switch (rc) {
                        case 0:
+                               /* clear error info accumulated during probe */
+                               ata_ering_clear(&dev->ering);
                                new_mask |= 1 << dev->devno;
                                break;
                        case -ENOENT:
@@ -2947,9 +2979,24 @@ static int ata_eh_skip_recovery(struct ata_link *link)
        return 1;
 }
 
+static int ata_count_probe_trials_cb(struct ata_ering_entry *ent, void *void_arg)
+{
+       u64 interval = msecs_to_jiffies(ATA_EH_PROBE_TRIAL_INTERVAL);
+       u64 now = get_jiffies_64();
+       int *trials = void_arg;
+
+       if (ent->timestamp < now - min(now, interval))
+               return -1;
+
+       (*trials)++;
+       return 0;
+}
+
 static int ata_eh_schedule_probe(struct ata_device *dev)
 {
        struct ata_eh_context *ehc = &dev->link->eh_context;
+       struct ata_link *link = ata_dev_phys_link(dev);
+       int trials = 0;
 
        if (!(ehc->i.probe_mask & (1 << dev->devno)) ||
            (ehc->did_probe_mask & (1 << dev->devno)))
@@ -2962,6 +3009,25 @@ static int ata_eh_schedule_probe(struct ata_device *dev)
        ehc->saved_xfer_mode[dev->devno] = 0;
        ehc->saved_ncq_enabled &= ~(1 << dev->devno);
 
+       /* Record and count probe trials on the ering.  The specific
+        * error mask used is irrelevant.  Because a successful device
+        * detection clears the ering, this count accumulates only if
+        * there are consecutive failed probes.
+        *
+        * If the count is equal to or higher than ATA_EH_PROBE_TRIALS
+        * in the last ATA_EH_PROBE_TRIAL_INTERVAL, link speed is
+        * forced to 1.5Gbps.
+        *
+        * This is to work around cases where failed link speed
+        * negotiation results in device misdetection leading to
+        * infinite DEVXCHG or PHRDY CHG events.
+        */
+       ata_ering_record(&dev->ering, 0, AC_ERR_OTHER);
+       ata_ering_map(&dev->ering, ata_count_probe_trials_cb, &trials);
+
+       if (trials > ATA_EH_PROBE_TRIALS)
+               sata_down_spd_limit(link, 1);
+
        return 1;
 }
 
@@ -2969,7 +3035,11 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err)
 {
        struct ata_eh_context *ehc = &dev->link->eh_context;
 
-       ehc->tries[dev->devno]--;
+       /* -EAGAIN from EH routine indicates retry without prejudice.
+        * The requester is responsible for ensuring forward progress.
+        */
+       if (err != -EAGAIN)
+               ehc->tries[dev->devno]--;
 
        switch (err) {
        case -ENODEV:
@@ -2979,12 +3049,13 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err)
                /* give it just one more chance */
                ehc->tries[dev->devno] = min(ehc->tries[dev->devno], 1);
        case -EIO:
-               if (ehc->tries[dev->devno] == 1 && dev->pio_mode > XFER_PIO_0) {
+               if (ehc->tries[dev->devno] == 1) {
                        /* This is the last chance, better to slow
                         * down than lose it.
                         */
-                       sata_down_spd_limit(ata_dev_phys_link(dev));
-                       ata_down_xfermask_limit(dev, ATA_DNXFER_PIO);
+                       sata_down_spd_limit(ata_dev_phys_link(dev), 0);
+                       if (dev->pio_mode > XFER_PIO_0)
+                               ata_down_xfermask_limit(dev, ATA_DNXFER_PIO);
                }
        }
 
index 98ca07a..619f2c3 100644 (file)
@@ -729,7 +729,7 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
                if (tries) {
                        /* consecutive revalidation failures? speed down */
                        if (reval_failed)
-                               sata_down_spd_limit(link);
+                               sata_down_spd_limit(link, 0);
                        else
                                reval_failed = 1;
 
index 3c4c5ae..b9747fa 100644 (file)
@@ -415,6 +415,7 @@ int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev,
 
 /**
  *     ata_get_identity - Handler for HDIO_GET_IDENTITY ioctl
+ *     @ap: target port
  *     @sdev: SCSI device to get identify data for
  *     @arg: User buffer area for identify data
  *
index fe2839e..cea8014 100644 (file)
@@ -79,7 +79,6 @@ extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
                           u64 block, u32 n_block, unsigned int tf_flags,
                           unsigned int tag);
 extern u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev);
-extern void ata_dev_disable(struct ata_device *dev);
 extern void ata_pio_queue_task(struct ata_port *ap, void *data,
                               unsigned long delay);
 extern void ata_port_flush_task(struct ata_port *ap);
@@ -100,7 +99,7 @@ extern int ata_dev_reread_id(struct ata_device *dev, unsigned int readid_flags);
 extern int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
                              unsigned int readid_flags);
 extern int ata_dev_configure(struct ata_device *dev);
-extern int sata_down_spd_limit(struct ata_link *link);
+extern int sata_down_spd_limit(struct ata_link *link, u32 spd_limit);
 extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel);
 extern void ata_sg_clean(struct ata_queued_cmd *qc);
 extern void ata_qc_free(struct ata_queued_cmd *qc);
@@ -160,6 +159,7 @@ extern void ata_scsi_error(struct Scsi_Host *host);
 extern void ata_port_wait_eh(struct ata_port *ap);
 extern void ata_eh_fastdrain_timerfn(unsigned long arg);
 extern void ata_qc_schedule_eh(struct ata_queued_cmd *qc);
+extern void ata_dev_disable(struct ata_device *dev);
 extern void ata_eh_detach_dev(struct ata_device *dev);
 extern void ata_eh_about_to_do(struct ata_link *link, struct ata_device *dev,
                               unsigned int action);
index 3080f37..f1b26f7 100644 (file)
@@ -12,7 +12,7 @@
  *
  * Probe code based on drivers/ide/legacy/qd65xx.c
  * Rewritten from the work of Colten Edwards <pje120@cs.usask.ca> by
- * Samuel Thibault <samuel.thibault@fnac.net>
+ * Samuel Thibault <samuel.thibault@ens-lyon.org>
  */
 
 #include <linux/kernel.h>
index f2d8a02..4ae1a41 100644 (file)
@@ -663,8 +663,8 @@ static const struct pci_device_id mv_pci_tbl[] = {
        { PCI_VDEVICE(MARVELL, 0x5081), chip_508x },
        /* RocketRAID 1720/174x have different identifiers */
        { PCI_VDEVICE(TTI, 0x1720), chip_6042 },
-       { PCI_VDEVICE(TTI, 0x1740), chip_508x },
-       { PCI_VDEVICE(TTI, 0x1742), chip_508x },
+       { PCI_VDEVICE(TTI, 0x1740), chip_6042 },
+       { PCI_VDEVICE(TTI, 0x1742), chip_6042 },
 
        { PCI_VDEVICE(MARVELL, 0x6040), chip_604x },
        { PCI_VDEVICE(MARVELL, 0x6041), chip_604x },
index c49ad0e..444af04 100644 (file)
@@ -436,11 +436,16 @@ static struct ata_port_operations nv_nf2_ops = {
        .hardreset              = nv_noclassify_hardreset,
 };
 
-/* CK804 finally gets hardreset right */
+/* For initial probing after boot and hot plugging, hardreset mostly
+ * works fine on CK804 but curiously, reprobing on the initial port by
+ * rescanning or rmmod/insmod fails to acquire the initial D2H Reg FIS
+ * in somewhat undeterministic way.  Use noclassify hardreset.
+ */
 static struct ata_port_operations nv_ck804_ops = {
        .inherits               = &nv_common_ops,
        .freeze                 = nv_ck804_freeze,
        .thaw                   = nv_ck804_thaw,
+       .hardreset              = nv_noclassify_hardreset,
        .host_stop              = nv_ck804_host_stop,
 };
 
index 9f02959..d009160 100644 (file)
@@ -324,7 +324,7 @@ static void sil_fill_sg(struct ata_queued_cmd *qc)
 
                prd->addr = cpu_to_le32(addr);
                prd->flags_len = cpu_to_le32(sg_len);
-               VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", pi, addr, sg_len);
+               VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", si, addr, sg_len);
 
                last_prd = prd;
                prd++;
index f5be808..735bbe2 100644 (file)
@@ -761,7 +761,7 @@ source "drivers/char/hw_random/Kconfig"
 
 config NVRAM
        tristate "/dev/nvram support"
-       depends on ATARI || X86 || ARM || GENERIC_NVRAM
+       depends on ATARI || X86 || (ARM && RTC_DRV_CMOS) || GENERIC_NVRAM
        ---help---
          If you say Y here and create a character special file /dev/nvram
          with major number 10 and minor number 144 using mknod ("man mknod"),
index b60be7b..f146e90 100644 (file)
@@ -1713,8 +1713,8 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
                for (i = 0; i < SX_NBOARDS; i++)
                        sx_dprintk(SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags);
                sx_dprintk(SX_DEBUG_FIRMWARE, "\n");
-               unlock_kernel();
-               return -EIO;
+               rc = -EIO;
+               goto out;
        }
 
        switch (cmd) {
@@ -1747,7 +1747,8 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
                break;
        case SXIO_DO_RAMTEST:
                if (sx_initialized)     /* Already initialized: better not ramtest the board.  */
-                       return -EPERM;
+                       rc = -EPERM;
+                       break;
                if (IS_SX_BOARD(board)) {
                        rc = do_memtest(board, 0, 0x7000);
                        if (!rc)
@@ -1844,6 +1845,7 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
                rc = -ENOTTY;
                break;
        }
+out:
        unlock_kernel();
        func_exit();
        return rc;
index 5543384..33bd753 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/device.h>
 #include <linux/dca.h>
 
-#define DCA_VERSION "1.4"
+#define DCA_VERSION "1.8"
 
 MODULE_VERSION(DCA_VERSION);
 MODULE_LICENSE("GPL");
@@ -60,16 +60,17 @@ int dca_add_requester(struct device *dev)
 {
        struct dca_provider *dca;
        int err, slot = -ENODEV;
+       unsigned long flags;
 
        if (!dev)
                return -EFAULT;
 
-       spin_lock(&dca_lock);
+       spin_lock_irqsave(&dca_lock, flags);
 
        /* check if the requester has not been added already */
        dca = dca_find_provider_by_dev(dev);
        if (dca) {
-               spin_unlock(&dca_lock);
+               spin_unlock_irqrestore(&dca_lock, flags);
                return -EEXIST;
        }
 
@@ -78,19 +79,21 @@ int dca_add_requester(struct device *dev)
                if (slot >= 0)
                        break;
        }
-       if (slot < 0) {
-               spin_unlock(&dca_lock);
+
+       spin_unlock_irqrestore(&dca_lock, flags);
+
+       if (slot < 0)
                return slot;
-       }
 
        err = dca_sysfs_add_req(dca, dev, slot);
        if (err) {
-               dca->ops->remove_requester(dca, dev);
-               spin_unlock(&dca_lock);
+               spin_lock_irqsave(&dca_lock, flags);
+               if (dca == dca_find_provider_by_dev(dev))
+                       dca->ops->remove_requester(dca, dev);
+               spin_unlock_irqrestore(&dca_lock, flags);
                return err;
        }
 
-       spin_unlock(&dca_lock);
        return 0;
 }
 EXPORT_SYMBOL_GPL(dca_add_requester);
@@ -103,25 +106,25 @@ int dca_remove_requester(struct device *dev)
 {
        struct dca_provider *dca;
        int slot;
+       unsigned long flags;
 
        if (!dev)
                return -EFAULT;
 
-       spin_lock(&dca_lock);
+       spin_lock_irqsave(&dca_lock, flags);
        dca = dca_find_provider_by_dev(dev);
        if (!dca) {
-               spin_unlock(&dca_lock);
+               spin_unlock_irqrestore(&dca_lock, flags);
                return -ENODEV;
        }
        slot = dca->ops->remove_requester(dca, dev);
-       if (slot < 0) {
-               spin_unlock(&dca_lock);
+       spin_unlock_irqrestore(&dca_lock, flags);
+
+       if (slot < 0)
                return slot;
-       }
 
        dca_sysfs_remove_req(dca, slot);
 
-       spin_unlock(&dca_lock);
        return 0;
 }
 EXPORT_SYMBOL_GPL(dca_remove_requester);
@@ -135,17 +138,18 @@ u8 dca_common_get_tag(struct device *dev, int cpu)
 {
        struct dca_provider *dca;
        u8 tag;
+       unsigned long flags;
 
-       spin_lock(&dca_lock);
+       spin_lock_irqsave(&dca_lock, flags);
 
        dca = dca_find_provider_by_dev(dev);
        if (!dca) {
-               spin_unlock(&dca_lock);
+               spin_unlock_irqrestore(&dca_lock, flags);
                return -ENODEV;
        }
        tag = dca->ops->get_tag(dca, dev, cpu);
 
-       spin_unlock(&dca_lock);
+       spin_unlock_irqrestore(&dca_lock, flags);
        return tag;
 }
 
@@ -217,11 +221,16 @@ static BLOCKING_NOTIFIER_HEAD(dca_provider_chain);
 int register_dca_provider(struct dca_provider *dca, struct device *dev)
 {
        int err;
+       unsigned long flags;
 
        err = dca_sysfs_add_provider(dca, dev);
        if (err)
                return err;
+
+       spin_lock_irqsave(&dca_lock, flags);
        list_add(&dca->node, &dca_providers);
+       spin_unlock_irqrestore(&dca_lock, flags);
+
        blocking_notifier_call_chain(&dca_provider_chain,
                                     DCA_PROVIDER_ADD, NULL);
        return 0;
@@ -234,9 +243,15 @@ EXPORT_SYMBOL_GPL(register_dca_provider);
  */
 void unregister_dca_provider(struct dca_provider *dca)
 {
+       unsigned long flags;
+
        blocking_notifier_call_chain(&dca_provider_chain,
                                     DCA_PROVIDER_REMOVE, NULL);
+
+       spin_lock_irqsave(&dca_lock, flags);
        list_del(&dca->node);
+       spin_unlock_irqrestore(&dca_lock, flags);
+
        dca_sysfs_remove_provider(dca);
 }
 EXPORT_SYMBOL_GPL(unregister_dca_provider);
index 7be2cf3..a5dd7a6 100644 (file)
@@ -412,6 +412,7 @@ fw_card_add(struct fw_card *card,
 {
        u32 *config_rom;
        size_t length;
+       int err;
 
        card->max_receive = max_receive;
        card->link_speed = link_speed;
@@ -422,7 +423,13 @@ fw_card_add(struct fw_card *card,
        list_add_tail(&card->link, &card_list);
        mutex_unlock(&card_mutex);
 
-       return card->driver->enable(card, config_rom, length);
+       err = card->driver->enable(card, config_rom, length);
+       if (err < 0) {
+               mutex_lock(&card_mutex);
+               list_del(&card->link);
+               mutex_unlock(&card_mutex);
+       }
+       return err;
 }
 EXPORT_SYMBOL(fw_card_add);
 
index 0370524..abf4dfc 100644 (file)
@@ -153,7 +153,10 @@ static struct axis_conversion lis3lv02d_axis_y_inverted = {1, -2, 3};
 static struct axis_conversion lis3lv02d_axis_x_inverted = {-1, 2, 3};
 static struct axis_conversion lis3lv02d_axis_z_inverted = {1, 2, -3};
 static struct axis_conversion lis3lv02d_axis_xy_rotated_left = {-2, 1, 3};
+static struct axis_conversion lis3lv02d_axis_xy_rotated_left_usd = {-2, 1, -3};
 static struct axis_conversion lis3lv02d_axis_xy_swap_inverted = {-2, -1, 3};
+static struct axis_conversion lis3lv02d_axis_xy_rotated_right = {2, -1, 3};
+static struct axis_conversion lis3lv02d_axis_xy_swap_yz_inverted = {2, -1, -3};
 
 #define AXIS_DMI_MATCH(_ident, _name, _axis) {         \
        .ident = _ident,                                \
@@ -172,10 +175,12 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = {
        AXIS_DMI_MATCH("NC2510", "HP Compaq 2510", y_inverted),
        AXIS_DMI_MATCH("NC8510", "HP Compaq 8510", xy_swap_inverted),
        AXIS_DMI_MATCH("HP2133", "HP 2133", xy_rotated_left),
+       AXIS_DMI_MATCH("NC653x", "HP Compaq 653", xy_rotated_left_usd),
+       AXIS_DMI_MATCH("NC673x", "HP Compaq 673", xy_rotated_left_usd),
+       AXIS_DMI_MATCH("NC651xx", "HP Compaq 651", xy_rotated_right),
+       AXIS_DMI_MATCH("NC671xx", "HP Compaq 671", xy_swap_yz_inverted),
        { NULL, }
 /* Laptop models without axis info (yet):
- * "NC651xx" "HP Compaq 651"
- * "NC671xx" "HP Compaq 671"
  * "NC6910" "HP Compaq 6910"
  * HP Compaq 8710x Notebook PC / Mobile Workstation
  * "NC2400" "HP Compaq nc2400"
index 5b2e3af..08c4fa3 100644 (file)
@@ -16,7 +16,7 @@
 
 /*
  * Rewritten from the work of Colten Edwards <pje120@cs.usask.ca> by
- * Samuel Thibault <samuel.thibault@fnac.net>
+ * Samuel Thibault <samuel.thibault@ens-lyon.org>
  */
 
 #include <linux/module.h>
index 6636f96..d7e67a1 100644 (file)
@@ -4,7 +4,7 @@
 
 /*
  * Authors:    Petr Soucek <petr@ryston.cz>
- *             Samuel Thibault <samuel.thibault@fnac.net>
+ *             Samuel Thibault <samuel.thibault@ens-lyon.org>
  */
 
 /* truncates a in [b,c] */
index a329e6b..3838bc4 100644 (file)
@@ -1823,6 +1823,10 @@ static int dv1394_open(struct inode *inode, struct file *file)
 
 #endif
 
+       printk(KERN_INFO "%s: NOTE, the dv1394 interface is unsupported "
+              "and will not be available in the new firewire driver stack. "
+              "Try libraw1394 based programs instead.\n", current->comm);
+
        return 0;
 }
 
@@ -2567,10 +2571,6 @@ static int __init dv1394_init_module(void)
 {
        int ret;
 
-       printk(KERN_WARNING
-              "NOTE: The dv1394 driver is unsupported and may be removed in a "
-              "future Linux release. Use raw1394 instead.\n");
-
        cdev_init(&dv1394_cdev, &dv1394_fops);
        dv1394_cdev.owner = THIS_MODULE;
        ret = cdev_add(&dv1394_cdev, IEEE1394_DV1394_DEV, 16);
index 1e3aea9..09658b2 100644 (file)
@@ -25,13 +25,13 @@ static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector)
 {
        dev_info_t *hash;
        linear_conf_t *conf = mddev_to_conf(mddev);
+       sector_t idx = sector >> conf->sector_shift;
 
        /*
         * sector_div(a,b) returns the remainer and sets a to a/b
         */
-       sector >>= conf->sector_shift;
-       (void)sector_div(sector, conf->spacing);
-       hash = conf->hash_table[sector];
+       (void)sector_div(idx, conf->spacing);
+       hash = conf->hash_table[idx];
 
        while (sector >= hash->num_sectors + hash->start_sector)
                hash++;
index 41e2509..4495104 100644 (file)
@@ -1481,6 +1481,11 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
                if (find_rdev_nr(mddev, rdev->desc_nr))
                        return -EBUSY;
        }
+       if (mddev->max_disks && rdev->desc_nr >= mddev->max_disks) {
+               printk(KERN_WARNING "md: %s: array is limited to %d devices\n",
+                      mdname(mddev), mddev->max_disks);
+               return -EBUSY;
+       }
        bdevname(rdev->bdev,b);
        while ( (s=strchr(b, '/')) != NULL)
                *s = '!';
@@ -2441,6 +2446,15 @@ static void analyze_sbs(mddev_t * mddev)
 
        i = 0;
        rdev_for_each(rdev, tmp, mddev) {
+               if (rdev->desc_nr >= mddev->max_disks ||
+                   i > mddev->max_disks) {
+                       printk(KERN_WARNING
+                              "md: %s: %s: only %d devices permitted\n",
+                              mdname(mddev), bdevname(rdev->bdev, b),
+                              mddev->max_disks);
+                       kick_rdev_from_array(rdev);
+                       continue;
+               }
                if (rdev != freshest)
                        if (super_types[mddev->major_version].
                            validate_super(mddev, rdev)) {
@@ -4614,13 +4628,6 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev)
         * noticed in interrupt contexts ...
         */
 
-       if (rdev->desc_nr == mddev->max_disks) {
-               printk(KERN_WARNING "%s: can not hot-add to full array!\n",
-                       mdname(mddev));
-               err = -EBUSY;
-               goto abort_unbind_export;
-       }
-
        rdev->raid_disk = -1;
 
        md_update_sb(mddev, 1);
@@ -4634,9 +4641,6 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev)
        md_new_event(mddev);
        return 0;
 
-abort_unbind_export:
-       unbind_rdev_from_array(rdev);
-
 abort_export:
        export_rdev(rdev);
        return err;
index 7b4f5f7..01e3cff 100644 (file)
@@ -1640,7 +1640,8 @@ static void raid1d(mddev_t *mddev)
                        }
 
                        bio = r1_bio->bios[r1_bio->read_disk];
-                       if ((disk=read_balance(conf, r1_bio)) == -1) {
+                       if ((disk=read_balance(conf, r1_bio)) == -1 ||
+                           disk == r1_bio->read_disk) {
                                printk(KERN_ALERT "raid1: %s: unrecoverable I/O"
                                       " read error for block %llu\n",
                                       bdevname(bio->bi_bdev,b),
index 24508e2..ea9488e 100644 (file)
@@ -626,7 +626,6 @@ static int __devinit pcf50633_probe(struct i2c_client *client,
        }
 
        if (client->irq) {
-               set_irq_handler(client->irq, handle_level_irq);
                ret = request_irq(client->irq, pcf50633_irq,
                                IRQF_TRIGGER_LOW, "pcf50633", pcf);
 
index 5607319..c64e679 100644 (file)
@@ -217,6 +217,7 @@ config DELL_LAPTOP
        depends on EXPERIMENTAL
        depends on BACKLIGHT_CLASS_DEVICE
        depends on RFKILL
+       depends on POWER_SUPPLY
        default n
        ---help---
        This driver adds support for rfkill and backlight control to Dell
index bf5e4d0..558bf3f 100644 (file)
@@ -35,7 +35,7 @@ struct ssc_device *ssc_request(unsigned int ssc_num)
 
        if (!ssc_valid) {
                spin_unlock(&user_lock);
-               dev_dbg(&ssc->pdev->dev, "could not find requested device\n");
+               pr_err("ssc: ssc%d platform device is missing\n", ssc_num);
                return ERR_PTR(-ENODEV);
        }
 
index 10c421b..f26667a 100644 (file)
@@ -207,7 +207,7 @@ static void ilo_ccb_close(struct pci_dev *pdev, struct ccb_data *data)
                  &device_ccb->recv_ctrl);
 
        /* give iLO some time to process stop request */
-       for (retries = 1000; retries > 0; retries--) {
+       for (retries = MAX_WAIT; retries > 0; retries--) {
                doorbell_set(driver_ccb);
                udelay(1);
                if (!(ioread32(&device_ccb->send_ctrl) & (1 << CTRL_BITPOS_A))
@@ -309,7 +309,7 @@ static int ilo_ccb_open(struct ilo_hwinfo *hw, struct ccb_data *data, int slot)
        doorbell_clr(driver_ccb);
 
        /* make sure iLO is really handling requests */
-       for (i = 1000; i > 0; i--) {
+       for (i = MAX_WAIT; i > 0; i--) {
                if (ilo_pkt_dequeue(hw, driver_ccb, SENDQ, &pkt_id, NULL, NULL))
                        break;
                udelay(1);
@@ -326,7 +326,7 @@ static int ilo_ccb_open(struct ilo_hwinfo *hw, struct ccb_data *data, int slot)
 
        return 0;
 free:
-       pci_free_consistent(pdev, data->dma_size, data->dma_va, data->dma_pa);
+       ilo_ccb_close(pdev, data);
 out:
        return error;
 }
index a281207..b64a20e 100644 (file)
@@ -19,6 +19,8 @@
 #define MAX_ILO_DEV    1
 /* max number of files */
 #define MAX_OPEN       (MAX_CCB * MAX_ILO_DEV)
+/* spin counter for open/close delay */
+#define MAX_WAIT       10000
 
 /*
  * Per device, used to track global memory allocations.
index a5bd658..275b788 100644 (file)
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (c) 2004-2008 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2004-2009 Silicon Graphics, Inc.  All Rights Reserved.
  */
 
 /*
@@ -514,7 +514,8 @@ struct xpc_channel_uv {
                                                /* partition's notify mq */
 
        struct xpc_send_msg_slot_uv *send_msg_slots;
-       struct xpc_notify_mq_msg_uv *recv_msg_slots;
+       void *recv_msg_slots;   /* each slot will hold a xpc_notify_mq_msg_uv */
+                               /* structure plus the user's payload */
 
        struct xpc_fifo_head_uv msg_slot_free_list;
        struct xpc_fifo_head_uv recv_msg_list;  /* deliverable payloads */
index f17f7d4..29c0502 100644 (file)
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (c) 2008 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2008-2009 Silicon Graphics, Inc.  All Rights Reserved.
  */
 
 /*
@@ -1010,8 +1010,8 @@ xpc_allocate_recv_msg_slot_uv(struct xpc_channel *ch)
                        continue;
 
                for (entry = 0; entry < nentries; entry++) {
-                       msg_slot = ch_uv->recv_msg_slots + entry *
-                           ch->entry_size;
+                       msg_slot = ch_uv->recv_msg_slots +
+                           entry * ch->entry_size;
 
                        msg_slot->hdr.msg_slot_number = entry;
                }
@@ -1308,9 +1308,8 @@ xpc_handle_notify_mq_msg_uv(struct xpc_partition *part,
        /* we're dealing with a normal message sent via the notify_mq */
        ch_uv = &ch->sn.uv;
 
-       msg_slot = (struct xpc_notify_mq_msg_uv *)((u64)ch_uv->recv_msg_slots +
-                   (msg->hdr.msg_slot_number % ch->remote_nentries) *
-                   ch->entry_size);
+       msg_slot = ch_uv->recv_msg_slots +
+           (msg->hdr.msg_slot_number % ch->remote_nentries) * ch->entry_size;
 
        BUG_ON(msg->hdr.msg_slot_number != msg_slot->hdr.msg_slot_number);
        BUG_ON(msg_slot->hdr.size != 0);
index 7957f52..6faefcf 100644 (file)
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1999-2008 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 1999-2009 Silicon Graphics, Inc. All rights reserved.
  */
 
 /*
@@ -551,6 +551,7 @@ xpnet_init(void)
 
        netif_carrier_off(xpnet_device);
 
+       xpnet_device->netdev_ops = &xpnet_netdev_ops;
        xpnet_device->mtu = XPNET_DEF_MTU;
 
        /*
index 7df6bbf..6f6a0f6 100644 (file)
@@ -453,7 +453,7 @@ static struct platform_driver sa1100_mtd_driver = {
        .resume         = sa1100_mtd_resume,
        .shutdown       = sa1100_mtd_shutdown,
        .driver         = {
-               .name   = "flash",
+               .name   = "sa1100-mtd",
                .owner  = THIS_MODULE,
        },
 };
@@ -474,4 +474,4 @@ module_exit(sa1100_mtd_exit);
 MODULE_AUTHOR("Nicolas Pitre");
 MODULE_DESCRIPTION("SA1100 CFI map driver");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:flash");
+MODULE_ALIAS("platform:sa1100-mtd");
index d15d8b7..54b52e5 100644 (file)
@@ -646,7 +646,7 @@ static const struct net_device_ops etherh_netdev_ops = {
        .ndo_get_stats          = ei_get_stats,
        .ndo_set_multicast_list = ei_set_multicast_list,
        .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_mac_address    = eth_set_mac_addr,
+       .ndo_set_mac_address    = eth_mac_addr,
        .ndo_change_mtu         = eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = ei_poll,
index 840b3d1..bbbc3bb 100644 (file)
@@ -806,7 +806,7 @@ static int cas_reset_mii_phy(struct cas *cp)
 
        cas_phy_write(cp, MII_BMCR, BMCR_RESET);
        udelay(100);
-       while (limit--) {
+       while (--limit) {
                val = cas_phy_read(cp, MII_BMCR);
                if ((val & BMCR_RESET) == 0)
                        break;
@@ -979,7 +979,7 @@ static void cas_phy_init(struct cas *cp)
                writel(val, cp->regs + REG_PCS_MII_CTRL);
 
                limit = STOP_TRIES;
-               while (limit-- > 0) {
+               while (--limit > 0) {
                        udelay(10);
                        if ((readl(cp->regs + REG_PCS_MII_CTRL) &
                             PCS_MII_RESET) == 0)
index 379a132..d31791f 100644 (file)
@@ -2276,8 +2276,7 @@ no_mem:
                } else if ((len = ntohl(r->len_cq)) != 0) {
                        struct sge_fl *fl;
 
-                       if (eth)
-                               lro = qs->lro_enabled && is_eth_tcp(rss_hi);
+                       lro &= eth && is_eth_tcp(rss_hi);
 
                        fl = (len & F_RSPD_FLQ) ? &qs->fl[1] : &qs->fl[0];
                        if (fl->use_pages) {
index c986978..6bd63cc 100644 (file)
@@ -940,7 +940,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
                err = pci_enable_device(pdev);
        } else {
                bars = pci_select_bars(pdev, IORESOURCE_MEM);
-               err = pci_enable_device(pdev);
+               err = pci_enable_device_mem(pdev);
        }
        if (err)
                return err;
index 3f7eab4..acae2d8 100644 (file)
@@ -351,6 +351,9 @@ static int gfar_probe(struct of_device *ofdev,
        /* Reset MAC layer */
        gfar_write(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
 
+       /* We need to delay at least 3 TX clocks */
+       udelay(2);
+
        tempval = (MACCFG1_TX_FLOW | MACCFG1_RX_FLOW);
        gfar_write(&priv->regs->maccfg1, tempval);
 
index b1a8334..eaa8689 100644 (file)
@@ -312,7 +312,7 @@ extern const char gfar_driver_version[];
 #define ATTRELI_EI(x) (x)
 
 #define BD_LFLAG(flags) ((flags) << 16)
-#define BD_LENGTH_MASK         0x00ff
+#define BD_LENGTH_MASK         0x0000ffff
 
 /* TxBD status field bits */
 #define TXBD_READY             0x8000
index c40cd8d..ac9d964 100644 (file)
@@ -60,7 +60,7 @@ int emac_mii_reset_phy(struct mii_phy *phy)
 
        udelay(300);
 
-       while (limit--) {
+       while (--limit) {
                val = phy_read(phy, MII_BMCR);
                if (val >= 0 && (val & BMCR_RESET) == 0)
                        break;
@@ -84,7 +84,7 @@ int emac_mii_reset_gpcs(struct mii_phy *phy)
 
        udelay(300);
 
-       while (limit--) {
+       while (--limit) {
                val = gpcs_phy_read(phy, MII_BMCR);
                if (val >= 0 && (val & BMCR_RESET) == 0)
                        break;
index c38ed77..a699940 100644 (file)
@@ -586,7 +586,7 @@ static int pcnet_config(struct pcmcia_device *link)
     }
 
     if ((link->conf.ConfigBase == 0x03c0)
-       && (link->manf_id == 0x149) && (link->card_id = 0xc1ab)) {
+       && (link->manf_id == 0x149) && (link->card_id == 0xc1ab)) {
        printk(KERN_INFO "pcnet_cs: this is an AX88190 card!\n");
        printk(KERN_INFO "pcnet_cs: use axnet_cs instead.\n");
        goto failed;
index c1dadad..e6fdce9 100644 (file)
@@ -787,12 +787,12 @@ struct mbox_params {
 
 struct flash_params {
        u8 dev_id_str[4];
-       u16 size;
-       u16 csum;
-       u16 ver;
-       u16 sub_dev_id;
+       __le16 size;
+       __le16 csum;
+       __le16 ver;
+       __le16 sub_dev_id;
        u8 mac_addr[6];
-       u16 res;
+       __le16 res;
 };
 
 
index 45421c8..3d1d7b6 100644 (file)
@@ -641,7 +641,7 @@ static void ql_enable_all_completion_interrupts(struct ql_adapter *qdev)
 
 }
 
-static int ql_read_flash_word(struct ql_adapter *qdev, int offset, u32 *data)
+static int ql_read_flash_word(struct ql_adapter *qdev, int offset, __le32 *data)
 {
        int status = 0;
        /* wait for reg to come ready */
@@ -656,8 +656,11 @@ static int ql_read_flash_word(struct ql_adapter *qdev, int offset, u32 *data)
                        FLASH_ADDR, FLASH_ADDR_RDY, FLASH_ADDR_ERR);
        if (status)
                goto exit;
-       /* get the data */
-       *data = ql_read32(qdev, FLASH_DATA);
+        /* This data is stored on flash as an array of
+        * __le32.  Since ql_read32() returns cpu endian
+        * we need to swap it back.
+        */
+       *data = cpu_to_le32(ql_read32(qdev, FLASH_DATA));
 exit:
        return status;
 }
@@ -666,13 +669,20 @@ static int ql_get_flash_params(struct ql_adapter *qdev)
 {
        int i;
        int status;
-       u32 *p = (u32 *)&qdev->flash;
+       __le32 *p = (__le32 *)&qdev->flash;
+       u32 offset = 0;
+
+       /* Second function's parameters follow the first
+        * function's.
+        */
+       if (qdev->func)
+               offset = sizeof(qdev->flash) / sizeof(u32);
 
        if (ql_sem_spinlock(qdev, SEM_FLASH_MASK))
                return -ETIMEDOUT;
 
        for (i = 0; i < sizeof(qdev->flash) / sizeof(u32); i++, p++) {
-               status = ql_read_flash_word(qdev, i, p);
+               status = ql_read_flash_word(qdev, i+offset, p);
                if (status) {
                        QPRINTK(qdev, IFUP, ERR, "Error reading flash.\n");
                        goto exit;
@@ -3826,7 +3836,7 @@ static int qlge_suspend(struct pci_dev *pdev, pm_message_t state)
 {
        struct net_device *ndev = pci_get_drvdata(pdev);
        struct ql_adapter *qdev = netdev_priv(ndev);
-       int err;
+       int err, i;
 
        netif_device_detach(ndev);
 
@@ -3836,6 +3846,9 @@ static int qlge_suspend(struct pci_dev *pdev, pm_message_t state)
                        return err;
        }
 
+       for (i = qdev->rss_ring_first_cq_id; i < qdev->rx_ring_count; i++)
+               netif_napi_del(&qdev->rx_ring[i].napi);
+
        err = pci_save_state(pdev);
        if (err)
                return err;
index bf3aa2a..223cde0 100644 (file)
@@ -220,9 +220,9 @@ static void smc911x_reset(struct net_device *dev)
 
        /* make sure EEPROM has finished loading before setting GPIO_CFG */
        timeout=1000;
-       while ( timeout-- && (SMC_GET_E2P_CMD(lp) & E2P_CMD_EPC_BUSY_)) {
+       while (--timeout && (SMC_GET_E2P_CMD(lp) & E2P_CMD_EPC_BUSY_))
                udelay(10);
-       }
+
        if (timeout == 0){
                PRINTK("%s: smc911x_reset timeout waiting for EEPROM busy\n", dev->name);
                return;
index d801900..a1e4b38 100644 (file)
@@ -498,7 +498,7 @@ static void smsc9420_check_mac_address(struct net_device *dev)
 static void smsc9420_stop_tx(struct smsc9420_pdata *pd)
 {
        u32 dmac_control, mac_cr, dma_intr_ena;
-       int timeOut = 1000;
+       int timeout = 1000;
 
        /* disable TX DMAC */
        dmac_control = smsc9420_reg_read(pd, DMAC_CONTROL);
@@ -506,13 +506,13 @@ static void smsc9420_stop_tx(struct smsc9420_pdata *pd)
        smsc9420_reg_write(pd, DMAC_CONTROL, dmac_control);
 
        /* Wait max 10ms for transmit process to stop */
-       while (timeOut--) {
+       while (--timeout) {
                if (smsc9420_reg_read(pd, DMAC_STATUS) & DMAC_STS_TS_)
                        break;
                udelay(10);
        }
 
-       if (!timeOut)
+       if (!timeout)
                smsc_warn(IFDOWN, "TX DMAC failed to stop");
 
        /* ACK Tx DMAC stop bit */
@@ -596,7 +596,7 @@ static void smsc9420_free_rx_ring(struct smsc9420_pdata *pd)
 
 static void smsc9420_stop_rx(struct smsc9420_pdata *pd)
 {
-       int timeOut = 1000;
+       int timeout = 1000;
        u32 mac_cr, dmac_control, dma_intr_ena;
 
        /* mask RX DMAC interrupts */
@@ -617,13 +617,13 @@ static void smsc9420_stop_rx(struct smsc9420_pdata *pd)
        smsc9420_pci_flush_write(pd);
 
        /* wait up to 10ms for receive to stop */
-       while (timeOut--) {
+       while (--timeout) {
                if (smsc9420_reg_read(pd, DMAC_STATUS) & DMAC_STS_RS_)
                        break;
                udelay(10);
        }
 
-       if (!timeOut)
+       if (!timeout)
                smsc_warn(IFDOWN, "RX DMAC did not stop! timeout.");
 
        /* ACK the Rx DMAC stop bit */
index 86c765d..b17efa9 100644 (file)
@@ -148,7 +148,7 @@ static u16 __phy_read(struct gem *gp, int phy_addr, int reg)
        cmd |= (MIF_FRAME_TAMSB);
        writel(cmd, gp->regs + MIF_FRAME);
 
-       while (limit--) {
+       while (--limit) {
                cmd = readl(gp->regs + MIF_FRAME);
                if (cmd & MIF_FRAME_TALSB)
                        break;
index 61843fd..78f8cee 100644 (file)
@@ -79,7 +79,7 @@ static int reset_one_mii_phy(struct mii_phy* phy, int phy_id)
 
        udelay(100);
 
-       while (limit--) {
+       while (--limit) {
                val = __phy_read(phy, phy_id, MII_BMCR);
                if ((val & BMCR_RESET) == 0)
                        break;
index 6e8f377..fe0c3f2 100644 (file)
@@ -227,7 +227,7 @@ static int qe_init(struct sunqe *qep, int from_irq)
        if (!(sbus_readb(mregs + MREGS_PHYCONFIG) & MREGS_PHYCONFIG_LTESTDIS)) {
                int tries = 50;
 
-               while (tries--) {
+               while (--tries) {
                        u8 tmp;
 
                        mdelay(5);
index 75461db..a9fd2b2 100644 (file)
@@ -1237,7 +1237,7 @@ static void tsi108_init_phy(struct net_device *dev)
        spin_lock_irqsave(&phy_lock, flags);
 
        tsi108_write_mii(data, MII_BMCR, BMCR_RESET);
-       while (i--){
+       while (--i) {
                if(!(tsi108_read_mii(data, MII_BMCR) & BMCR_RESET))
                        break;
                udelay(10);
index d5d53b6..0bf2114 100644 (file)
@@ -392,7 +392,7 @@ static void de_rx (struct de_private *de)
        unsigned drop = 0;
        int rc;
 
-       while (rx_work--) {
+       while (--rx_work) {
                u32 status, len;
                dma_addr_t mapping;
                struct sk_buff *skb, *copy_skb;
index 0d0fa91..fe98aca 100644 (file)
@@ -455,6 +455,7 @@ static const struct usb_device_id hso_ids[] = {
        {icon321_port_device(0x0af0, 0xd033)},  /* Icon-322 */
        {USB_DEVICE(0x0af0, 0x7301)},           /* GE40x */
        {USB_DEVICE(0x0af0, 0x7361)},           /* GE40x */
+       {USB_DEVICE(0x0af0, 0x7381)},           /* GE40x */
        {USB_DEVICE(0x0af0, 0x7401)},           /* GI 0401 */
        {USB_DEVICE(0x0af0, 0x7501)},           /* GTM 382 */
        {USB_DEVICE(0x0af0, 0x7601)},           /* GE40x */
@@ -462,7 +463,8 @@ static const struct usb_device_id hso_ids[] = {
        {USB_DEVICE(0x0af0, 0x7801)},
        {USB_DEVICE(0x0af0, 0x7901)},
        {USB_DEVICE(0x0af0, 0x7361)},
-       {icon321_port_device(0x0af0, 0xd051)},
+       {USB_DEVICE(0x0af0, 0xd057)},
+       {USB_DEVICE(0x0af0, 0xd055)},
        {}
 };
 MODULE_DEVICE_TABLE(usb, hso_ids);
index b35c881..c01ea48 100644 (file)
@@ -4042,6 +4042,7 @@ static int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
                priv->is_open = 1;
        }
 
+       pci_save_state(pdev);
        pci_set_power_state(pdev, PCI_D3hot);
 
        return 0;
@@ -4052,6 +4053,7 @@ static int iwl_pci_resume(struct pci_dev *pdev)
        struct iwl_priv *priv = pci_get_drvdata(pdev);
 
        pci_set_power_state(pdev, PCI_D0);
+       pci_restore_state(pdev);
 
        if (priv->is_open)
                iwl_mac_start(priv->hw);
index 412f66b..70a8b21 100644 (file)
@@ -480,6 +480,9 @@ void iwl_clear_stations_table(struct iwl_priv *priv)
        priv->num_stations = 0;
        memset(priv->stations, 0, sizeof(priv->stations));
 
+       /* clean ucode key table bit map */
+       priv->ucode_key_table = 0;
+
        spin_unlock_irqrestore(&priv->sta_lock, flags);
 }
 EXPORT_SYMBOL(iwl_clear_stations_table);
index 95d0198..5b44d32 100644 (file)
@@ -8143,6 +8143,7 @@ static int iwl3945_pci_suspend(struct pci_dev *pdev, pm_message_t state)
                priv->is_open = 1;
        }
 
+       pci_save_state(pdev);
        pci_set_power_state(pdev, PCI_D3hot);
 
        return 0;
@@ -8153,6 +8154,7 @@ static int iwl3945_pci_resume(struct pci_dev *pdev)
        struct iwl3945_priv *priv = pci_get_drvdata(pdev);
 
        pci_set_power_state(pdev, PCI_D0);
+       pci_restore_state(pdev);
 
        if (priv->is_open)
                iwl3945_mac_start(priv->hw);
index de91dda..f41135f 100644 (file)
@@ -463,9 +463,11 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
 
        return 0;
 register_wwan_err:
-       rfkill_unregister(bluetooth_rfkill);
+       if (bluetooth_rfkill)
+               rfkill_unregister(bluetooth_rfkill);
 register_bluetooth_error:
-       rfkill_unregister(wifi_rfkill);
+       if (wifi_rfkill)
+               rfkill_unregister(wifi_rfkill);
 add_sysfs_error:
        cleanup_sysfs(device);
        return err;
index cced4d1..81450fb 100644 (file)
@@ -241,6 +241,12 @@ config RTC_DRV_M41T80_WDT
          If you say Y here you will get support for the
          watchdog timer in the ST M41T60 and M41T80 RTC chips series.
 
+config RTC_DRV_DM355EVM
+       tristate "TI DaVinci DM355 EVM RTC"
+       depends on MFD_DM355EVM_MSP
+       help
+         Supports the RTC firmware in the MSP430 on the DM355 EVM.
+
 config RTC_DRV_TWL92330
        boolean "TI TWL92330/Menelaus"
        depends on MENELAUS
index 6e28021..0e697aa 100644 (file)
@@ -23,6 +23,7 @@ obj-$(CONFIG_RTC_DRV_AT91SAM9)        += rtc-at91sam9.o
 obj-$(CONFIG_RTC_DRV_AU1XXX)   += rtc-au1xxx.o
 obj-$(CONFIG_RTC_DRV_BFIN)     += rtc-bfin.o
 obj-$(CONFIG_RTC_DRV_CMOS)     += rtc-cmos.o
+obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o
 obj-$(CONFIG_RTC_DRV_DS1216)   += rtc-ds1216.o
 obj-$(CONFIG_RTC_DRV_DS1286)   += rtc-ds1286.o
 obj-$(CONFIG_RTC_DRV_DS1302)   += rtc-ds1302.o
diff --git a/drivers/rtc/rtc-dm355evm.c b/drivers/rtc/rtc-dm355evm.c
new file mode 100644 (file)
index 0000000..58d4e18
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * rtc-dm355evm.c - access battery-backed counter in MSP430 firmware
+ *
+ * Copyright (c) 2008 by David Brownell
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/rtc.h>
+#include <linux/platform_device.h>
+
+#include <linux/i2c/dm355evm_msp.h>
+
+
+/*
+ * The MSP430 firmware on the DM355 EVM uses a watch crystal to feed
+ * a 1 Hz counter.  When a backup battery is supplied, that makes a
+ * reasonable RTC for applications where alarms and non-NTP drift
+ * compensation aren't important.
+ *
+ * The only real glitch is the inability to read or write all four
+ * counter bytes atomically:  the count may increment in the middle
+ * of an operation, causing trouble when the LSB rolls over.
+ *
+ * This driver was tested with firmware revision A4.
+ */
+union evm_time {
+       u8      bytes[4];
+       u32     value;
+};
+
+static int dm355evm_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+       union evm_time  time;
+       int             status;
+       int             tries = 0;
+
+       do {
+               /*
+                * Read LSB(0) to MSB(3) bytes.  Defend against the counter
+                * rolling over by re-reading until the value is stable,
+                * and assuming the four reads take at most a few seconds.
+                */
+               status = dm355evm_msp_read(DM355EVM_MSP_RTC_0);
+               if (status < 0)
+                       return status;
+               if (tries && time.bytes[0] == status)
+                       break;
+               time.bytes[0] = status;
+
+               status = dm355evm_msp_read(DM355EVM_MSP_RTC_1);
+               if (status < 0)
+                       return status;
+               if (tries && time.bytes[1] == status)
+                       break;
+               time.bytes[1] = status;
+
+               status = dm355evm_msp_read(DM355EVM_MSP_RTC_2);
+               if (status < 0)
+                       return status;
+               if (tries && time.bytes[2] == status)
+                       break;
+               time.bytes[2] = status;
+
+               status = dm355evm_msp_read(DM355EVM_MSP_RTC_3);
+               if (status < 0)
+                       return status;
+               if (tries && time.bytes[3] == status)
+                       break;
+               time.bytes[3] = status;
+
+       } while (++tries < 5);
+
+       dev_dbg(dev, "read timestamp %08x\n", time.value);
+
+       rtc_time_to_tm(le32_to_cpu(time.value), tm);
+       return 0;
+}
+
+static int dm355evm_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+       union evm_time  time;
+       unsigned long   value;
+       int             status;
+
+       rtc_tm_to_time(tm, &value);
+       time.value = cpu_to_le32(value);
+
+       dev_dbg(dev, "write timestamp %08x\n", time.value);
+
+       /*
+        * REVISIT handle non-atomic writes ... maybe just retry until
+        * byte[1] sticks (no rollover)?
+        */
+       status = dm355evm_msp_write(time.bytes[0], DM355EVM_MSP_RTC_0);
+       if (status < 0)
+               return status;
+
+       status = dm355evm_msp_write(time.bytes[1], DM355EVM_MSP_RTC_1);
+       if (status < 0)
+               return status;
+
+       status = dm355evm_msp_write(time.bytes[2], DM355EVM_MSP_RTC_2);
+       if (status < 0)
+               return status;
+
+       status = dm355evm_msp_write(time.bytes[3], DM355EVM_MSP_RTC_3);
+       if (status < 0)
+               return status;
+
+       return 0;
+}
+
+static struct rtc_class_ops dm355evm_rtc_ops = {
+       .read_time      = dm355evm_rtc_read_time,
+       .set_time       = dm355evm_rtc_set_time,
+};
+
+/*----------------------------------------------------------------------*/
+
+static int __devinit dm355evm_rtc_probe(struct platform_device *pdev)
+{
+       struct rtc_device *rtc;
+
+       rtc = rtc_device_register(pdev->name,
+                                 &pdev->dev, &dm355evm_rtc_ops, THIS_MODULE);
+       if (IS_ERR(rtc)) {
+               dev_err(&pdev->dev, "can't register RTC device, err %ld\n",
+                       PTR_ERR(rtc));
+               return PTR_ERR(rtc);
+       }
+       platform_set_drvdata(pdev, rtc);
+
+       return 0;
+}
+
+static int __devexit dm355evm_rtc_remove(struct platform_device *pdev)
+{
+       struct rtc_device *rtc = platform_get_drvdata(pdev);
+
+       rtc_device_unregister(rtc);
+       platform_set_drvdata(pdev, NULL);
+       return 0;
+}
+
+/*
+ * I2C is used to talk to the MSP430, but this platform device is
+ * exposed by an MFD driver that manages I2C communications.
+ */
+static struct platform_driver rtc_dm355evm_driver = {
+       .probe          = dm355evm_rtc_probe,
+       .remove         = __devexit_p(dm355evm_rtc_remove),
+       .driver         = {
+               .owner  = THIS_MODULE,
+               .name   = "rtc-dm355evm",
+       },
+};
+
+static int __init dm355evm_rtc_init(void)
+{
+       return platform_driver_register(&rtc_dm355evm_driver);
+}
+module_init(dm355evm_rtc_init);
+
+static void __exit dm355evm_rtc_exit(void)
+{
+       platform_driver_unregister(&rtc_dm355evm_driver);
+}
+module_exit(dm355evm_rtc_exit);
+
+MODULE_LICENSE("GPL");
index e54b5c6..e01b955 100644 (file)
@@ -122,7 +122,6 @@ static const struct rtc_class_ops ds1390_rtc_ops = {
 
 static int __devinit ds1390_probe(struct spi_device *spi)
 {
-       struct rtc_device *rtc;
        unsigned char tmp;
        struct ds1390 *chip;
        int res;
index db16112..fb2b0f5 100644 (file)
@@ -1475,7 +1475,7 @@ static int aty128fb_set_par(struct fb_info *info)
        aty128_set_pll(&par->pll, par);
        aty128_set_fifo(&par->fifo_reg, par);
 
-       config = aty_ld_le32(CONFIG_CNTL) & ~3;
+       config = aty_ld_le32(CNFG_CNTL) & ~3;
 
 #if defined(__BIG_ENDIAN)
        if (par->crtc.bpp == 32)
@@ -1484,7 +1484,7 @@ static int aty128fb_set_par(struct fb_info *info)
                config |= 1;    /* make aperture do 16 bit swapping */
 #endif
 
-       aty_st_le32(CONFIG_CNTL, config);
+       aty_st_le32(CNFG_CNTL, config);
        aty_st_8(CRTC_EXT_CNTL + 1, 0); /* turn the video back on */
 
        info->fix.line_length = (par->crtc.vxres * par->crtc.bpp) >> 3;
@@ -1875,7 +1875,7 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i
        u32 dac;
 
        /* Get the chip revision */
-       chip_rev = (aty_ld_le32(CONFIG_CNTL) >> 16) & 0x1F;
+       chip_rev = (aty_ld_le32(CNFG_CNTL) >> 16) & 0x1F;
 
        strcpy(video_card, "Rage128 XX ");
        video_card[8] = ent->device >> 8;
@@ -2057,7 +2057,7 @@ static int __devinit aty128_probe(struct pci_dev *pdev, const struct pci_device_
 
        /* Grab memory size from the card */
        // How does this relate to the resource length from the PCI hardware?
-       par->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF;
+       par->vram_size = aty_ld_le32(CNFG_MEMSIZE) & 0x03FFFFFF;
 
        /* Virtualize the framebuffer */
        info->screen_base = ioremap(fb_addr, par->vram_size);
index cc6b470..1d6e16d 100644 (file)
 #if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || \
 defined (CONFIG_FB_ATY_GENERIC_LCD) || defined(CONFIG_FB_ATY_BACKLIGHT)
 static const u32 lt_lcd_regs[] = {
-       CONFIG_PANEL_LG,
+       CNFG_PANEL_LG,
        LCD_GEN_CNTL_LG,
        DSTN_CONTROL_LG,
        HFB_PITCH_ADDR_LG,
@@ -446,7 +446,7 @@ static int __devinit correct_chipset(struct atyfb_par *par)
        par->pll_limits.ecp_max = aty_chips[i].ecp_max;
        par->features = aty_chips[i].features;
 
-       chip_id = aty_ld_le32(CONFIG_CHIP_ID, par);
+       chip_id = aty_ld_le32(CNFG_CHIP_ID, par);
        type = chip_id & CFG_CHIP_TYPE;
        rev = (chip_id & CFG_CHIP_REV) >> 24;
 
@@ -629,7 +629,7 @@ static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc)
                    crtc->lcd_index = aty_ld_le32(LCD_INDEX, par);
                    aty_st_le32(LCD_INDEX, crtc->lcd_index, par);
                }
-               crtc->lcd_config_panel = aty_ld_lcd(CONFIG_PANEL, par);
+               crtc->lcd_config_panel = aty_ld_lcd(CNFG_PANEL, par);
                crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par);
 
 
@@ -676,7 +676,7 @@ static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc)
                aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl & ~(CRTC_EXT_DISP_EN | CRTC_EN), par);
 
                /* update non-shadow registers first */
-               aty_st_lcd(CONFIG_PANEL, crtc->lcd_config_panel, par);
+               aty_st_lcd(CNFG_PANEL, crtc->lcd_config_panel, par);
                aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl &
                        ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par);
 
@@ -858,7 +858,7 @@ static int aty_var_to_crtc(const struct fb_info *info,
                if (!M64_HAS(MOBIL_BUS))
                        crtc->lcd_index |= CRTC2_DISPLAY_DIS;
 
-               crtc->lcd_config_panel = aty_ld_lcd(CONFIG_PANEL, par) | 0x4000;
+               crtc->lcd_config_panel = aty_ld_lcd(CNFG_PANEL, par) | 0x4000;
                crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par) & ~CRTC_RW_SELECT;
 
                crtc->lcd_gen_cntl &=
@@ -2254,7 +2254,7 @@ static int __devinit aty_init(struct fb_info *info)
        if (!M64_HAS(INTEGRATED)) {
                u32 stat0;
                u8 dac_type, dac_subtype, clk_type;
-               stat0 = aty_ld_le32(CONFIG_STAT0, par);
+               stat0 = aty_ld_le32(CNFG_STAT0, par);
                par->bus_type = (stat0 >> 0) & 0x07;
                par->ram_type = (stat0 >> 3) & 0x07;
                ramname = aty_gx_ram[par->ram_type];
@@ -2324,7 +2324,7 @@ static int __devinit aty_init(struct fb_info *info)
                par->dac_ops = &aty_dac_ct;
                par->pll_ops = &aty_pll_ct;
                par->bus_type = PCI;
-               par->ram_type = (aty_ld_le32(CONFIG_STAT0, par) & 0x07);
+               par->ram_type = (aty_ld_le32(CNFG_STAT0, par) & 0x07);
                ramname = aty_ct_ram[par->ram_type];
                /* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */
                if (par->pll_limits.mclk == 67 && par->ram_type < SDRAM)
@@ -2433,7 +2433,7 @@ static int __devinit aty_init(struct fb_info *info)
                }
 
        if (M64_HAS(MAGIC_VRAM_SIZE)) {
-               if (aty_ld_le32(CONFIG_STAT1, par) & 0x40000000)
+               if (aty_ld_le32(CNFG_STAT1, par) & 0x40000000)
                        info->fix.smem_len += 0x400000;
        }
 
@@ -2946,7 +2946,7 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
                 * Fix PROMs idea of MEM_CNTL settings...
                 */
                mem = aty_ld_le32(MEM_CNTL, par);
-               chip_id = aty_ld_le32(CONFIG_CHIP_ID, par);
+               chip_id = aty_ld_le32(CNFG_CHIP_ID, par);
                if (((chip_id & CFG_CHIP_TYPE) == VT_CHIP_ID) && !((chip_id >> 24) & 1)) {
                        switch (mem & 0x0f) {
                        case 3:
@@ -2964,7 +2964,7 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
                        default:
                                break;
                        }
-                       if ((aty_ld_le32(CONFIG_STAT0, par) & 7) >= SDRAM)
+                       if ((aty_ld_le32(CNFG_STAT0, par) & 7) >= SDRAM)
                                mem &= ~(0x00700000);
                }
                mem &= ~(0xcf80e000);   /* Turn off all undocumented bits. */
@@ -3572,7 +3572,7 @@ static int __init atyfb_atari_probe(void)
                }
 
                /* Fake pci_id for correct_chipset() */
-               switch (aty_ld_le32(CONFIG_CHIP_ID, par) & CFG_CHIP_TYPE) {
+               switch (aty_ld_le32(CNFG_CHIP_ID, par) & CFG_CHIP_TYPE) {
                case 0x00d7:
                        par->pci_id = PCI_CHIP_MACH64GX;
                        break;
index d0f1a7f..16bb7e3 100644 (file)
@@ -1936,8 +1936,8 @@ static void fixup_memory_mappings(struct radeonfb_info *rinfo)
        OUTREG(CRTC_GEN_CNTL, save_crtc_gen_cntl | CRTC_DISP_REQ_EN_B);
        mdelay(100);
 
-       aper_base = INREG(CONFIG_APER_0_BASE);
-       aper_size = INREG(CONFIG_APER_SIZE);
+       aper_base = INREG(CNFG_APER_0_BASE);
+       aper_size = INREG(CNFG_APER_SIZE);
 
 #ifdef SET_MC_FB_FROM_APERTURE
        /* Set framebuffer to be at the same address as set in PCI BAR */
@@ -2024,11 +2024,11 @@ static void radeon_identify_vram(struct radeonfb_info *rinfo)
                      ~CRTC_H_CUTOFF_ACTIVE_EN);
           }
         } else {
-          tmp = INREG(CONFIG_MEMSIZE);
+          tmp = INREG(CNFG_MEMSIZE);
         }
 
        /* mem size is bits [28:0], mask off the rest */
-       rinfo->video_ram = tmp & CONFIG_MEMSIZE_MASK;
+       rinfo->video_ram = tmp & CNFG_MEMSIZE_MASK;
 
        /*
         * Hack to get around some busted production M6's
@@ -2228,7 +2228,7 @@ static int __devinit radeonfb_pci_register (struct pci_dev *pdev,
         */
        rinfo->errata = 0;
        if (rinfo->family == CHIP_FAMILY_R300 &&
-           (INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK)
+           (INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK)
            == CFG_ATI_REV_A11)
                rinfo->errata |= CHIP_ERRATA_R300_CG;
 
index 675abda..c4ac2a0 100644 (file)
@@ -333,7 +333,7 @@ static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo)
        if (!rinfo->has_CRTC2) {
                 tmp = INPLL(pllSCLK_CNTL);
 
-               if ((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) > CFG_ATI_REV_A13)
+               if ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) > CFG_ATI_REV_A13)
                     tmp &= ~(SCLK_CNTL__FORCE_CP       | SCLK_CNTL__FORCE_RB);
                 tmp &= ~(SCLK_CNTL__FORCE_HDP          | SCLK_CNTL__FORCE_DISP1 |
                         SCLK_CNTL__FORCE_TOP           | SCLK_CNTL__FORCE_SE   |
@@ -468,9 +468,9 @@ static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo)
 
        /*RAGE_6::A11 A12 A12N1 A13, RV250::A11 A12, R300*/
        if ((rinfo->family == CHIP_FAMILY_RV250 &&
-            ((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) ||
+            ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) ||
            ((rinfo->family == CHIP_FAMILY_RV100) &&
-            ((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) <= CFG_ATI_REV_A13))) {
+            ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) <= CFG_ATI_REV_A13))) {
                tmp |= SCLK_CNTL__FORCE_CP;
                tmp |= SCLK_CNTL__FORCE_VIP;
        }
@@ -486,7 +486,7 @@ static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo)
                /* RV200::A11 A12 RV250::A11 A12 */
                if (((rinfo->family == CHIP_FAMILY_RV200) ||
                     (rinfo->family == CHIP_FAMILY_RV250)) &&
-                   ((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13))
+                   ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13))
                        tmp |= SCLK_MORE_CNTL__FORCEON;
 
                OUTPLL(pllSCLK_MORE_CNTL, tmp);
@@ -497,7 +497,7 @@ static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo)
        /* RV200::A11 A12, RV250::A11 A12 */
        if (((rinfo->family == CHIP_FAMILY_RV200) ||
             (rinfo->family == CHIP_FAMILY_RV250)) &&
-           ((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) {
+           ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) {
                tmp = INPLL(pllPLL_PWRMGT_CNTL);
                tmp |= PLL_PWRMGT_CNTL__TCL_BYPASS_DISABLE;
                OUTPLL(pllPLL_PWRMGT_CNTL, tmp);
@@ -702,7 +702,7 @@ static void radeon_pm_restore_regs(struct radeonfb_info *rinfo)
        OUTREG(DISPLAY_BASE_ADDR, rinfo->save_regs[31]);
        OUTREG(MC_AGP_LOCATION, rinfo->save_regs[32]);
        OUTREG(CRTC2_DISPLAY_BASE_ADDR, rinfo->save_regs[33]);
-       OUTREG(CONFIG_MEMSIZE, rinfo->video_ram);
+       OUTREG(CNFG_MEMSIZE, rinfo->video_ram);
 
        OUTREG(DISP_MISC_CNTL, rinfo->save_regs[9]);
        OUTREG(DISP_PWR_MAN, rinfo->save_regs[10]);
@@ -1723,7 +1723,7 @@ static void radeon_reinitialize_M10(struct radeonfb_info *rinfo)
        OUTREG(CRTC2_DISPLAY_BASE_ADDR, rinfo->save_regs[33]);
        OUTREG(MC_FB_LOCATION, rinfo->save_regs[30]);
        OUTREG(OV0_BASE_ADDR, rinfo->save_regs[80]);
-       OUTREG(CONFIG_MEMSIZE, rinfo->video_ram);
+       OUTREG(CNFG_MEMSIZE, rinfo->video_ram);
        OUTREG(BUS_CNTL, rinfo->save_regs[36]);
        OUTREG(BUS_CNTL1, rinfo->save_regs[14]);
        OUTREG(MPP_TB_CONFIG, rinfo->save_regs[37]);
@@ -1961,7 +1961,7 @@ static void radeon_pm_m9p_reconfigure_mc(struct radeonfb_info *rinfo)
        OUTMC(rinfo, ixMC_CHP_IO_CNTL_B1, rinfo->save_regs[68] /*0x141555ff*/);
        OUTMC(rinfo, ixMC_IMP_CNTL_0, rinfo->save_regs[71] /*0x00009249*/);
        OUTREG(MC_IND_INDEX, 0);
-       OUTREG(CONFIG_MEMSIZE, rinfo->video_ram);
+       OUTREG(CNFG_MEMSIZE, rinfo->video_ram);
 
        mdelay(20);
 }
@@ -2361,7 +2361,7 @@ static void radeon_reinitialize_QW(struct radeonfb_info *rinfo)
        OUTMC(rinfo, ixMC_IMP_CNTL_0, 0x00009249);
        OUTREG(MC_IND_INDEX, 0);
 
-       OUTREG(CONFIG_MEMSIZE, rinfo->video_ram);
+       OUTREG(CNFG_MEMSIZE, rinfo->video_ram);
 
        radeon_pm_full_reset_sdram(rinfo);
 
index 363b3cb..63d7594 100644 (file)
@@ -18,7 +18,7 @@ obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o
 obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o
 obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o
 obj-$(CONFIG_BACKLIGHT_PWM)    += pwm_bl.o
-obj-$(CONFIG_BACKLIGHT_DA903X) += da903x.o
+obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o
 obj-$(CONFIG_BACKLIGHT_MBP_NVIDIA) += mbp_nvidia_bl.o
 obj-$(CONFIG_BACKLIGHT_TOSA)   += tosa_bl.o
 obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o
diff --git a/drivers/video/backlight/da903x.c b/drivers/video/backlight/da903x.c
deleted file mode 100644 (file)
index 93bb434..0000000
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Backlight driver for Dialog Semiconductor DA9030/DA9034
- *
- * Copyright (C) 2008 Compulab, Ltd.
- *     Mike Rapoport <mike@compulab.co.il>
- *
- * Copyright (C) 2006-2008 Marvell International Ltd.
- *     Eric Miao <eric.miao@marvell.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/fb.h>
-#include <linux/backlight.h>
-#include <linux/mfd/da903x.h>
-
-#define DA9030_WLED_CONTROL    0x25
-#define DA9030_WLED_CP_EN      (1 << 6)
-#define DA9030_WLED_TRIM(x)    ((x) & 0x7)
-
-#define DA9034_WLED_CONTROL1   0x3C
-#define DA9034_WLED_CONTROL2   0x3D
-
-#define DA9034_WLED_BOOST_EN   (1 << 5)
-
-#define DA9030_MAX_BRIGHTNESS  7
-#define DA9034_MAX_BRIGHTNESS  0x7f
-
-struct da903x_backlight_data {
-       struct device *da903x_dev;
-       int id;
-       int current_brightness;
-};
-
-static int da903x_backlight_set(struct backlight_device *bl, int brightness)
-{
-       struct da903x_backlight_data *data = bl_get_data(bl);
-       struct device *dev = data->da903x_dev;
-       uint8_t val;
-       int ret = 0;
-
-       switch (data->id) {
-       case DA9034_ID_WLED:
-               ret = da903x_update(dev, DA9034_WLED_CONTROL1,
-                               brightness, 0x7f);
-               if (ret)
-                       return ret;
-
-               if (data->current_brightness && brightness == 0)
-                       ret = da903x_clr_bits(dev,
-                                       DA9034_WLED_CONTROL2,
-                                       DA9034_WLED_BOOST_EN);
-
-               if (data->current_brightness == 0 && brightness)
-                       ret = da903x_set_bits(dev,
-                                       DA9034_WLED_CONTROL2,
-                                       DA9034_WLED_BOOST_EN);
-               break;
-       case DA9030_ID_WLED:
-               val = DA9030_WLED_TRIM(brightness);
-               val |= brightness ? DA9030_WLED_CP_EN : 0;
-               ret = da903x_write(dev, DA9030_WLED_CONTROL, val);
-               break;
-       }
-
-       if (ret)
-               return ret;
-
-       data->current_brightness = brightness;
-       return 0;
-}
-
-static int da903x_backlight_update_status(struct backlight_device *bl)
-{
-       int brightness = bl->props.brightness;
-
-       if (bl->props.power != FB_BLANK_UNBLANK)
-               brightness = 0;
-
-       if (bl->props.fb_blank != FB_BLANK_UNBLANK)
-               brightness = 0;
-
-       return da903x_backlight_set(bl, brightness);
-}
-
-static int da903x_backlight_get_brightness(struct backlight_device *bl)
-{
-       struct da903x_backlight_data *data = bl_get_data(bl);
-       return data->current_brightness;
-}
-
-static struct backlight_ops da903x_backlight_ops = {
-       .update_status  = da903x_backlight_update_status,
-       .get_brightness = da903x_backlight_get_brightness,
-};
-
-static int da903x_backlight_probe(struct platform_device *pdev)
-{
-       struct da903x_backlight_data *data;
-       struct backlight_device *bl;
-       int max_brightness;
-
-       data = kzalloc(sizeof(*data), GFP_KERNEL);
-       if (data == NULL)
-               return -ENOMEM;
-
-       switch (pdev->id) {
-       case DA9030_ID_WLED:
-               max_brightness = DA9030_MAX_BRIGHTNESS;
-               break;
-       case DA9034_ID_WLED:
-               max_brightness = DA9034_MAX_BRIGHTNESS;
-               break;
-       default:
-               dev_err(&pdev->dev, "invalid backlight device ID(%d)\n",
-                               pdev->id);
-               kfree(data);
-               return -EINVAL;
-       }
-
-       data->id = pdev->id;
-       data->da903x_dev = pdev->dev.parent;
-       data->current_brightness = 0;
-
-       bl = backlight_device_register(pdev->name, data->da903x_dev,
-                       data, &da903x_backlight_ops);
-       if (IS_ERR(bl)) {
-               dev_err(&pdev->dev, "failed to register backlight\n");
-               kfree(data);
-               return PTR_ERR(bl);
-       }
-
-       bl->props.max_brightness = max_brightness;
-       bl->props.brightness = max_brightness;
-
-       platform_set_drvdata(pdev, bl);
-       backlight_update_status(bl);
-       return 0;
-}
-
-static int da903x_backlight_remove(struct platform_device *pdev)
-{
-       struct backlight_device *bl = platform_get_drvdata(pdev);
-       struct da903x_backlight_data *data = bl_get_data(bl);
-
-       backlight_device_unregister(bl);
-       kfree(data);
-       return 0;
-}
-
-#ifdef CONFIG_PM
-static int da903x_backlight_suspend(struct platform_device *pdev,
-                                pm_message_t state)
-{
-       struct backlight_device *bl = platform_get_drvdata(pdev);
-       return da903x_backlight_set(bl, 0);
-}
-
-static int da903x_backlight_resume(struct platform_device *pdev)
-{
-       struct backlight_device *bl = platform_get_drvdata(pdev);
-
-       backlight_update_status(bl);
-       return 0;
-}
-#else
-#define da903x_backlight_suspend       NULL
-#define da903x_backlight_resume                NULL
-#endif
-
-static struct platform_driver da903x_backlight_driver = {
-       .driver         = {
-               .name   = "da903x-backlight",
-               .owner  = THIS_MODULE,
-       },
-       .probe          = da903x_backlight_probe,
-       .remove         = da903x_backlight_remove,
-       .suspend        = da903x_backlight_suspend,
-       .resume         = da903x_backlight_resume,
-};
-
-static int __init da903x_backlight_init(void)
-{
-       return platform_driver_register(&da903x_backlight_driver);
-}
-module_init(da903x_backlight_init);
-
-static void __exit da903x_backlight_exit(void)
-{
-       platform_driver_unregister(&da903x_backlight_driver);
-}
-module_exit(da903x_backlight_exit);
-
-MODULE_DESCRIPTION("Backlight Driver for Dialog Semiconductor DA9030/DA9034");
-MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"
-             "Mike Rapoport <mike@compulab.co.il>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:da903x-backlight");
diff --git a/drivers/video/backlight/da903x_bl.c b/drivers/video/backlight/da903x_bl.c
new file mode 100644 (file)
index 0000000..93bb434
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * Backlight driver for Dialog Semiconductor DA9030/DA9034
+ *
+ * Copyright (C) 2008 Compulab, Ltd.
+ *     Mike Rapoport <mike@compulab.co.il>
+ *
+ * Copyright (C) 2006-2008 Marvell International Ltd.
+ *     Eric Miao <eric.miao@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+#include <linux/backlight.h>
+#include <linux/mfd/da903x.h>
+
+#define DA9030_WLED_CONTROL    0x25
+#define DA9030_WLED_CP_EN      (1 << 6)
+#define DA9030_WLED_TRIM(x)    ((x) & 0x7)
+
+#define DA9034_WLED_CONTROL1   0x3C
+#define DA9034_WLED_CONTROL2   0x3D
+
+#define DA9034_WLED_BOOST_EN   (1 << 5)
+
+#define DA9030_MAX_BRIGHTNESS  7
+#define DA9034_MAX_BRIGHTNESS  0x7f
+
+struct da903x_backlight_data {
+       struct device *da903x_dev;
+       int id;
+       int current_brightness;
+};
+
+static int da903x_backlight_set(struct backlight_device *bl, int brightness)
+{
+       struct da903x_backlight_data *data = bl_get_data(bl);
+       struct device *dev = data->da903x_dev;
+       uint8_t val;
+       int ret = 0;
+
+       switch (data->id) {
+       case DA9034_ID_WLED:
+               ret = da903x_update(dev, DA9034_WLED_CONTROL1,
+                               brightness, 0x7f);
+               if (ret)
+                       return ret;
+
+               if (data->current_brightness && brightness == 0)
+                       ret = da903x_clr_bits(dev,
+                                       DA9034_WLED_CONTROL2,
+                                       DA9034_WLED_BOOST_EN);
+
+               if (data->current_brightness == 0 && brightness)
+                       ret = da903x_set_bits(dev,
+                                       DA9034_WLED_CONTROL2,
+                                       DA9034_WLED_BOOST_EN);
+               break;
+       case DA9030_ID_WLED:
+               val = DA9030_WLED_TRIM(brightness);
+               val |= brightness ? DA9030_WLED_CP_EN : 0;
+               ret = da903x_write(dev, DA9030_WLED_CONTROL, val);
+               break;
+       }
+
+       if (ret)
+               return ret;
+
+       data->current_brightness = brightness;
+       return 0;
+}
+
+static int da903x_backlight_update_status(struct backlight_device *bl)
+{
+       int brightness = bl->props.brightness;
+
+       if (bl->props.power != FB_BLANK_UNBLANK)
+               brightness = 0;
+
+       if (bl->props.fb_blank != FB_BLANK_UNBLANK)
+               brightness = 0;
+
+       return da903x_backlight_set(bl, brightness);
+}
+
+static int da903x_backlight_get_brightness(struct backlight_device *bl)
+{
+       struct da903x_backlight_data *data = bl_get_data(bl);
+       return data->current_brightness;
+}
+
+static struct backlight_ops da903x_backlight_ops = {
+       .update_status  = da903x_backlight_update_status,
+       .get_brightness = da903x_backlight_get_brightness,
+};
+
+static int da903x_backlight_probe(struct platform_device *pdev)
+{
+       struct da903x_backlight_data *data;
+       struct backlight_device *bl;
+       int max_brightness;
+
+       data = kzalloc(sizeof(*data), GFP_KERNEL);
+       if (data == NULL)
+               return -ENOMEM;
+
+       switch (pdev->id) {
+       case DA9030_ID_WLED:
+               max_brightness = DA9030_MAX_BRIGHTNESS;
+               break;
+       case DA9034_ID_WLED:
+               max_brightness = DA9034_MAX_BRIGHTNESS;
+               break;
+       default:
+               dev_err(&pdev->dev, "invalid backlight device ID(%d)\n",
+                               pdev->id);
+               kfree(data);
+               return -EINVAL;
+       }
+
+       data->id = pdev->id;
+       data->da903x_dev = pdev->dev.parent;
+       data->current_brightness = 0;
+
+       bl = backlight_device_register(pdev->name, data->da903x_dev,
+                       data, &da903x_backlight_ops);
+       if (IS_ERR(bl)) {
+               dev_err(&pdev->dev, "failed to register backlight\n");
+               kfree(data);
+               return PTR_ERR(bl);
+       }
+
+       bl->props.max_brightness = max_brightness;
+       bl->props.brightness = max_brightness;
+
+       platform_set_drvdata(pdev, bl);
+       backlight_update_status(bl);
+       return 0;
+}
+
+static int da903x_backlight_remove(struct platform_device *pdev)
+{
+       struct backlight_device *bl = platform_get_drvdata(pdev);
+       struct da903x_backlight_data *data = bl_get_data(bl);
+
+       backlight_device_unregister(bl);
+       kfree(data);
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int da903x_backlight_suspend(struct platform_device *pdev,
+                                pm_message_t state)
+{
+       struct backlight_device *bl = platform_get_drvdata(pdev);
+       return da903x_backlight_set(bl, 0);
+}
+
+static int da903x_backlight_resume(struct platform_device *pdev)
+{
+       struct backlight_device *bl = platform_get_drvdata(pdev);
+
+       backlight_update_status(bl);
+       return 0;
+}
+#else
+#define da903x_backlight_suspend       NULL
+#define da903x_backlight_resume                NULL
+#endif
+
+static struct platform_driver da903x_backlight_driver = {
+       .driver         = {
+               .name   = "da903x-backlight",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = da903x_backlight_probe,
+       .remove         = da903x_backlight_remove,
+       .suspend        = da903x_backlight_suspend,
+       .resume         = da903x_backlight_resume,
+};
+
+static int __init da903x_backlight_init(void)
+{
+       return platform_driver_register(&da903x_backlight_driver);
+}
+module_init(da903x_backlight_init);
+
+static void __exit da903x_backlight_exit(void)
+{
+       platform_driver_unregister(&da903x_backlight_driver);
+}
+module_exit(da903x_backlight_exit);
+
+MODULE_DESCRIPTION("Backlight Driver for Dialog Semiconductor DA9030/DA9034");
+MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"
+             "Mike Rapoport <mike@compulab.co.il>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:da903x-backlight");
index 91b78e6..f53b9f1 100644 (file)
@@ -250,10 +250,6 @@ int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *info)
        int rc, size = cmap->len * sizeof(u16);
        struct fb_cmap umap;
 
-       if (cmap->start < 0 || (!info->fbops->fb_setcolreg &&
-                               !info->fbops->fb_setcmap))
-               return -EINVAL;
-
        memset(&umap, 0, sizeof(struct fb_cmap));
        rc = fb_alloc_cmap(&umap, cmap->len, cmap->transp != NULL);
        if (rc)
@@ -262,11 +258,23 @@ int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *info)
            copy_from_user(umap.green, cmap->green, size) ||
            copy_from_user(umap.blue, cmap->blue, size) ||
            (cmap->transp && copy_from_user(umap.transp, cmap->transp, size))) {
-               fb_dealloc_cmap(&umap);
-               return -EFAULT;
+               rc = -EFAULT;
+               goto out;
        }
        umap.start = cmap->start;
+       if (!lock_fb_info(info)) {
+               rc = -ENODEV;
+               goto out;
+       }
+       if (cmap->start < 0 || (!info->fbops->fb_setcolreg &&
+                               !info->fbops->fb_setcmap)) {
+               rc = -EINVAL;
+               goto out1;
+       }
        rc = fb_set_cmap(&umap, info);
+out1:
+       unlock_fb_info(info);
+out:
        fb_dealloc_cmap(&umap);
        return rc;
 }
index 756efeb..cfd9dce 100644 (file)
@@ -1013,132 +1013,139 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
        struct fb_var_screeninfo var;
        struct fb_fix_screeninfo fix;
        struct fb_con2fbmap con2fb;
+       struct fb_cmap cmap_from;
        struct fb_cmap_user cmap;
        struct fb_event event;
        void __user *argp = (void __user *)arg;
        long ret = 0;
 
-       fb = info->fbops;
-       if (!fb)
-               return -ENODEV;
-
        switch (cmd) {
        case FBIOGET_VSCREENINFO:
-               ret = copy_to_user(argp, &info->var,
-                                   sizeof(var)) ? -EFAULT : 0;
+               if (!lock_fb_info(info))
+                       return -ENODEV;
+               var = info->var;
+               unlock_fb_info(info);
+
+               ret = copy_to_user(argp, &var, sizeof(var)) ? -EFAULT : 0;
                break;
        case FBIOPUT_VSCREENINFO:
-               if (copy_from_user(&var, argp, sizeof(var))) {
-                       ret =  -EFAULT;
-                       break;
-               }
+               if (copy_from_user(&var, argp, sizeof(var)))
+                       return -EFAULT;
+               if (!lock_fb_info(info))
+                       return -ENODEV;
                acquire_console_sem();
                info->flags |= FBINFO_MISC_USEREVENT;
                ret = fb_set_var(info, &var);
                info->flags &= ~FBINFO_MISC_USEREVENT;
                release_console_sem();
-               if (ret == 0 && copy_to_user(argp, &var, sizeof(var)))
+               unlock_fb_info(info);
+               if (!ret && copy_to_user(argp, &var, sizeof(var)))
                        ret = -EFAULT;
                break;
        case FBIOGET_FSCREENINFO:
-               ret = copy_to_user(argp, &info->fix,
-                                   sizeof(fix)) ? -EFAULT : 0;
+               if (!lock_fb_info(info))
+                       return -ENODEV;
+               fix = info->fix;
+               unlock_fb_info(info);
+
+               ret = copy_to_user(argp, &fix, sizeof(fix)) ? -EFAULT : 0;
                break;
        case FBIOPUTCMAP:
                if (copy_from_user(&cmap, argp, sizeof(cmap)))
-                       ret = -EFAULT;
-               else
-                       ret = fb_set_user_cmap(&cmap, info);
+                       return -EFAULT;
+               ret = fb_set_user_cmap(&cmap, info);
                break;
        case FBIOGETCMAP:
                if (copy_from_user(&cmap, argp, sizeof(cmap)))
-                       ret = -EFAULT;
-               else
-                       ret = fb_cmap_to_user(&info->cmap, &cmap);
+                       return -EFAULT;
+               if (!lock_fb_info(info))
+                       return -ENODEV;
+               cmap_from = info->cmap;
+               unlock_fb_info(info);
+               ret = fb_cmap_to_user(&cmap_from, &cmap);
                break;
        case FBIOPAN_DISPLAY:
-               if (copy_from_user(&var, argp, sizeof(var))) {
-                       ret = -EFAULT;
-                       break;
-               }
+               if (copy_from_user(&var, argp, sizeof(var)))
+                       return -EFAULT;
+               if (!lock_fb_info(info))
+                       return -ENODEV;
                acquire_console_sem();
                ret = fb_pan_display(info, &var);
                release_console_sem();
+               unlock_fb_info(info);
                if (ret == 0 && copy_to_user(argp, &var, sizeof(var)))
-                       ret = -EFAULT;
+                       return -EFAULT;
                break;
        case FBIO_CURSOR:
                ret = -EINVAL;
                break;
        case FBIOGET_CON2FBMAP:
                if (copy_from_user(&con2fb, argp, sizeof(con2fb)))
-                       ret = -EFAULT;
-               else if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
-                       ret = -EINVAL;
-               else {
-                       con2fb.framebuffer = -1;
-                       event.info = info;
-                       event.data = &con2fb;
-                       fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP,
-                                                               &event);
-                       ret = copy_to_user(argp, &con2fb,
-                                   sizeof(con2fb)) ? -EFAULT : 0;
-               }
+                       return -EFAULT;
+               if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
+                       return -EINVAL;
+               con2fb.framebuffer = -1;
+               event.data = &con2fb;
+
+               if (!lock_fb_info(info))
+                       return -ENODEV;
+               event.info = info;
+               fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, &event);
+               unlock_fb_info(info);
+
+               ret = copy_to_user(argp, &con2fb, sizeof(con2fb)) ? -EFAULT : 0;
                break;
        case FBIOPUT_CON2FBMAP:
-               if (copy_from_user(&con2fb, argp, sizeof(con2fb))) {
-                       ret = -EFAULT;
-                       break;
-               }
-               if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) {
-                       ret = -EINVAL;
-                       break;
-               }
-               if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX) {
-                       ret = -EINVAL;
-                       break;
-               }
+               if (copy_from_user(&con2fb, argp, sizeof(con2fb)))
+                       return -EFAULT;
+               if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
+                       return -EINVAL;
+               if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX)
+                       return -EINVAL;
                if (!registered_fb[con2fb.framebuffer])
                        request_module("fb%d", con2fb.framebuffer);
                if (!registered_fb[con2fb.framebuffer]) {
                        ret = -EINVAL;
                        break;
                }
-               event.info = info;
                event.data = &con2fb;
+               if (!lock_fb_info(info))
+                       return -ENODEV;
+               event.info = info;
                ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP,
                                              &event);
+               unlock_fb_info(info);
                break;
        case FBIOBLANK:
+               if (!lock_fb_info(info))
+                       return -ENODEV;
                acquire_console_sem();
                info->flags |= FBINFO_MISC_USEREVENT;
                ret = fb_blank(info, arg);
                info->flags &= ~FBINFO_MISC_USEREVENT;
                release_console_sem();
-               break;;
+               unlock_fb_info(info);
+               break;
        default:
-               if (fb->fb_ioctl == NULL)
-                       ret = -ENOTTY;
-               else
+               if (!lock_fb_info(info))
+                       return -ENODEV;
+               fb = info->fbops;
+               if (fb->fb_ioctl)
                        ret = fb->fb_ioctl(info, cmd, arg);
+               else
+                       ret = -ENOTTY;
+               unlock_fb_info(info);
        }
        return ret;
 }
 
 static long fb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-__acquires(&info->lock)
-__releases(&info->lock)
 {
        struct inode *inode = file->f_path.dentry->d_inode;
        int fbidx = iminor(inode);
-       struct fb_info *info;
-       long ret;
+       struct fb_info *info = registered_fb[fbidx];
 
-       info = registered_fb[fbidx];
-       mutex_lock(&info->lock);
-       ret = do_fb_ioctl(info, cmd, arg);
-       mutex_unlock(&info->lock);
-       return ret;
+       return do_fb_ioctl(info, cmd, arg);
 }
 
 #ifdef CONFIG_COMPAT
@@ -1257,8 +1264,6 @@ static int fb_get_fscreeninfo(struct fb_info *info, unsigned int cmd,
 
 static long fb_compat_ioctl(struct file *file, unsigned int cmd,
                            unsigned long arg)
-__acquires(&info->lock)
-__releases(&info->lock)
 {
        struct inode *inode = file->f_path.dentry->d_inode;
        int fbidx = iminor(inode);
@@ -1266,7 +1271,6 @@ __releases(&info->lock)
        struct fb_ops *fb = info->fbops;
        long ret = -ENOIOCTLCMD;
 
-       mutex_lock(&info->lock);
        switch(cmd) {
        case FBIOGET_VSCREENINFO:
        case FBIOPUT_VSCREENINFO:
@@ -1292,7 +1296,6 @@ __releases(&info->lock)
                        ret = fb->fb_compat_ioctl(info, cmd, arg);
                break;
        }
-       mutex_unlock(&info->lock);
        return ret;
 }
 #endif
index e3ff2b9..33b7235 100644 (file)
@@ -1208,9 +1208,11 @@ static unsigned long vma_dump_size(struct vm_area_struct *vma,
         * check for an ELF header.  If we find one, dump the first page to
         * aid in determining what was mapped here.
         */
-       if (FILTER(ELF_HEADERS) && vma->vm_file != NULL && vma->vm_pgoff == 0) {
+       if (FILTER(ELF_HEADERS) &&
+           vma->vm_pgoff == 0 && (vma->vm_flags & VM_READ)) {
                u32 __user *header = (u32 __user *) vma->vm_start;
                u32 word;
+               mm_segment_t fs = get_fs();
                /*
                 * Doing it this way gets the constant folded by GCC.
                 */
@@ -1223,7 +1225,15 @@ static unsigned long vma_dump_size(struct vm_area_struct *vma,
                magic.elfmag[EI_MAG1] = ELFMAG1;
                magic.elfmag[EI_MAG2] = ELFMAG2;
                magic.elfmag[EI_MAG3] = ELFMAG3;
-               if (get_user(word, header) == 0 && word == magic.cmp)
+               /*
+                * Switch to the user "segment" for get_user(),
+                * then put back what elf_core_dump() had in place.
+                */
+               set_fs(USER_DS);
+               if (unlikely(get_user(word, header)))
+                       word = 0;
+               set_fs(fs);
+               if (word == magic.cmp)
                        return PAGE_SIZE;
        }
 
index f8fcf99..7bb3c02 100644 (file)
@@ -16,3 +16,16 @@ config BTRFS_FS
          module will be called btrfs.
 
          If unsure, say N.
+
+config BTRFS_FS_POSIX_ACL
+       bool "Btrfs POSIX Access Control Lists"
+       depends on BTRFS_FS
+       select FS_POSIX_ACL
+       help
+         POSIX Access Control Lists (ACLs) support permissions for users and
+         groups beyond the owner/group/world scheme.
+
+         To learn more about Access Control Lists, visit the POSIX ACLs for
+         Linux website <http://acl.bestbits.at/>.
+
+         If you don't know what Access Control Lists are, say N
index 8e2fec0..c84ca1f 100644 (file)
  * Boston, MA 021110-1307, USA.
  */
 
-#include <linux/version.h>
 #include <linux/kthread.h>
 #include <linux/list.h>
 #include <linux/spinlock.h>
-# include <linux/freezer.h>
+#include <linux/freezer.h>
+#include <linux/ftrace.h>
 #include "async-thread.h"
 
 #define WORK_QUEUED_BIT 0
@@ -143,6 +143,7 @@ static int worker_loop(void *arg)
        struct btrfs_work *work;
        do {
                spin_lock_irq(&worker->lock);
+again_locked:
                while (!list_empty(&worker->pending)) {
                        cur = worker->pending.next;
                        work = list_entry(cur, struct btrfs_work, list);
@@ -165,14 +166,50 @@ static int worker_loop(void *arg)
                        check_idle_worker(worker);
 
                }
-               worker->working = 0;
                if (freezing(current)) {
+                       worker->working = 0;
+                       spin_unlock_irq(&worker->lock);
                        refrigerator();
                } else {
-                       set_current_state(TASK_INTERRUPTIBLE);
                        spin_unlock_irq(&worker->lock);
-                       if (!kthread_should_stop())
+                       if (!kthread_should_stop()) {
+                               cpu_relax();
+                               /*
+                                * we've dropped the lock, did someone else
+                                * jump_in?
+                                */
+                               smp_mb();
+                               if (!list_empty(&worker->pending))
+                                       continue;
+
+                               /*
+                                * this short schedule allows more work to
+                                * come in without the queue functions
+                                * needing to go through wake_up_process()
+                                *
+                                * worker->working is still 1, so nobody
+                                * is going to try and wake us up
+                                */
+                               schedule_timeout(1);
+                               smp_mb();
+                               if (!list_empty(&worker->pending))
+                                       continue;
+
+                               /* still no more work?, sleep for real */
+                               spin_lock_irq(&worker->lock);
+                               set_current_state(TASK_INTERRUPTIBLE);
+                               if (!list_empty(&worker->pending))
+                                       goto again_locked;
+
+                               /*
+                                * this makes sure we get a wakeup when someone
+                                * adds something new to the queue
+                                */
+                               worker->working = 0;
+                               spin_unlock_irq(&worker->lock);
+
                                schedule();
+                       }
                        __set_current_state(TASK_RUNNING);
                }
        } while (!kthread_should_stop());
@@ -350,13 +387,14 @@ int btrfs_requeue_work(struct btrfs_work *work)
 {
        struct btrfs_worker_thread *worker = work->worker;
        unsigned long flags;
+       int wake = 0;
 
        if (test_and_set_bit(WORK_QUEUED_BIT, &work->flags))
                goto out;
 
        spin_lock_irqsave(&worker->lock, flags);
-       atomic_inc(&worker->num_pending);
        list_add_tail(&work->list, &worker->pending);
+       atomic_inc(&worker->num_pending);
 
        /* by definition we're busy, take ourselves off the idle
         * list
@@ -368,10 +406,16 @@ int btrfs_requeue_work(struct btrfs_work *work)
                               &worker->workers->worker_list);
                spin_unlock_irqrestore(&worker->workers->lock, flags);
        }
+       if (!worker->working) {
+               wake = 1;
+               worker->working = 1;
+       }
 
        spin_unlock_irqrestore(&worker->lock, flags);
-
+       if (wake)
+               wake_up_process(worker->task);
 out:
+
        return 0;
 }
 
@@ -398,9 +442,10 @@ int btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work)
        }
 
        spin_lock_irqsave(&worker->lock, flags);
+
+       list_add_tail(&work->list, &worker->pending);
        atomic_inc(&worker->num_pending);
        check_busy_worker(worker);
-       list_add_tail(&work->list, &worker->pending);
 
        /*
         * avoid calling into wake_up_process if this thread has already
index ee848d8..ab07627 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/swap.h>
 #include <linux/writeback.h>
 #include <linux/bit_spinlock.h>
-#include <linux/version.h>
 #include <linux/pagevec.h>
 #include "compat.h"
 #include "ctree.h"
index 9e46c07..551177c 100644 (file)
@@ -54,6 +54,31 @@ struct btrfs_path *btrfs_alloc_path(void)
        return path;
 }
 
+/*
+ * set all locked nodes in the path to blocking locks.  This should
+ * be done before scheduling
+ */
+noinline void btrfs_set_path_blocking(struct btrfs_path *p)
+{
+       int i;
+       for (i = 0; i < BTRFS_MAX_LEVEL; i++) {
+               if (p->nodes[i] && p->locks[i])
+                       btrfs_set_lock_blocking(p->nodes[i]);
+       }
+}
+
+/*
+ * reset all the locked nodes in the patch to spinning locks.
+ */
+noinline void btrfs_clear_path_blocking(struct btrfs_path *p)
+{
+       int i;
+       for (i = 0; i < BTRFS_MAX_LEVEL; i++) {
+               if (p->nodes[i] && p->locks[i])
+                       btrfs_clear_lock_blocking(p->nodes[i]);
+       }
+}
+
 /* this also releases the path */
 void btrfs_free_path(struct btrfs_path *p)
 {
@@ -272,6 +297,8 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
        if (IS_ERR(cow))
                return PTR_ERR(cow);
 
+       /* cow is set to blocking by btrfs_init_new_buffer */
+
        copy_extent_buffer(cow, buf, 0, 0, cow->len);
        btrfs_set_header_bytenr(cow, cow->start);
        btrfs_set_header_generation(cow, trans->transid);
@@ -388,17 +415,20 @@ noinline int btrfs_cow_block(struct btrfs_trans_handle *trans,
                WARN_ON(1);
        }
 
-       spin_lock(&root->fs_info->hash_lock);
        if (btrfs_header_generation(buf) == trans->transid &&
            btrfs_header_owner(buf) == root->root_key.objectid &&
            !btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN)) {
                *cow_ret = buf;
-               spin_unlock(&root->fs_info->hash_lock);
                WARN_ON(prealloc_dest);
                return 0;
        }
-       spin_unlock(&root->fs_info->hash_lock);
+
        search_start = buf->start & ~((u64)(1024 * 1024 * 1024) - 1);
+
+       if (parent)
+               btrfs_set_lock_blocking(parent);
+       btrfs_set_lock_blocking(buf);
+
        ret = __btrfs_cow_block(trans, root, buf, parent,
                                 parent_slot, cow_ret, search_start, 0,
                                 prealloc_dest);
@@ -504,6 +534,8 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
        if (parent_nritems == 1)
                return 0;
 
+       btrfs_set_lock_blocking(parent);
+
        for (i = start_slot; i < end_slot; i++) {
                int close = 1;
 
@@ -564,6 +596,7 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
                        search_start = last_block;
 
                btrfs_tree_lock(cur);
+               btrfs_set_lock_blocking(cur);
                err = __btrfs_cow_block(trans, root, cur, parent, i,
                                        &cur, search_start,
                                        min(16 * blocksize,
@@ -862,6 +895,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
                return 0;
 
        mid = path->nodes[level];
+
        WARN_ON(!path->locks[level]);
        WARN_ON(btrfs_header_generation(mid) != trans->transid);
 
@@ -884,6 +918,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
                /* promote the child to a root */
                child = read_node_slot(root, mid, 0);
                btrfs_tree_lock(child);
+               btrfs_set_lock_blocking(child);
                BUG_ON(!child);
                ret = btrfs_cow_block(trans, root, child, mid, 0, &child, 0);
                BUG_ON(ret);
@@ -900,6 +935,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
 
                add_root_to_dirty_list(root);
                btrfs_tree_unlock(child);
+
                path->locks[level] = 0;
                path->nodes[level] = NULL;
                clean_tree_block(trans, root, mid);
@@ -924,6 +960,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
        left = read_node_slot(root, parent, pslot - 1);
        if (left) {
                btrfs_tree_lock(left);
+               btrfs_set_lock_blocking(left);
                wret = btrfs_cow_block(trans, root, left,
                                       parent, pslot - 1, &left, 0);
                if (wret) {
@@ -934,6 +971,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
        right = read_node_slot(root, parent, pslot + 1);
        if (right) {
                btrfs_tree_lock(right);
+               btrfs_set_lock_blocking(right);
                wret = btrfs_cow_block(trans, root, right,
                                       parent, pslot + 1, &right, 0);
                if (wret) {
@@ -1109,6 +1147,8 @@ static noinline int push_nodes_for_insert(struct btrfs_trans_handle *trans,
                u32 left_nr;
 
                btrfs_tree_lock(left);
+               btrfs_set_lock_blocking(left);
+
                left_nr = btrfs_header_nritems(left);
                if (left_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) {
                        wret = 1;
@@ -1155,7 +1195,10 @@ static noinline int push_nodes_for_insert(struct btrfs_trans_handle *trans,
         */
        if (right) {
                u32 right_nr;
+
                btrfs_tree_lock(right);
+               btrfs_set_lock_blocking(right);
+
                right_nr = btrfs_header_nritems(right);
                if (right_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) {
                        wret = 1;
@@ -1210,8 +1253,7 @@ static noinline void reada_for_search(struct btrfs_root *root,
        struct btrfs_disk_key disk_key;
        u32 nritems;
        u64 search;
-       u64 lowest_read;
-       u64 highest_read;
+       u64 target;
        u64 nread = 0;
        int direction = path->reada;
        struct extent_buffer *eb;
@@ -1235,8 +1277,7 @@ static noinline void reada_for_search(struct btrfs_root *root,
                return;
        }
 
-       highest_read = search;
-       lowest_read = search;
+       target = search;
 
        nritems = btrfs_header_nritems(node);
        nr = slot;
@@ -1256,27 +1297,80 @@ static noinline void reada_for_search(struct btrfs_root *root,
                                break;
                }
                search = btrfs_node_blockptr(node, nr);
-               if ((search >= lowest_read && search <= highest_read) ||
-                   (search < lowest_read && lowest_read - search <= 16384) ||
-                   (search > highest_read && search - highest_read <= 16384)) {
+               if ((search <= target && target - search <= 65536) ||
+                   (search > target && search - target <= 65536)) {
                        readahead_tree_block(root, search, blocksize,
                                     btrfs_node_ptr_generation(node, nr));
                        nread += blocksize;
                }
                nscan++;
-               if (path->reada < 2 && (nread > (64 * 1024) || nscan > 32))
+               if ((nread > 65536 || nscan > 32))
                        break;
+       }
+}
 
-               if (nread > (256 * 1024) || nscan > 128)
-                       break;
+/*
+ * returns -EAGAIN if it had to drop the path, or zero if everything was in
+ * cache
+ */
+static noinline int reada_for_balance(struct btrfs_root *root,
+                                     struct btrfs_path *path, int level)
+{
+       int slot;
+       int nritems;
+       struct extent_buffer *parent;
+       struct extent_buffer *eb;
+       u64 gen;
+       u64 block1 = 0;
+       u64 block2 = 0;
+       int ret = 0;
+       int blocksize;
 
-               if (search < lowest_read)
-                       lowest_read = search;
-               if (search > highest_read)
-                       highest_read = search;
+       parent = path->nodes[level - 1];
+       if (!parent)
+               return 0;
+
+       nritems = btrfs_header_nritems(parent);
+       slot = path->slots[level];
+       blocksize = btrfs_level_size(root, level);
+
+       if (slot > 0) {
+               block1 = btrfs_node_blockptr(parent, slot - 1);
+               gen = btrfs_node_ptr_generation(parent, slot - 1);
+               eb = btrfs_find_tree_block(root, block1, blocksize);
+               if (eb && btrfs_buffer_uptodate(eb, gen))
+                       block1 = 0;
+               free_extent_buffer(eb);
+       }
+       if (slot < nritems) {
+               block2 = btrfs_node_blockptr(parent, slot + 1);
+               gen = btrfs_node_ptr_generation(parent, slot + 1);
+               eb = btrfs_find_tree_block(root, block2, blocksize);
+               if (eb && btrfs_buffer_uptodate(eb, gen))
+                       block2 = 0;
+               free_extent_buffer(eb);
+       }
+       if (block1 || block2) {
+               ret = -EAGAIN;
+               btrfs_release_path(root, path);
+               if (block1)
+                       readahead_tree_block(root, block1, blocksize, 0);
+               if (block2)
+                       readahead_tree_block(root, block2, blocksize, 0);
+
+               if (block1) {
+                       eb = read_tree_block(root, block1, blocksize, 0);
+                       free_extent_buffer(eb);
+               }
+               if (block1) {
+                       eb = read_tree_block(root, block2, blocksize, 0);
+                       free_extent_buffer(eb);
+               }
        }
+       return ret;
 }
 
+
 /*
  * when we walk down the tree, it is usually safe to unlock the higher layers
  * in the tree.  The exceptions are when our path goes through slot 0, because
@@ -1327,6 +1421,32 @@ static noinline void unlock_up(struct btrfs_path *path, int level,
        }
 }
 
+/*
+ * This releases any locks held in the path starting at level and
+ * going all the way up to the root.
+ *
+ * btrfs_search_slot will keep the lock held on higher nodes in a few
+ * corner cases, such as COW of the block at slot zero in the node.  This
+ * ignores those rules, and it should only be called when there are no
+ * more updates to be done higher up in the tree.
+ */
+noinline void btrfs_unlock_up_safe(struct btrfs_path *path, int level)
+{
+       int i;
+
+       if (path->keep_locks || path->lowest_level)
+               return;
+
+       for (i = level; i < BTRFS_MAX_LEVEL; i++) {
+               if (!path->nodes[i])
+                       continue;
+               if (!path->locks[i])
+                       continue;
+               btrfs_tree_unlock(path->nodes[i]);
+               path->locks[i] = 0;
+       }
+}
+
 /*
  * look for key in the tree.  path is filled in with nodes along the way
  * if key is found, we return zero and you can find the item in the leaf
@@ -1387,31 +1507,30 @@ again:
                        int wret;
 
                        /* is a cow on this block not required */
-                       spin_lock(&root->fs_info->hash_lock);
                        if (btrfs_header_generation(b) == trans->transid &&
                            btrfs_header_owner(b) == root->root_key.objectid &&
                            !btrfs_header_flag(b, BTRFS_HEADER_FLAG_WRITTEN)) {
-                               spin_unlock(&root->fs_info->hash_lock);
                                goto cow_done;
                        }
-                       spin_unlock(&root->fs_info->hash_lock);
 
                        /* ok, we have to cow, is our old prealloc the right
                         * size?
                         */
                        if (prealloc_block.objectid &&
                            prealloc_block.offset != b->len) {
+                               btrfs_release_path(root, p);
                                btrfs_free_reserved_extent(root,
                                           prealloc_block.objectid,
                                           prealloc_block.offset);
                                prealloc_block.objectid = 0;
+                               goto again;
                        }
 
                        /*
                         * for higher level blocks, try not to allocate blocks
                         * with the block and the parent locks held.
                         */
-                       if (level > 1 && !prealloc_block.objectid &&
+                       if (level > 0 && !prealloc_block.objectid &&
                            btrfs_path_lock_waiting(p, level)) {
                                u32 size = b->len;
                                u64 hint = b->start;
@@ -1425,6 +1544,8 @@ again:
                                goto again;
                        }
 
+                       btrfs_set_path_blocking(p);
+
                        wret = btrfs_cow_block(trans, root, b,
                                               p->nodes[level + 1],
                                               p->slots[level + 1],
@@ -1446,6 +1567,22 @@ cow_done:
                if (!p->skip_locking)
                        p->locks[level] = 1;
 
+               btrfs_clear_path_blocking(p);
+
+               /*
+                * we have a lock on b and as long as we aren't changing
+                * the tree, there is no way to for the items in b to change.
+                * It is safe to drop the lock on our parent before we
+                * go through the expensive btree search on b.
+                *
+                * If cow is true, then we might be changing slot zero,
+                * which may require changing the parent.  So, we can't
+                * drop the lock until after we know which slot we're
+                * operating on.
+                */
+               if (!cow)
+                       btrfs_unlock_up_safe(p, level + 1);
+
                ret = check_block(root, p, level);
                if (ret) {
                        ret = -1;
@@ -1453,6 +1590,7 @@ cow_done:
                }
 
                ret = bin_search(b, key, level, &slot);
+
                if (level != 0) {
                        if (ret && slot > 0)
                                slot -= 1;
@@ -1460,7 +1598,16 @@ cow_done:
                        if ((p->search_for_split || ins_len > 0) &&
                            btrfs_header_nritems(b) >=
                            BTRFS_NODEPTRS_PER_BLOCK(root) - 3) {
-                               int sret = split_node(trans, root, p, level);
+                               int sret;
+
+                               sret = reada_for_balance(root, p, level);
+                               if (sret)
+                                       goto again;
+
+                               btrfs_set_path_blocking(p);
+                               sret = split_node(trans, root, p, level);
+                               btrfs_clear_path_blocking(p);
+
                                BUG_ON(sret > 0);
                                if (sret) {
                                        ret = sret;
@@ -1468,9 +1615,19 @@ cow_done:
                                }
                                b = p->nodes[level];
                                slot = p->slots[level];
-                       } else if (ins_len < 0) {
-                               int sret = balance_level(trans, root, p,
-                                                        level);
+                       } else if (ins_len < 0 &&
+                                  btrfs_header_nritems(b) <
+                                  BTRFS_NODEPTRS_PER_BLOCK(root) / 4) {
+                               int sret;
+
+                               sret = reada_for_balance(root, p, level);
+                               if (sret)
+                                       goto again;
+
+                               btrfs_set_path_blocking(p);
+                               sret = balance_level(trans, root, p, level);
+                               btrfs_clear_path_blocking(p);
+
                                if (sret) {
                                        ret = sret;
                                        goto done;
@@ -1504,7 +1661,7 @@ cow_done:
                                 * of the btree by dropping locks before
                                 * we read.
                                 */
-                               if (level > 1) {
+                               if (level > 0) {
                                        btrfs_release_path(NULL, p);
                                        if (tmp)
                                                free_extent_buffer(tmp);
@@ -1519,6 +1676,7 @@ cow_done:
                                                free_extent_buffer(tmp);
                                        goto again;
                                } else {
+                                       btrfs_set_path_blocking(p);
                                        if (tmp)
                                                free_extent_buffer(tmp);
                                        if (should_reada)
@@ -1528,14 +1686,29 @@ cow_done:
                                        b = read_node_slot(root, b, slot);
                                }
                        }
-                       if (!p->skip_locking)
-                               btrfs_tree_lock(b);
+                       if (!p->skip_locking) {
+                               int lret;
+
+                               btrfs_clear_path_blocking(p);
+                               lret = btrfs_try_spin_lock(b);
+
+                               if (!lret) {
+                                       btrfs_set_path_blocking(p);
+                                       btrfs_tree_lock(b);
+                                       btrfs_clear_path_blocking(p);
+                               }
+                       }
                } else {
                        p->slots[level] = slot;
                        if (ins_len > 0 &&
                            btrfs_leaf_free_space(root, b) < ins_len) {
-                               int sret = split_leaf(trans, root, key,
+                               int sret;
+
+                               btrfs_set_path_blocking(p);
+                               sret = split_leaf(trans, root, key,
                                                      p, ins_len, ret == 0);
+                               btrfs_clear_path_blocking(p);
+
                                BUG_ON(sret > 0);
                                if (sret) {
                                        ret = sret;
@@ -1549,12 +1722,16 @@ cow_done:
        }
        ret = 1;
 done:
+       /*
+        * we don't really know what they plan on doing with the path
+        * from here on, so for now just mark it as blocking
+        */
+       btrfs_set_path_blocking(p);
        if (prealloc_block.objectid) {
                btrfs_free_reserved_extent(root,
                           prealloc_block.objectid,
                           prealloc_block.offset);
        }
-
        return ret;
 }
 
@@ -1578,6 +1755,8 @@ int btrfs_merge_path(struct btrfs_trans_handle *trans,
        ret = btrfs_cow_block(trans, root, eb, NULL, 0, &eb, 0);
        BUG_ON(ret);
 
+       btrfs_set_lock_blocking(eb);
+
        parent = eb;
        while (1) {
                level = btrfs_header_level(parent);
@@ -1602,6 +1781,7 @@ int btrfs_merge_path(struct btrfs_trans_handle *trans,
                        eb = read_tree_block(root, bytenr, blocksize,
                                             generation);
                        btrfs_tree_lock(eb);
+                       btrfs_set_lock_blocking(eb);
                }
 
                /*
@@ -1626,6 +1806,7 @@ int btrfs_merge_path(struct btrfs_trans_handle *trans,
                                eb = read_tree_block(root, bytenr, blocksize,
                                                generation);
                                btrfs_tree_lock(eb);
+                               btrfs_set_lock_blocking(eb);
                        }
 
                        ret = btrfs_cow_block(trans, root, eb, parent, slot,
@@ -2172,6 +2353,8 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
 
        right = read_node_slot(root, upper, slot + 1);
        btrfs_tree_lock(right);
+       btrfs_set_lock_blocking(right);
+
        free_space = btrfs_leaf_free_space(root, right);
        if (free_space < data_size)
                goto out_unlock;
@@ -2367,6 +2550,8 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
 
        left = read_node_slot(root, path->nodes[1], slot - 1);
        btrfs_tree_lock(left);
+       btrfs_set_lock_blocking(left);
+
        free_space = btrfs_leaf_free_space(root, left);
        if (free_space < data_size) {
                ret = 1;
@@ -2825,6 +3010,12 @@ int btrfs_split_item(struct btrfs_trans_handle *trans,
        path->keep_locks = 0;
        BUG_ON(ret);
 
+       /*
+        * make sure any changes to the path from split_leaf leave it
+        * in a blocking state
+        */
+       btrfs_set_path_blocking(path);
+
        leaf = path->nodes[0];
        BUG_ON(btrfs_leaf_free_space(root, leaf) < sizeof(struct btrfs_item));
 
@@ -3354,6 +3545,7 @@ int btrfs_insert_empty_items(struct btrfs_trans_handle *trans,
                BUG();
        }
 out:
+       btrfs_unlock_up_safe(path, 1);
        return ret;
 }
 
@@ -3441,15 +3633,22 @@ noinline int btrfs_del_leaf(struct btrfs_trans_handle *trans,
 {
        int ret;
        u64 root_gen = btrfs_header_generation(path->nodes[1]);
+       u64 parent_start = path->nodes[1]->start;
+       u64 parent_owner = btrfs_header_owner(path->nodes[1]);
 
        ret = del_ptr(trans, root, path, 1, path->slots[1]);
        if (ret)
                return ret;
 
+       /*
+        * btrfs_free_extent is expensive, we want to make sure we
+        * aren't holding any locks when we call it
+        */
+       btrfs_unlock_up_safe(path, 0);
+
        ret = btrfs_free_extent(trans, root, bytenr,
                                btrfs_level_size(root, 0),
-                               path->nodes[1]->start,
-                               btrfs_header_owner(path->nodes[1]),
+                               parent_start, parent_owner,
                                root_gen, 0, 1);
        return ret;
 }
@@ -3721,12 +3920,14 @@ find_next_key:
                 */
                if (slot >= nritems) {
                        path->slots[level] = slot;
+                       btrfs_set_path_blocking(path);
                        sret = btrfs_find_next_key(root, path, min_key, level,
                                                  cache_only, min_trans);
                        if (sret == 0) {
                                btrfs_release_path(root, path);
                                goto again;
                        } else {
+                               btrfs_clear_path_blocking(path);
                                goto out;
                        }
                }
@@ -3738,16 +3939,20 @@ find_next_key:
                        unlock_up(path, level, 1);
                        goto out;
                }
+               btrfs_set_path_blocking(path);
                cur = read_node_slot(root, cur, slot);
 
                btrfs_tree_lock(cur);
+
                path->locks[level - 1] = 1;
                path->nodes[level - 1] = cur;
                unlock_up(path, level, 1);
+               btrfs_clear_path_blocking(path);
        }
 out:
        if (ret == 0)
                memcpy(min_key, &found_key, sizeof(found_key));
+       btrfs_set_path_blocking(path);
        return ret;
 }
 
@@ -3843,6 +4048,7 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
        if (ret < 0)
                return ret;
 
+       btrfs_set_path_blocking(path);
        nritems = btrfs_header_nritems(path->nodes[0]);
        /*
         * by releasing the path above we dropped all our locks.  A balance
@@ -3873,6 +4079,7 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
                        free_extent_buffer(next);
                }
 
+               /* the path was set to blocking above */
                if (level == 1 && (path->locks[1] || path->skip_locking) &&
                    path->reada)
                        reada_for_search(root, path, level, slot, 0);
@@ -3881,6 +4088,7 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
                if (!path->skip_locking) {
                        WARN_ON(!btrfs_tree_locked(c));
                        btrfs_tree_lock(next);
+                       btrfs_set_lock_blocking(next);
                }
                break;
        }
@@ -3897,12 +4105,15 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
                        path->locks[level] = 1;
                if (!level)
                        break;
+
+               btrfs_set_path_blocking(path);
                if (level == 1 && path->locks[1] && path->reada)
                        reada_for_search(root, path, level, slot, 0);
                next = read_node_slot(root, next, 0);
                if (!path->skip_locking) {
                        WARN_ON(!btrfs_tree_locked(path->nodes[level]));
                        btrfs_tree_lock(next);
+                       btrfs_set_lock_blocking(next);
                }
        }
 done:
@@ -3927,6 +4138,7 @@ int btrfs_previous_item(struct btrfs_root *root,
 
        while (1) {
                if (path->slots[0] == 0) {
+                       btrfs_set_path_blocking(path);
                        ret = btrfs_prev_leaf(root, path);
                        if (ret != 0)
                                return ret;
index eee060f..531db11 100644 (file)
@@ -454,17 +454,11 @@ struct btrfs_timespec {
        __le32 nsec;
 } __attribute__ ((__packed__));
 
-typedef enum {
+enum btrfs_compression_type {
        BTRFS_COMPRESS_NONE = 0,
        BTRFS_COMPRESS_ZLIB = 1,
        BTRFS_COMPRESS_LAST = 2,
-} btrfs_compression_type;
-
-/* we don't understand any encryption methods right now */
-typedef enum {
-       BTRFS_ENCRYPTION_NONE = 0,
-       BTRFS_ENCRYPTION_LAST = 1,
-} btrfs_encryption_type;
+};
 
 struct btrfs_inode_item {
        /* nfs style generation number */
@@ -701,9 +695,7 @@ struct btrfs_fs_info {
        struct btrfs_transaction *running_transaction;
        wait_queue_head_t transaction_throttle;
        wait_queue_head_t transaction_wait;
-
        wait_queue_head_t async_submit_wait;
-       wait_queue_head_t tree_log_wait;
 
        struct btrfs_super_block super_copy;
        struct btrfs_super_block super_for_commit;
@@ -711,7 +703,6 @@ struct btrfs_fs_info {
        struct super_block *sb;
        struct inode *btree_inode;
        struct backing_dev_info bdi;
-       spinlock_t hash_lock;
        struct mutex trans_mutex;
        struct mutex tree_log_mutex;
        struct mutex transaction_kthread_mutex;
@@ -730,10 +721,6 @@ struct btrfs_fs_info {
        atomic_t async_submit_draining;
        atomic_t nr_async_bios;
        atomic_t async_delalloc_pages;
-       atomic_t tree_log_writers;
-       atomic_t tree_log_commit;
-       unsigned long tree_log_batch;
-       u64 tree_log_transid;
 
        /*
         * this is used by the balancing code to wait for all the pending
@@ -833,7 +820,14 @@ struct btrfs_root {
        struct kobject root_kobj;
        struct completion kobj_unregister;
        struct mutex objectid_mutex;
+
        struct mutex log_mutex;
+       wait_queue_head_t log_writer_wait;
+       wait_queue_head_t log_commit_wait[2];
+       atomic_t log_writers;
+       atomic_t log_commit[2];
+       unsigned long log_transid;
+       unsigned long log_batch;
 
        u64 objectid;
        u64 last_trans;
@@ -1841,6 +1835,10 @@ void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p);
 struct btrfs_path *btrfs_alloc_path(void);
 void btrfs_free_path(struct btrfs_path *p);
 void btrfs_init_path(struct btrfs_path *p);
+void btrfs_set_path_blocking(struct btrfs_path *p);
+void btrfs_clear_path_blocking(struct btrfs_path *p);
+void btrfs_unlock_up_safe(struct btrfs_path *p, int level);
+
 int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root,
                   struct btrfs_path *path, int slot, int nr);
 int btrfs_del_leaf(struct btrfs_trans_handle *trans,
index 81a3138..5aebddd 100644 (file)
@@ -16,7 +16,6 @@
  * Boston, MA 021110-1307, USA.
  */
 
-#include <linux/version.h>
 #include <linux/fs.h>
 #include <linux/blkdev.h>
 #include <linux/scatterlist.h>
@@ -800,7 +799,7 @@ struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
        ret = btree_read_extent_buffer_pages(root, buf, 0, parent_transid);
 
        if (ret == 0)
-               buf->flags |= EXTENT_UPTODATE;
+               set_bit(EXTENT_BUFFER_UPTODATE, &buf->bflags);
        else
                WARN_ON(1);
        return buf;
@@ -814,6 +813,10 @@ int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
        if (btrfs_header_generation(buf) ==
            root->fs_info->running_transaction->transid) {
                WARN_ON(!btrfs_tree_locked(buf));
+
+               /* ugh, clear_extent_buffer_dirty can be expensive */
+               btrfs_set_lock_blocking(buf);
+
                clear_extent_buffer_dirty(&BTRFS_I(btree_inode)->io_tree,
                                          buf);
        }
@@ -850,6 +853,14 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
        spin_lock_init(&root->list_lock);
        mutex_init(&root->objectid_mutex);
        mutex_init(&root->log_mutex);
+       init_waitqueue_head(&root->log_writer_wait);
+       init_waitqueue_head(&root->log_commit_wait[0]);
+       init_waitqueue_head(&root->log_commit_wait[1]);
+       atomic_set(&root->log_commit[0], 0);
+       atomic_set(&root->log_commit[1], 0);
+       atomic_set(&root->log_writers, 0);
+       root->log_batch = 0;
+       root->log_transid = 0;
        extent_io_tree_init(&root->dirty_log_pages,
                             fs_info->btree_inode->i_mapping, GFP_NOFS);
 
@@ -934,15 +945,16 @@ int btrfs_free_log_root_tree(struct btrfs_trans_handle *trans,
        return 0;
 }
 
-int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans,
-                            struct btrfs_fs_info *fs_info)
+static struct btrfs_root *alloc_log_tree(struct btrfs_trans_handle *trans,
+                                        struct btrfs_fs_info *fs_info)
 {
        struct btrfs_root *root;
        struct btrfs_root *tree_root = fs_info->tree_root;
+       struct extent_buffer *leaf;
 
        root = kzalloc(sizeof(*root), GFP_NOFS);
        if (!root)
-               return -ENOMEM;
+               return ERR_PTR(-ENOMEM);
 
        __setup_root(tree_root->nodesize, tree_root->leafsize,
                     tree_root->sectorsize, tree_root->stripesize,
@@ -951,12 +963,23 @@ int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans,
        root->root_key.objectid = BTRFS_TREE_LOG_OBJECTID;
        root->root_key.type = BTRFS_ROOT_ITEM_KEY;
        root->root_key.offset = BTRFS_TREE_LOG_OBJECTID;
+       /*
+        * log trees do not get reference counted because they go away
+        * before a real commit is actually done.  They do store pointers
+        * to file data extents, and those reference counts still get
+        * updated (along with back refs to the log tree).
+        */
        root->ref_cows = 0;
 
-       root->node = btrfs_alloc_free_block(trans, root, root->leafsize,
-                                           0, BTRFS_TREE_LOG_OBJECTID,
-                                           trans->transid, 0, 0, 0);
+       leaf = btrfs_alloc_free_block(trans, root, root->leafsize,
+                                     0, BTRFS_TREE_LOG_OBJECTID,
+                                     trans->transid, 0, 0, 0);
+       if (IS_ERR(leaf)) {
+               kfree(root);
+               return ERR_CAST(leaf);
+       }
 
+       root->node = leaf;
        btrfs_set_header_nritems(root->node, 0);
        btrfs_set_header_level(root->node, 0);
        btrfs_set_header_bytenr(root->node, root->node->start);
@@ -968,7 +991,48 @@ int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans,
                            BTRFS_FSID_SIZE);
        btrfs_mark_buffer_dirty(root->node);
        btrfs_tree_unlock(root->node);
-       fs_info->log_root_tree = root;
+       return root;
+}
+
+int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans,
+                            struct btrfs_fs_info *fs_info)
+{
+       struct btrfs_root *log_root;
+
+       log_root = alloc_log_tree(trans, fs_info);
+       if (IS_ERR(log_root))
+               return PTR_ERR(log_root);
+       WARN_ON(fs_info->log_root_tree);
+       fs_info->log_root_tree = log_root;
+       return 0;
+}
+
+int btrfs_add_log_tree(struct btrfs_trans_handle *trans,
+                      struct btrfs_root *root)
+{
+       struct btrfs_root *log_root;
+       struct btrfs_inode_item *inode_item;
+
+       log_root = alloc_log_tree(trans, root->fs_info);
+       if (IS_ERR(log_root))
+               return PTR_ERR(log_root);
+
+       log_root->last_trans = trans->transid;
+       log_root->root_key.offset = root->root_key.objectid;
+
+       inode_item = &log_root->root_item.inode;
+       inode_item->generation = cpu_to_le64(1);
+       inode_item->size = cpu_to_le64(3);
+       inode_item->nlink = cpu_to_le32(1);
+       inode_item->nbytes = cpu_to_le64(root->leafsize);
+       inode_item->mode = cpu_to_le32(S_IFDIR | 0755);
+
+       btrfs_set_root_bytenr(&log_root->root_item, log_root->node->start);
+       btrfs_set_root_generation(&log_root->root_item, trans->transid);
+
+       WARN_ON(root->log_root);
+       root->log_root = log_root;
+       root->log_transid = 0;
        return 0;
 }
 
@@ -1136,7 +1200,6 @@ static int btrfs_congested_fn(void *congested_data, int bdi_bits)
 {
        struct btrfs_fs_info *info = (struct btrfs_fs_info *)congested_data;
        int ret = 0;
-       struct list_head *cur;
        struct btrfs_device *device;
        struct backing_dev_info *bdi;
 #if 0
@@ -1144,8 +1207,7 @@ static int btrfs_congested_fn(void *congested_data, int bdi_bits)
            btrfs_congested_async(info, 0))
                return 1;
 #endif
-       list_for_each(cur, &info->fs_devices->devices) {
-               device = list_entry(cur, struct btrfs_device, dev_list);
+       list_for_each_entry(device, &info->fs_devices->devices, dev_list) {
                if (!device->bdev)
                        continue;
                bdi = blk_get_backing_dev_info(device->bdev);
@@ -1163,13 +1225,11 @@ static int btrfs_congested_fn(void *congested_data, int bdi_bits)
  */
 static void __unplug_io_fn(struct backing_dev_info *bdi, struct page *page)
 {
-       struct list_head *cur;
        struct btrfs_device *device;
        struct btrfs_fs_info *info;
 
        info = (struct btrfs_fs_info *)bdi->unplug_io_data;
-       list_for_each(cur, &info->fs_devices->devices) {
-               device = list_entry(cur, struct btrfs_device, dev_list);
+       list_for_each_entry(device, &info->fs_devices->devices, dev_list) {
                if (!device->bdev)
                        continue;
 
@@ -1447,7 +1507,6 @@ struct btrfs_root *open_ctree(struct super_block *sb,
        INIT_LIST_HEAD(&fs_info->dead_roots);
        INIT_LIST_HEAD(&fs_info->hashers);
        INIT_LIST_HEAD(&fs_info->delalloc_inodes);
-       spin_lock_init(&fs_info->hash_lock);
        spin_lock_init(&fs_info->delalloc_lock);
        spin_lock_init(&fs_info->new_trans_lock);
        spin_lock_init(&fs_info->ref_cache_lock);
@@ -1535,10 +1594,6 @@ struct btrfs_root *open_ctree(struct super_block *sb,
        init_waitqueue_head(&fs_info->transaction_throttle);
        init_waitqueue_head(&fs_info->transaction_wait);
        init_waitqueue_head(&fs_info->async_submit_wait);
-       init_waitqueue_head(&fs_info->tree_log_wait);
-       atomic_set(&fs_info->tree_log_commit, 0);
-       atomic_set(&fs_info->tree_log_writers, 0);
-       fs_info->tree_log_transid = 0;
 
        __setup_root(4096, 4096, 4096, 4096, tree_root,
                     fs_info, BTRFS_ROOT_TREE_OBJECTID);
@@ -1627,6 +1682,8 @@ struct btrfs_root *open_ctree(struct super_block *sb,
         * low idle thresh
         */
        fs_info->endio_workers.idle_thresh = 4;
+       fs_info->endio_meta_workers.idle_thresh = 4;
+
        fs_info->endio_write_workers.idle_thresh = 64;
        fs_info->endio_meta_write_workers.idle_thresh = 64;
 
@@ -1740,13 +1797,13 @@ struct btrfs_root *open_ctree(struct super_block *sb,
        fs_info->system_alloc_profile = fs_info->metadata_alloc_profile;
        fs_info->cleaner_kthread = kthread_run(cleaner_kthread, tree_root,
                                               "btrfs-cleaner");
-       if (!fs_info->cleaner_kthread)
+       if (IS_ERR(fs_info->cleaner_kthread))
                goto fail_csum_root;
 
        fs_info->transaction_kthread = kthread_run(transaction_kthread,
                                                   tree_root,
                                                   "btrfs-transaction");
-       if (!fs_info->transaction_kthread)
+       if (IS_ERR(fs_info->transaction_kthread))
                goto fail_cleaner;
 
        if (btrfs_super_log_root(disk_super) != 0) {
@@ -1828,13 +1885,14 @@ fail_sb_buffer:
 fail_iput:
        invalidate_inode_pages2(fs_info->btree_inode->i_mapping);
        iput(fs_info->btree_inode);
-fail:
+
        btrfs_close_devices(fs_info->fs_devices);
        btrfs_mapping_tree_free(&fs_info->mapping_tree);
+       bdi_destroy(&fs_info->bdi);
 
+fail:
        kfree(extent_root);
        kfree(tree_root);
-       bdi_destroy(&fs_info->bdi);
        kfree(fs_info);
        kfree(chunk_root);
        kfree(dev_root);
@@ -1995,7 +2053,6 @@ static int write_dev_supers(struct btrfs_device *device,
 
 int write_all_supers(struct btrfs_root *root, int max_mirrors)
 {
-       struct list_head *cur;
        struct list_head *head = &root->fs_info->fs_devices->devices;
        struct btrfs_device *dev;
        struct btrfs_super_block *sb;
@@ -2011,8 +2068,7 @@ int write_all_supers(struct btrfs_root *root, int max_mirrors)
 
        sb = &root->fs_info->super_for_commit;
        dev_item = &sb->dev_item;
-       list_for_each(cur, head) {
-               dev = list_entry(cur, struct btrfs_device, dev_list);
+       list_for_each_entry(dev, head, dev_list) {
                if (!dev->bdev) {
                        total_errors++;
                        continue;
@@ -2045,8 +2101,7 @@ int write_all_supers(struct btrfs_root *root, int max_mirrors)
        }
 
        total_errors = 0;
-       list_for_each(cur, head) {
-               dev = list_entry(cur, struct btrfs_device, dev_list);
+       list_for_each_entry(dev, head, dev_list) {
                if (!dev->bdev)
                        continue;
                if (!dev->in_fs_metadata || !dev->writeable)
@@ -2260,6 +2315,8 @@ void btrfs_mark_buffer_dirty(struct extent_buffer *buf)
        u64 transid = btrfs_header_generation(buf);
        struct inode *btree_inode = root->fs_info->btree_inode;
 
+       btrfs_set_lock_blocking(buf);
+
        WARN_ON(!btrfs_tree_locked(buf));
        if (transid != root->fs_info->generation) {
                printk(KERN_CRIT "btrfs transid mismatch buffer %llu, "
@@ -2302,14 +2359,13 @@ int btrfs_read_buffer(struct extent_buffer *buf, u64 parent_transid)
        int ret;
        ret = btree_read_extent_buffer_pages(root, buf, 0, parent_transid);
        if (ret == 0)
-               buf->flags |= EXTENT_UPTODATE;
+               set_bit(EXTENT_BUFFER_UPTODATE, &buf->bflags);
        return ret;
 }
 
 int btree_lock_page_hook(struct page *page)
 {
        struct inode *inode = page->mapping->host;
-       struct btrfs_root *root = BTRFS_I(inode)->root;
        struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
        struct extent_buffer *eb;
        unsigned long len;
@@ -2324,9 +2380,7 @@ int btree_lock_page_hook(struct page *page)
                goto out;
 
        btrfs_tree_lock(eb);
-       spin_lock(&root->fs_info->hash_lock);
        btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN);
-       spin_unlock(&root->fs_info->hash_lock);
        btrfs_tree_unlock(eb);
        free_extent_buffer(eb);
 out:
index c0ff404..494a56e 100644 (file)
@@ -98,5 +98,7 @@ int btrfs_free_log_root_tree(struct btrfs_trans_handle *trans,
                             struct btrfs_fs_info *fs_info);
 int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans,
                             struct btrfs_fs_info *fs_info);
+int btrfs_add_log_tree(struct btrfs_trans_handle *trans,
+                      struct btrfs_root *root);
 int btree_lock_page_hook(struct page *page);
 #endif
index 293da65..7527523 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/pagemap.h>
 #include <linux/writeback.h>
 #include <linux/blkdev.h>
-#include <linux/version.h>
+#include <linux/sort.h>
 #include "compat.h"
 #include "hash.h"
 #include "crc32c.h"
@@ -30,7 +30,6 @@
 #include "volumes.h"
 #include "locking.h"
 #include "ref-cache.h"
-#include "compat.h"
 
 #define PENDING_EXTENT_INSERT 0
 #define PENDING_EXTENT_DELETE 1
@@ -326,10 +325,8 @@ static struct btrfs_space_info *__find_space_info(struct btrfs_fs_info *info,
                                                  u64 flags)
 {
        struct list_head *head = &info->space_info;
-       struct list_head *cur;
        struct btrfs_space_info *found;
-       list_for_each(cur, head) {
-               found = list_entry(cur, struct btrfs_space_info, list);
+       list_for_each_entry(found, head, list) {
                if (found->flags == flags)
                        return found;
        }
@@ -1525,15 +1522,55 @@ out:
        return ret;
 }
 
-int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
-                 struct extent_buffer *orig_buf, struct extent_buffer *buf,
-                 u32 *nr_extents)
+/* when a block goes through cow, we update the reference counts of
+ * everything that block points to.  The internal pointers of the block
+ * can be in just about any order, and it is likely to have clusters of
+ * things that are close together and clusters of things that are not.
+ *
+ * To help reduce the seeks that come with updating all of these reference
+ * counts, sort them by byte number before actual updates are done.
+ *
+ * struct refsort is used to match byte number to slot in the btree block.
+ * we sort based on the byte number and then use the slot to actually
+ * find the item.
+ *
+ * struct refsort is smaller than strcut btrfs_item and smaller than
+ * struct btrfs_key_ptr.  Since we're currently limited to the page size
+ * for a btree block, there's no way for a kmalloc of refsorts for a
+ * single node to be bigger than a page.
+ */
+struct refsort {
+       u64 bytenr;
+       u32 slot;
+};
+
+/*
+ * for passing into sort()
+ */
+static int refsort_cmp(const void *a_void, const void *b_void)
+{
+       const struct refsort *a = a_void;
+       const struct refsort *b = b_void;
+
+       if (a->bytenr < b->bytenr)
+               return -1;
+       if (a->bytenr > b->bytenr)
+               return 1;
+       return 0;
+}
+
+
+noinline int btrfs_inc_ref(struct btrfs_trans_handle *trans,
+                          struct btrfs_root *root,
+                          struct extent_buffer *orig_buf,
+                          struct extent_buffer *buf, u32 *nr_extents)
 {
        u64 bytenr;
        u64 ref_root;
        u64 orig_root;
        u64 ref_generation;
        u64 orig_generation;
+       struct refsort *sorted;
        u32 nritems;
        u32 nr_file_extents = 0;
        struct btrfs_key key;
@@ -1542,6 +1579,8 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
        int level;
        int ret = 0;
        int faili = 0;
+       int refi = 0;
+       int slot;
        int (*process_func)(struct btrfs_trans_handle *, struct btrfs_root *,
                            u64, u64, u64, u64, u64, u64, u64, u64);
 
@@ -1553,6 +1592,9 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
        nritems = btrfs_header_nritems(buf);
        level = btrfs_header_level(buf);
 
+       sorted = kmalloc(sizeof(struct refsort) * nritems, GFP_NOFS);
+       BUG_ON(!sorted);
+
        if (root->ref_cows) {
                process_func = __btrfs_inc_extent_ref;
        } else {
@@ -1565,6 +1607,11 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
                process_func = __btrfs_update_extent_ref;
        }
 
+       /*
+        * we make two passes through the items.  In the first pass we
+        * only record the byte number and slot.  Then we sort based on
+        * byte number and do the actual work based on the sorted results
+        */
        for (i = 0; i < nritems; i++) {
                cond_resched();
                if (level == 0) {
@@ -1581,6 +1628,32 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
                                continue;
 
                        nr_file_extents++;
+                       sorted[refi].bytenr = bytenr;
+                       sorted[refi].slot = i;
+                       refi++;
+               } else {
+                       bytenr = btrfs_node_blockptr(buf, i);
+                       sorted[refi].bytenr = bytenr;
+                       sorted[refi].slot = i;
+                       refi++;
+               }
+       }
+       /*
+        * if refi == 0, we didn't actually put anything into the sorted
+        * array and we're done
+        */
+       if (refi == 0)
+               goto out;
+
+       sort(sorted, refi, sizeof(struct refsort), refsort_cmp, NULL);
+
+       for (i = 0; i < refi; i++) {
+               cond_resched();
+               slot = sorted[i].slot;
+               bytenr = sorted[i].bytenr;
+
+               if (level == 0) {
+                       btrfs_item_key_to_cpu(buf, &key, slot);
 
                        ret = process_func(trans, root, bytenr,
                                           orig_buf->start, buf->start,
@@ -1589,25 +1662,25 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
                                           key.objectid);
 
                        if (ret) {
-                               faili = i;
+                               faili = slot;
                                WARN_ON(1);
                                goto fail;
                        }
                } else {
-                       bytenr = btrfs_node_blockptr(buf, i);
                        ret = process_func(trans, root, bytenr,
                                           orig_buf->start, buf->start,
                                           orig_root, ref_root,
                                           orig_generation, ref_generation,
                                           level - 1);
                        if (ret) {
-                               faili = i;
+                               faili = slot;
                                WARN_ON(1);
                                goto fail;
                        }
                }
        }
 out:
+       kfree(sorted);
        if (nr_extents) {
                if (level == 0)
                        *nr_extents = nr_file_extents;
@@ -1616,6 +1689,7 @@ out:
        }
        return 0;
 fail:
+       kfree(sorted);
        WARN_ON(1);
        return ret;
 }
@@ -2159,7 +2233,8 @@ again:
                ret = find_first_extent_bit(&info->extent_ins, search, &start,
                                            &end, EXTENT_WRITEBACK);
                if (ret) {
-                       if (skipped && all && !num_inserts) {
+                       if (skipped && all && !num_inserts &&
+                           list_empty(&update_list)) {
                                skipped = 0;
                                search = 0;
                                continue;
@@ -2547,6 +2622,7 @@ again:
                if (ret) {
                        if (all && skipped && !nr) {
                                search = 0;
+                               skipped = 0;
                                continue;
                        }
                        mutex_unlock(&info->extent_ins_mutex);
@@ -2700,13 +2776,9 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
        /* if metadata always pin */
        if (owner_objectid < BTRFS_FIRST_FREE_OBJECTID) {
                if (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID) {
-                       struct btrfs_block_group_cache *cache;
-
-                       /* btrfs_free_reserved_extent */
-                       cache = btrfs_lookup_block_group(root->fs_info, bytenr);
-                       BUG_ON(!cache);
-                       btrfs_add_free_space(cache, bytenr, num_bytes);
-                       put_block_group(cache);
+                       mutex_lock(&root->fs_info->pinned_mutex);
+                       btrfs_update_pinned_extents(root, bytenr, num_bytes, 1);
+                       mutex_unlock(&root->fs_info->pinned_mutex);
                        update_reserved_extents(root, bytenr, num_bytes, 0);
                        return 0;
                }
@@ -3014,7 +3086,6 @@ loop_check:
 static void dump_space_info(struct btrfs_space_info *info, u64 bytes)
 {
        struct btrfs_block_group_cache *cache;
-       struct list_head *l;
 
        printk(KERN_INFO "space_info has %llu free, is %sfull\n",
               (unsigned long long)(info->total_bytes - info->bytes_used -
@@ -3022,8 +3093,7 @@ static void dump_space_info(struct btrfs_space_info *info, u64 bytes)
               (info->full) ? "" : "not ");
 
        down_read(&info->groups_sem);
-       list_for_each(l, &info->block_groups) {
-               cache = list_entry(l, struct btrfs_block_group_cache, list);
+       list_for_each_entry(cache, &info->block_groups, list) {
                spin_lock(&cache->lock);
                printk(KERN_INFO "block group %llu has %llu bytes, %llu used "
                       "%llu pinned %llu reserved\n",
@@ -3342,7 +3412,10 @@ struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans,
        btrfs_set_header_generation(buf, trans->transid);
        btrfs_tree_lock(buf);
        clean_tree_block(trans, root, buf);
+
+       btrfs_set_lock_blocking(buf);
        btrfs_set_buffer_uptodate(buf);
+
        if (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID) {
                set_extent_dirty(&root->dirty_log_pages, buf->start,
                         buf->start + buf->len - 1, GFP_NOFS);
@@ -3351,6 +3424,7 @@ struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans,
                         buf->start + buf->len - 1, GFP_NOFS);
        }
        trans->blocks_used++;
+       /* this returns a buffer locked for blocking */
        return buf;
 }
 
@@ -3388,36 +3462,73 @@ int btrfs_drop_leaf_ref(struct btrfs_trans_handle *trans,
 {
        u64 leaf_owner;
        u64 leaf_generation;
+       struct refsort *sorted;
        struct btrfs_key key;
        struct btrfs_file_extent_item *fi;
        int i;
        int nritems;
        int ret;
+       int refi = 0;
+       int slot;
 
        BUG_ON(!btrfs_is_leaf(leaf));
        nritems = btrfs_header_nritems(leaf);
        leaf_owner = btrfs_header_owner(leaf);
        leaf_generation = btrfs_header_generation(leaf);
 
+       sorted = kmalloc(sizeof(*sorted) * nritems, GFP_NOFS);
+       /* we do this loop twice.  The first time we build a list
+        * of the extents we have a reference on, then we sort the list
+        * by bytenr.  The second time around we actually do the
+        * extent freeing.
+        */
        for (i = 0; i < nritems; i++) {
                u64 disk_bytenr;
                cond_resched();
 
                btrfs_item_key_to_cpu(leaf, &key, i);
+
+               /* only extents have references, skip everything else */
                if (btrfs_key_type(&key) != BTRFS_EXTENT_DATA_KEY)
                        continue;
+
                fi = btrfs_item_ptr(leaf, i, struct btrfs_file_extent_item);
+
+               /* inline extents live in the btree, they don't have refs */
                if (btrfs_file_extent_type(leaf, fi) ==
                    BTRFS_FILE_EXTENT_INLINE)
                        continue;
-               /*
-                * FIXME make sure to insert a trans record that
-                * repeats the snapshot del on crash
-                */
+
                disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi);
+
+               /* holes don't have refs */
                if (disk_bytenr == 0)
                        continue;
 
+               sorted[refi].bytenr = disk_bytenr;
+               sorted[refi].slot = i;
+               refi++;
+       }
+
+       if (refi == 0)
+               goto out;
+
+       sort(sorted, refi, sizeof(struct refsort), refsort_cmp, NULL);
+
+       for (i = 0; i < refi; i++) {
+               u64 disk_bytenr;
+
+               disk_bytenr = sorted[i].bytenr;
+               slot = sorted[i].slot;
+
+               cond_resched();
+
+               btrfs_item_key_to_cpu(leaf, &key, slot);
+               if (btrfs_key_type(&key) != BTRFS_EXTENT_DATA_KEY)
+                       continue;
+
+               fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item);
+
                ret = __btrfs_free_extent(trans, root, disk_bytenr,
                                btrfs_file_extent_disk_num_bytes(leaf, fi),
                                leaf->start, leaf_owner, leaf_generation,
@@ -3428,6 +3539,8 @@ int btrfs_drop_leaf_ref(struct btrfs_trans_handle *trans,
                wake_up(&root->fs_info->transaction_throttle);
                cond_resched();
        }
+out:
+       kfree(sorted);
        return 0;
 }
 
@@ -3437,9 +3550,25 @@ static noinline int cache_drop_leaf_ref(struct btrfs_trans_handle *trans,
 {
        int i;
        int ret;
-       struct btrfs_extent_info *info = ref->extents;
+       struct btrfs_extent_info *info;
+       struct refsort *sorted;
+
+       if (ref->nritems == 0)
+               return 0;
 
+       sorted = kmalloc(sizeof(*sorted) * ref->nritems, GFP_NOFS);
        for (i = 0; i < ref->nritems; i++) {
+               sorted[i].bytenr = ref->extents[i].bytenr;
+               sorted[i].slot = i;
+       }
+       sort(sorted, ref->nritems, sizeof(struct refsort), refsort_cmp, NULL);
+
+       /*
+        * the items in the ref were sorted when the ref was inserted
+        * into the ref cache, so this is already in order
+        */
+       for (i = 0; i < ref->nritems; i++) {
+               info = ref->extents + sorted[i].slot;
                ret = __btrfs_free_extent(trans, root, info->bytenr,
                                          info->num_bytes, ref->bytenr,
                                          ref->owner, ref->generation,
@@ -3453,6 +3582,7 @@ static noinline int cache_drop_leaf_ref(struct btrfs_trans_handle *trans,
                info++;
        }
 
+       kfree(sorted);
        return 0;
 }
 
@@ -3496,6 +3626,152 @@ static int drop_snap_lookup_refcount(struct btrfs_root *root, u64 start,
        return ret;
 }
 
+/*
+ * this is used while deleting old snapshots, and it drops the refs
+ * on a whole subtree starting from a level 1 node.
+ *
+ * The idea is to sort all the leaf pointers, and then drop the
+ * ref on all the leaves in order.  Most of the time the leaves
+ * will have ref cache entries, so no leaf IOs will be required to
+ * find the extents they have references on.
+ *
+ * For each leaf, any references it has are also dropped in order
+ *
+ * This ends up dropping the references in something close to optimal
+ * order for reading and modifying the extent allocation tree.
+ */
+static noinline int drop_level_one_refs(struct btrfs_trans_handle *trans,
+                                       struct btrfs_root *root,
+                                       struct btrfs_path *path)
+{
+       u64 bytenr;
+       u64 root_owner;
+       u64 root_gen;
+       struct extent_buffer *eb = path->nodes[1];
+       struct extent_buffer *leaf;
+       struct btrfs_leaf_ref *ref;
+       struct refsort *sorted = NULL;
+       int nritems = btrfs_header_nritems(eb);
+       int ret;
+       int i;
+       int refi = 0;
+       int slot = path->slots[1];
+       u32 blocksize = btrfs_level_size(root, 0);
+       u32 refs;
+
+       if (nritems == 0)
+               goto out;
+
+       root_owner = btrfs_header_owner(eb);
+       root_gen = btrfs_header_generation(eb);
+       sorted = kmalloc(sizeof(*sorted) * nritems, GFP_NOFS);
+
+       /*
+        * step one, sort all the leaf pointers so we don't scribble
+        * randomly into the extent allocation tree
+        */
+       for (i = slot; i < nritems; i++) {
+               sorted[refi].bytenr = btrfs_node_blockptr(eb, i);
+               sorted[refi].slot = i;
+               refi++;
+       }
+
+       /*
+        * nritems won't be zero, but if we're picking up drop_snapshot
+        * after a crash, slot might be > 0, so double check things
+        * just in case.
+        */
+       if (refi == 0)
+               goto out;
+
+       sort(sorted, refi, sizeof(struct refsort), refsort_cmp, NULL);
+
+       /*
+        * the first loop frees everything the leaves point to
+        */
+       for (i = 0; i < refi; i++) {
+               u64 ptr_gen;
+
+               bytenr = sorted[i].bytenr;
+
+               /*
+                * check the reference count on this leaf.  If it is > 1
+                * we just decrement it below and don't update any
+                * of the refs the leaf points to.
+                */
+               ret = drop_snap_lookup_refcount(root, bytenr, blocksize, &refs);
+               BUG_ON(ret);
+               if (refs != 1)
+                       continue;
+
+               ptr_gen = btrfs_node_ptr_generation(eb, sorted[i].slot);
+
+               /*
+                * the leaf only had one reference, which means the
+                * only thing pointing to this leaf is the snapshot
+                * we're deleting.  It isn't possible for the reference
+                * count to increase again later
+                *
+                * The reference cache is checked for the leaf,
+                * and if found we'll be able to drop any refs held by
+                * the leaf without needing to read it in.
+                */
+               ref = btrfs_lookup_leaf_ref(root, bytenr);
+               if (ref && ref->generation != ptr_gen) {
+                       btrfs_free_leaf_ref(root, ref);
+                       ref = NULL;
+               }
+               if (ref) {
+                       ret = cache_drop_leaf_ref(trans, root, ref);
+                       BUG_ON(ret);
+                       btrfs_remove_leaf_ref(root, ref);
+                       btrfs_free_leaf_ref(root, ref);
+               } else {
+                       /*
+                        * the leaf wasn't in the reference cache, so
+                        * we have to read it.
+                        */
+                       leaf = read_tree_block(root, bytenr, blocksize,
+                                              ptr_gen);
+                       ret = btrfs_drop_leaf_ref(trans, root, leaf);
+                       BUG_ON(ret);
+                       free_extent_buffer(leaf);
+               }
+               atomic_inc(&root->fs_info->throttle_gen);
+               wake_up(&root->fs_info->transaction_throttle);
+               cond_resched();
+       }
+
+       /*
+        * run through the loop again to free the refs on the leaves.
+        * This is faster than doing it in the loop above because
+        * the leaves are likely to be clustered together.  We end up
+        * working in nice chunks on the extent allocation tree.
+        */
+       for (i = 0; i < refi; i++) {
+               bytenr = sorted[i].bytenr;
+               ret = __btrfs_free_extent(trans, root, bytenr,
+                                       blocksize, eb->start,
+                                       root_owner, root_gen, 0, 1);
+               BUG_ON(ret);
+
+               atomic_inc(&root->fs_info->throttle_gen);
+               wake_up(&root->fs_info->transaction_throttle);
+               cond_resched();
+       }
+out:
+       kfree(sorted);
+
+       /*
+        * update the path to show we've processed the entire level 1
+        * node.  This will get saved into the root's drop_snapshot_progress
+        * field so these drops are not repeated again if this transaction
+        * commits.
+        */
+       path->slots[1] = nritems;
+       return 0;
+}
+
 /*
  * helper function for drop_snapshot, this walks down the tree dropping ref
  * counts as it goes.
@@ -3511,7 +3787,6 @@ static noinline int walk_down_tree(struct btrfs_trans_handle *trans,
        struct extent_buffer *next;
        struct extent_buffer *cur;
        struct extent_buffer *parent;
-       struct btrfs_leaf_ref *ref;
        u32 blocksize;
        int ret;
        u32 refs;
@@ -3538,17 +3813,46 @@ static noinline int walk_down_tree(struct btrfs_trans_handle *trans,
                if (path->slots[*level] >=
                    btrfs_header_nritems(cur))
                        break;
+
+               /* the new code goes down to level 1 and does all the
+                * leaves pointed to that node in bulk.  So, this check
+                * for level 0 will always be false.
+                *
+                * But, the disk format allows the drop_snapshot_progress
+                * field in the root to leave things in a state where
+                * a leaf will need cleaning up here.  If someone crashes
+                * with the old code and then boots with the new code,
+                * we might find a leaf here.
+                */
                if (*level == 0) {
                        ret = btrfs_drop_leaf_ref(trans, root, cur);
                        BUG_ON(ret);
                        break;
                }
+
+               /*
+                * once we get to level one, process the whole node
+                * at once, including everything below it.
+                */
+               if (*level == 1) {
+                       ret = drop_level_one_refs(trans, root, path);
+                       BUG_ON(ret);
+                       break;
+               }
+
                bytenr = btrfs_node_blockptr(cur, path->slots[*level]);
                ptr_gen = btrfs_node_ptr_generation(cur, path->slots[*level]);
                blocksize = btrfs_level_size(root, *level - 1);
 
                ret = drop_snap_lookup_refcount(root, bytenr, blocksize, &refs);
                BUG_ON(ret);
+
+               /*
+                * if there is more than one reference, we don't need
+                * to read that node to drop any references it has.  We
+                * just drop the ref we hold on that node and move on to the
+                * next slot in this level.
+                */
                if (refs != 1) {
                        parent = path->nodes[*level];
                        root_owner = btrfs_header_owner(parent);
@@ -3567,46 +3871,12 @@ static noinline int walk_down_tree(struct btrfs_trans_handle *trans,
 
                        continue;
                }
+
                /*
-                * at this point, we have a single ref, and since the
-                * only place referencing this extent is a dead root
-                * the reference count should never go higher.
-                * So, we don't need to check it again
+                * we need to keep freeing things in the next level down.
+                * read the block and loop around to process it
                 */
-               if (*level == 1) {
-                       ref = btrfs_lookup_leaf_ref(root, bytenr);
-                       if (ref && ref->generation != ptr_gen) {
-                               btrfs_free_leaf_ref(root, ref);
-                               ref = NULL;
-                       }
-                       if (ref) {
-                               ret = cache_drop_leaf_ref(trans, root, ref);
-                               BUG_ON(ret);
-                               btrfs_remove_leaf_ref(root, ref);
-                               btrfs_free_leaf_ref(root, ref);
-                               *level = 0;
-                               break;
-                       }
-               }
-               next = btrfs_find_tree_block(root, bytenr, blocksize);
-               if (!next || !btrfs_buffer_uptodate(next, ptr_gen)) {
-                       free_extent_buffer(next);
-
-                       next = read_tree_block(root, bytenr, blocksize,
-                                              ptr_gen);
-                       cond_resched();
-#if 0
-                       /*
-                        * this is a debugging check and can go away
-                        * the ref should never go all the way down to 1
-                        * at this point
-                        */
-                       ret = lookup_extent_ref(NULL, root, bytenr, blocksize,
-                                               &refs);
-                       BUG_ON(ret);
-                       WARN_ON(refs != 1);
-#endif
-               }
+               next = read_tree_block(root, bytenr, blocksize, ptr_gen);
                WARN_ON(*level <= 0);
                if (path->nodes[*level-1])
                        free_extent_buffer(path->nodes[*level-1]);
@@ -3631,11 +3901,16 @@ out:
        root_owner = btrfs_header_owner(parent);
        root_gen = btrfs_header_generation(parent);
 
+       /*
+        * cleanup and free the reference on the last node
+        * we processed
+        */
        ret = __btrfs_free_extent(trans, root, bytenr, blocksize,
                                  parent->start, root_owner, root_gen,
                                  *level, 1);
        free_extent_buffer(path->nodes[*level]);
        path->nodes[*level] = NULL;
+
        *level += 1;
        BUG_ON(ret);
 
@@ -3687,6 +3962,7 @@ static noinline int walk_down_subtree(struct btrfs_trans_handle *trans,
 
                next = read_tree_block(root, bytenr, blocksize, ptr_gen);
                btrfs_tree_lock(next);
+               btrfs_set_lock_blocking(next);
 
                ret = btrfs_lookup_extent_ref(trans, root, bytenr, blocksize,
                                              &refs);
@@ -3754,6 +4030,13 @@ static noinline int walk_up_tree(struct btrfs_trans_handle *trans,
                if (slot < btrfs_header_nritems(path->nodes[i]) - 1) {
                        struct extent_buffer *node;
                        struct btrfs_disk_key disk_key;
+
+                       /*
+                        * there is more work to do in this level.
+                        * Update the drop_progress marker to reflect
+                        * the work we've done so far, and then bump
+                        * the slot number
+                        */
                        node = path->nodes[i];
                        path->slots[i]++;
                        *level = i;
@@ -3765,6 +4048,11 @@ static noinline int walk_up_tree(struct btrfs_trans_handle *trans,
                        return 0;
                } else {
                        struct extent_buffer *parent;
+
+                       /*
+                        * this whole node is done, free our reference
+                        * on it and go up one level
+                        */
                        if (path->nodes[*level] == root->node)
                                parent = path->nodes[*level];
                        else
@@ -4444,7 +4732,7 @@ static noinline int replace_one_extent(struct btrfs_trans_handle *trans,
        u64 lock_end = 0;
        u64 num_bytes;
        u64 ext_offset;
-       u64 first_pos;
+       u64 search_end = (u64)-1;
        u32 nritems;
        int nr_scaned = 0;
        int extent_locked = 0;
@@ -4452,7 +4740,6 @@ static noinline int replace_one_extent(struct btrfs_trans_handle *trans,
        int ret;
 
        memcpy(&key, leaf_key, sizeof(key));
-       first_pos = INT_LIMIT(loff_t) - extent_key->offset;
        if (ref_path->owner_objectid != BTRFS_MULTIPLE_OBJECTIDS) {
                if (key.objectid < ref_path->owner_objectid ||
                    (key.objectid == ref_path->owner_objectid &&
@@ -4501,7 +4788,7 @@ next:
                        if ((key.objectid > ref_path->owner_objectid) ||
                            (key.objectid == ref_path->owner_objectid &&
                             key.type > BTRFS_EXTENT_DATA_KEY) ||
-                           (key.offset >= first_pos + extent_key->offset))
+                           key.offset >= search_end)
                                break;
                }
 
@@ -4534,8 +4821,10 @@ next:
                num_bytes = btrfs_file_extent_num_bytes(leaf, fi);
                ext_offset = btrfs_file_extent_offset(leaf, fi);
 
-               if (first_pos > key.offset - ext_offset)
-                       first_pos = key.offset - ext_offset;
+               if (search_end == (u64)-1) {
+                       search_end = key.offset - ext_offset +
+                               btrfs_file_extent_ram_bytes(leaf, fi);
+               }
 
                if (!extent_locked) {
                        lock_start = key.offset;
@@ -4724,7 +5013,7 @@ next:
                }
 skip:
                if (ref_path->owner_objectid != BTRFS_MULTIPLE_OBJECTIDS &&
-                   key.offset >= first_pos + extent_key->offset)
+                   key.offset >= search_end)
                        break;
 
                cond_resched();
@@ -4778,6 +5067,7 @@ int btrfs_reloc_tree_cache_ref(struct btrfs_trans_handle *trans,
                ref->bytenr = buf->start;
                ref->owner = btrfs_header_owner(buf);
                ref->generation = btrfs_header_generation(buf);
+
                ret = btrfs_add_leaf_ref(root, ref, 0);
                WARN_ON(ret);
                btrfs_free_leaf_ref(root, ref);
@@ -5957,9 +6247,11 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
        path = btrfs_alloc_path();
        BUG_ON(!path);
 
-       btrfs_remove_free_space_cache(block_group);
+       spin_lock(&root->fs_info->block_group_cache_lock);
        rb_erase(&block_group->cache_node,
                 &root->fs_info->block_group_cache_tree);
+       spin_unlock(&root->fs_info->block_group_cache_lock);
+       btrfs_remove_free_space_cache(block_group);
        down_write(&block_group->space_info->groups_sem);
        list_del(&block_group->list);
        up_write(&block_group->space_info->groups_sem);
index e086d40..37d43b5 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/spinlock.h>
 #include <linux/blkdev.h>
 #include <linux/swap.h>
-#include <linux/version.h>
 #include <linux/writeback.h>
 #include <linux/pagevec.h>
 #include "extent_io.h"
@@ -31,7 +30,7 @@ static LIST_HEAD(buffers);
 static LIST_HEAD(states);
 
 #define LEAK_DEBUG 0
-#ifdef LEAK_DEBUG
+#if LEAK_DEBUG
 static DEFINE_SPINLOCK(leak_lock);
 #endif
 
@@ -120,7 +119,7 @@ void extent_io_tree_init(struct extent_io_tree *tree,
 static struct extent_state *alloc_extent_state(gfp_t mask)
 {
        struct extent_state *state;
-#ifdef LEAK_DEBUG
+#if LEAK_DEBUG
        unsigned long flags;
 #endif
 
@@ -130,7 +129,7 @@ static struct extent_state *alloc_extent_state(gfp_t mask)
        state->state = 0;
        state->private = 0;
        state->tree = NULL;
-#ifdef LEAK_DEBUG
+#if LEAK_DEBUG
        spin_lock_irqsave(&leak_lock, flags);
        list_add(&state->leak_list, &states);
        spin_unlock_irqrestore(&leak_lock, flags);
@@ -145,11 +144,11 @@ static void free_extent_state(struct extent_state *state)
        if (!state)
                return;
        if (atomic_dec_and_test(&state->refs)) {
-#ifdef LEAK_DEBUG
+#if LEAK_DEBUG
                unsigned long flags;
 #endif
                WARN_ON(state->tree);
-#ifdef LEAK_DEBUG
+#if LEAK_DEBUG
                spin_lock_irqsave(&leak_lock, flags);
                list_del(&state->leak_list);
                spin_unlock_irqrestore(&leak_lock, flags);
@@ -2378,11 +2377,6 @@ static int extent_write_cache_pages(struct extent_io_tree *tree,
        int scanned = 0;
        int range_whole = 0;
 
-       if (wbc->nonblocking && bdi_write_congested(bdi)) {
-               wbc->encountered_congestion = 1;
-               return 0;
-       }
-
        pagevec_init(&pvec, 0);
        if (wbc->range_cyclic) {
                index = mapping->writeback_index; /* Start from prev offset */
@@ -2855,6 +2849,98 @@ out:
        return sector;
 }
 
+int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+               __u64 start, __u64 len, get_extent_t *get_extent)
+{
+       int ret;
+       u64 off = start;
+       u64 max = start + len;
+       u32 flags = 0;
+       u64 disko = 0;
+       struct extent_map *em = NULL;
+       int end = 0;
+       u64 em_start = 0, em_len = 0;
+       unsigned long emflags;
+       ret = 0;
+
+       if (len == 0)
+               return -EINVAL;
+
+       lock_extent(&BTRFS_I(inode)->io_tree, start, start + len,
+               GFP_NOFS);
+       em = get_extent(inode, NULL, 0, off, max - off, 0);
+       if (!em)
+               goto out;
+       if (IS_ERR(em)) {
+               ret = PTR_ERR(em);
+               goto out;
+       }
+       while (!end) {
+               off = em->start + em->len;
+               if (off >= max)
+                       end = 1;
+
+               em_start = em->start;
+               em_len = em->len;
+
+               disko = 0;
+               flags = 0;
+
+               switch (em->block_start) {
+               case EXTENT_MAP_LAST_BYTE:
+                       end = 1;
+                       flags |= FIEMAP_EXTENT_LAST;
+                       break;
+               case EXTENT_MAP_HOLE:
+                       flags |= FIEMAP_EXTENT_UNWRITTEN;
+                       break;
+               case EXTENT_MAP_INLINE:
+                       flags |= (FIEMAP_EXTENT_DATA_INLINE |
+                                 FIEMAP_EXTENT_NOT_ALIGNED);
+                       break;
+               case EXTENT_MAP_DELALLOC:
+                       flags |= (FIEMAP_EXTENT_DELALLOC |
+                                 FIEMAP_EXTENT_UNKNOWN);
+                       break;
+               default:
+                       disko = em->block_start;
+                       break;
+               }
+               if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags))
+                       flags |= FIEMAP_EXTENT_ENCODED;
+
+               emflags = em->flags;
+               free_extent_map(em);
+               em = NULL;
+
+               if (!end) {
+                       em = get_extent(inode, NULL, 0, off, max - off, 0);
+                       if (!em)
+                               goto out;
+                       if (IS_ERR(em)) {
+                               ret = PTR_ERR(em);
+                               goto out;
+                       }
+                       emflags = em->flags;
+               }
+               if (test_bit(EXTENT_FLAG_VACANCY, &emflags)) {
+                       flags |= FIEMAP_EXTENT_LAST;
+                       end = 1;
+               }
+
+               ret = fiemap_fill_next_extent(fieinfo, em_start, disko,
+                                       em_len, flags);
+               if (ret)
+                       goto out_free;
+       }
+out_free:
+       free_extent_map(em);
+out:
+       unlock_extent(&BTRFS_I(inode)->io_tree, start, start + len,
+                       GFP_NOFS);
+       return ret;
+}
+
 static inline struct page *extent_buffer_page(struct extent_buffer *eb,
                                              unsigned long i)
 {
@@ -2892,15 +2978,17 @@ static struct extent_buffer *__alloc_extent_buffer(struct extent_io_tree *tree,
                                                   gfp_t mask)
 {
        struct extent_buffer *eb = NULL;
-#ifdef LEAK_DEBUG
+#if LEAK_DEBUG
        unsigned long flags;
 #endif
 
        eb = kmem_cache_zalloc(extent_buffer_cache, mask);
        eb->start = start;
        eb->len = len;
-       mutex_init(&eb->mutex);
-#ifdef LEAK_DEBUG
+       spin_lock_init(&eb->lock);
+       init_waitqueue_head(&eb->lock_wq);
+
+#if LEAK_DEBUG
        spin_lock_irqsave(&leak_lock, flags);
        list_add(&eb->leak_list, &buffers);
        spin_unlock_irqrestore(&leak_lock, flags);
@@ -2912,7 +3000,7 @@ static struct extent_buffer *__alloc_extent_buffer(struct extent_io_tree *tree,
 
 static void __free_extent_buffer(struct extent_buffer *eb)
 {
-#ifdef LEAK_DEBUG
+#if LEAK_DEBUG
        unsigned long flags;
        spin_lock_irqsave(&leak_lock, flags);
        list_del(&eb->leak_list);
@@ -2980,8 +3068,7 @@ struct extent_buffer *alloc_extent_buffer(struct extent_io_tree *tree,
                unlock_page(p);
        }
        if (uptodate)
-               eb->flags |= EXTENT_UPTODATE;
-       eb->flags |= EXTENT_BUFFER_FILLED;
+               set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags);
 
        spin_lock(&tree->buffer_lock);
        exists = buffer_tree_insert(tree, start, &eb->rb_node);
@@ -3135,7 +3222,7 @@ int clear_extent_buffer_uptodate(struct extent_io_tree *tree,
        unsigned long num_pages;
 
        num_pages = num_extent_pages(eb->start, eb->len);
-       eb->flags &= ~EXTENT_UPTODATE;
+       clear_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags);
 
        clear_extent_uptodate(tree, eb->start, eb->start + eb->len - 1,
                              GFP_NOFS);
@@ -3206,7 +3293,7 @@ int extent_buffer_uptodate(struct extent_io_tree *tree,
        struct page *page;
        int pg_uptodate = 1;
 
-       if (eb->flags & EXTENT_UPTODATE)
+       if (test_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags))
                return 1;
 
        ret = test_range_bit(tree, eb->start, eb->start + eb->len - 1,
@@ -3242,7 +3329,7 @@ int read_extent_buffer_pages(struct extent_io_tree *tree,
        struct bio *bio = NULL;
        unsigned long bio_flags = 0;
 
-       if (eb->flags & EXTENT_UPTODATE)
+       if (test_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags))
                return 0;
 
        if (test_range_bit(tree, eb->start, eb->start + eb->len - 1,
@@ -3273,7 +3360,7 @@ int read_extent_buffer_pages(struct extent_io_tree *tree,
        }
        if (all_uptodate) {
                if (start_i == 0)
-                       eb->flags |= EXTENT_UPTODATE;
+                       set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags);
                goto unlock_exit;
        }
 
@@ -3309,7 +3396,7 @@ int read_extent_buffer_pages(struct extent_io_tree *tree,
        }
 
        if (!ret)
-               eb->flags |= EXTENT_UPTODATE;
+               set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags);
        return ret;
 
 unlock_exit:
@@ -3406,7 +3493,6 @@ int map_extent_buffer(struct extent_buffer *eb, unsigned long start,
                unmap_extent_buffer(eb, eb->map_token, km);
                eb->map_token = NULL;
                save = 1;
-               WARN_ON(!mutex_is_locked(&eb->mutex));
        }
        err = map_private_extent_buffer(eb, start, min_len, token, map,
                                       map_start, map_len, km);
index c5b483a..1f9df88 100644 (file)
 /* flags for bio submission */
 #define EXTENT_BIO_COMPRESSED 1
 
+/* these are bit numbers for test/set bit */
+#define EXTENT_BUFFER_UPTODATE 0
+#define EXTENT_BUFFER_BLOCKING 1
+
 /*
  * page->private values.  Every page that is controlled by the extent
  * map has page->private set to one.
@@ -95,11 +99,19 @@ struct extent_buffer {
        unsigned long map_start;
        unsigned long map_len;
        struct page *first_page;
+       unsigned long bflags;
        atomic_t refs;
-       int flags;
        struct list_head leak_list;
        struct rb_node rb_node;
-       struct mutex mutex;
+
+       /* the spinlock is used to protect most operations */
+       spinlock_t lock;
+
+       /*
+        * when we keep the lock held while blocking, waiters go onto
+        * the wq
+        */
+       wait_queue_head_t lock_wq;
 };
 
 struct extent_map_tree;
@@ -193,6 +205,8 @@ int extent_commit_write(struct extent_io_tree *tree,
                        unsigned from, unsigned to);
 sector_t extent_bmap(struct address_space *mapping, sector_t iblock,
                get_extent_t *get_extent);
+int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+               __u64 start, __u64 len, get_extent_t *get_extent);
 int set_range_dirty(struct extent_io_tree *tree, u64 start, u64 end);
 int set_state_private(struct extent_io_tree *tree, u64 start, u64 private);
 int get_state_private(struct extent_io_tree *tree, u64 start, u64 *private);
index 4a83e33..50da69d 100644 (file)
@@ -3,7 +3,6 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
-#include <linux/version.h>
 #include <linux/hardirq.h>
 #include "extent_map.h"
 
index 9026833..3e8023e 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/writeback.h>
 #include <linux/statfs.h>
 #include <linux/compat.h>
-#include <linux/version.h>
 #include "ctree.h"
 #include "disk-io.h"
 #include "transaction.h"
@@ -1215,10 +1214,10 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync)
        }
        mutex_unlock(&root->fs_info->trans_mutex);
 
-       root->fs_info->tree_log_batch++;
+       root->log_batch++;
        filemap_fdatawrite(inode->i_mapping);
        btrfs_wait_ordered_range(inode, 0, (u64)-1);
-       root->fs_info->tree_log_batch++;
+       root->log_batch++;
 
        /*
         * ok we haven't committed the transaction yet, lets do a commit
index 8adfe05..8f07062 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/statfs.h>
 #include <linux/compat.h>
 #include <linux/bit_spinlock.h>
-#include <linux/version.h>
 #include <linux/xattr.h>
 #include <linux/posix_acl.h>
 #include <linux/falloc.h>
@@ -51,6 +50,7 @@
 #include "tree-log.h"
 #include "ref-cache.h"
 #include "compression.h"
+#include "locking.h"
 
 struct btrfs_iget_args {
        u64 ino;
@@ -91,6 +91,16 @@ static noinline int cow_file_range(struct inode *inode,
                                   u64 start, u64 end, int *page_started,
                                   unsigned long *nr_written, int unlock);
 
+static int btrfs_init_inode_security(struct inode *inode,  struct inode *dir)
+{
+       int err;
+
+       err = btrfs_init_acl(inode, dir);
+       if (!err)
+               err = btrfs_xattr_security_init(inode, dir);
+       return err;
+}
+
 /*
  * a very lame attempt at stopping writes when the FS is 85% full.  There
  * are countless ways this is incorrect, but it is better than nothing.
@@ -350,6 +360,19 @@ again:
        nr_pages = (end >> PAGE_CACHE_SHIFT) - (start >> PAGE_CACHE_SHIFT) + 1;
        nr_pages = min(nr_pages, (128 * 1024UL) / PAGE_CACHE_SIZE);
 
+       /*
+        * we don't want to send crud past the end of i_size through
+        * compression, that's just a waste of CPU time.  So, if the
+        * end of the file is before the start of our current
+        * requested range of bytes, we bail out to the uncompressed
+        * cleanup code that can deal with all of this.
+        *
+        * It isn't really the fastest way to fix things, but this is a
+        * very uncommon corner.
+        */
+       if (actual_end <= start)
+               goto cleanup_and_bail_uncompressed;
+
        total_compressed = actual_end - start;
 
        /* we want to make sure that amount of ram required to uncompress
@@ -494,6 +517,7 @@ again:
                        goto again;
                }
        } else {
+cleanup_and_bail_uncompressed:
                /*
                 * No compression, but we still need to write the pages in
                 * the file we've been given so far.  redirty the locked
@@ -1324,12 +1348,11 @@ static noinline int add_pending_csums(struct btrfs_trans_handle *trans,
                             struct inode *inode, u64 file_offset,
                             struct list_head *list)
 {
-       struct list_head *cur;
        struct btrfs_ordered_sum *sum;
 
        btrfs_set_trans_block_group(trans, inode);
-       list_for_each(cur, list) {
-               sum = list_entry(cur, struct btrfs_ordered_sum, list);
+
+       list_for_each_entry(sum, list, list) {
                btrfs_csum_file_blocks(trans,
                       BTRFS_I(inode)->root->fs_info->csum_root, sum);
        }
@@ -2013,6 +2036,7 @@ void btrfs_read_locked_inode(struct inode *inode)
        BTRFS_I(inode)->flags = btrfs_inode_flags(leaf, inode_item);
 
        alloc_group_block = btrfs_inode_block_group(leaf, inode_item);
+
        BTRFS_I(inode)->block_group = btrfs_find_block_group(root, 0,
                                                alloc_group_block, 0);
        btrfs_free_path(path);
@@ -2039,6 +2063,7 @@ void btrfs_read_locked_inode(struct inode *inode)
                inode->i_mapping->backing_dev_info = &root->fs_info->bdi;
                break;
        default:
+               inode->i_op = &btrfs_special_inode_operations;
                init_special_inode(inode, inode->i_mode, rdev);
                break;
        }
@@ -2108,6 +2133,7 @@ noinline int btrfs_update_inode(struct btrfs_trans_handle *trans,
                goto failed;
        }
 
+       btrfs_unlock_up_safe(path, 1);
        leaf = path->nodes[0];
        inode_item = btrfs_item_ptr(leaf, path->slots[0],
                                  struct btrfs_inode_item);
@@ -2429,6 +2455,8 @@ next_node:
                        ref->generation = leaf_gen;
                        ref->nritems = 0;
 
+                       btrfs_sort_leaf_ref(ref);
+
                        ret = btrfs_add_leaf_ref(root, ref, 0);
                        WARN_ON(ret);
                        btrfs_free_leaf_ref(root, ref);
@@ -2476,7 +2504,7 @@ noinline int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
        struct btrfs_path *path;
        struct btrfs_key key;
        struct btrfs_key found_key;
-       u32 found_type;
+       u32 found_type = (u8)-1;
        struct extent_buffer *leaf;
        struct btrfs_file_extent_item *fi;
        u64 extent_start = 0;
@@ -2663,6 +2691,8 @@ next:
                        if (pending_del_nr)
                                goto del_pending;
                        btrfs_release_path(root, path);
+                       if (found_type == BTRFS_INODE_ITEM_KEY)
+                               break;
                        goto search_again;
                }
 
@@ -2679,6 +2709,8 @@ del_pending:
                        BUG_ON(ret);
                        pending_del_nr = 0;
                        btrfs_release_path(root, path);
+                       if (found_type == BTRFS_INODE_ITEM_KEY)
+                               break;
                        goto search_again;
                }
        }
@@ -3265,7 +3297,7 @@ skip:
 
        /* Reached end of directory/root. Bump pos past the last item. */
        if (key_type == BTRFS_DIR_INDEX_KEY)
-               filp->f_pos = INT_LIMIT(typeof(filp->f_pos));
+               filp->f_pos = INT_LIMIT(off_t);
        else
                filp->f_pos++;
 nopos:
@@ -3458,7 +3490,14 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
                root->highest_inode = objectid;
 
        inode->i_uid = current_fsuid();
-       inode->i_gid = current_fsgid();
+
+       if (dir && (dir->i_mode & S_ISGID)) {
+               inode->i_gid = dir->i_gid;
+               if (S_ISDIR(mode))
+                       mode |= S_ISGID;
+       } else
+               inode->i_gid = current_fsgid();
+
        inode->i_mode = mode;
        inode->i_ino = objectid;
        inode_set_bytes(inode, 0);
@@ -3586,7 +3625,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
        if (IS_ERR(inode))
                goto out_unlock;
 
-       err = btrfs_init_acl(inode, dir);
+       err = btrfs_init_inode_security(inode, dir);
        if (err) {
                drop_inode = 1;
                goto out_unlock;
@@ -3649,7 +3688,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
        if (IS_ERR(inode))
                goto out_unlock;
 
-       err = btrfs_init_acl(inode, dir);
+       err = btrfs_init_inode_security(inode, dir);
        if (err) {
                drop_inode = 1;
                goto out_unlock;
@@ -3772,7 +3811,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 
        drop_on_err = 1;
 
-       err = btrfs_init_acl(inode, dir);
+       err = btrfs_init_inode_security(inode, dir);
        if (err)
                goto out_fail;
 
@@ -4158,9 +4197,10 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb,
        return -EINVAL;
 }
 
-static sector_t btrfs_bmap(struct address_space *mapping, sector_t iblock)
+static int btrfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+               __u64 start, __u64 len)
 {
-       return extent_bmap(mapping, iblock, btrfs_get_extent);
+       return extent_fiemap(inode, fieinfo, start, len, btrfs_get_extent);
 }
 
 int btrfs_readpage(struct file *file, struct page *page)
@@ -4733,7 +4773,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
        if (IS_ERR(inode))
                goto out_unlock;
 
-       err = btrfs_init_acl(inode, dir);
+       err = btrfs_init_inode_security(inode, dir);
        if (err) {
                drop_inode = 1;
                goto out_unlock;
@@ -4987,13 +5027,24 @@ static struct extent_io_ops btrfs_extent_io_ops = {
        .clear_bit_hook = btrfs_clear_bit_hook,
 };
 
+/*
+ * btrfs doesn't support the bmap operation because swapfiles
+ * use bmap to make a mapping of extents in the file.  They assume
+ * these extents won't change over the life of the file and they
+ * use the bmap result to do IO directly to the drive.
+ *
+ * the btrfs bmap call would return logical addresses that aren't
+ * suitable for IO and they also will change frequently as COW
+ * operations happen.  So, swapfile + btrfs == corruption.
+ *
+ * For now we're avoiding this by dropping bmap.
+ */
 static struct address_space_operations btrfs_aops = {
        .readpage       = btrfs_readpage,
        .writepage      = btrfs_writepage,
        .writepages     = btrfs_writepages,
        .readpages      = btrfs_readpages,
        .sync_page      = block_sync_page,
-       .bmap           = btrfs_bmap,
        .direct_IO      = btrfs_direct_IO,
        .invalidatepage = btrfs_invalidatepage,
        .releasepage    = btrfs_releasepage,
@@ -5017,6 +5068,7 @@ static struct inode_operations btrfs_file_inode_operations = {
        .removexattr    = btrfs_removexattr,
        .permission     = btrfs_permission,
        .fallocate      = btrfs_fallocate,
+       .fiemap         = btrfs_fiemap,
 };
 static struct inode_operations btrfs_special_inode_operations = {
        .getattr        = btrfs_getattr,
@@ -5032,4 +5084,8 @@ static struct inode_operations btrfs_symlink_inode_operations = {
        .follow_link    = page_follow_link_light,
        .put_link       = page_put_link,
        .permission     = btrfs_permission,
+       .setxattr       = btrfs_setxattr,
+       .getxattr       = btrfs_getxattr,
+       .listxattr      = btrfs_listxattr,
+       .removexattr    = btrfs_removexattr,
 };
index c2aa33e..988fdc8 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/compat.h>
 #include <linux/bit_spinlock.h>
 #include <linux/security.h>
-#include <linux/version.h>
 #include <linux/xattr.h>
 #include <linux/vmalloc.h>
 #include "compat.h"
index 39bae77..68fd9cc 100644 (file)
 #include "locking.h"
 
 /*
- * locks the per buffer mutex in an extent buffer.  This uses adaptive locks
- * and the spin is not tuned very extensively.  The spinning does make a big
- * difference in almost every workload, but spinning for the right amount of
- * time needs some help.
- *
- * In general, we want to spin as long as the lock holder is doing btree
- * searches, and we should give up if they are in more expensive code.
+ * btrfs_header_level() isn't free, so don't call it when lockdep isn't
+ * on
  */
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+static inline void spin_nested(struct extent_buffer *eb)
+{
+       spin_lock_nested(&eb->lock, BTRFS_MAX_LEVEL - btrfs_header_level(eb));
+}
+#else
+static inline void spin_nested(struct extent_buffer *eb)
+{
+       spin_lock(&eb->lock);
+}
+#endif
 
-int btrfs_tree_lock(struct extent_buffer *eb)
+/*
+ * Setting a lock to blocking will drop the spinlock and set the
+ * flag that forces other procs who want the lock to wait.  After
+ * this you can safely schedule with the lock held.
+ */
+void btrfs_set_lock_blocking(struct extent_buffer *eb)
 {
-       int i;
+       if (!test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags)) {
+               set_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags);
+               spin_unlock(&eb->lock);
+       }
+       /* exit with the spin lock released and the bit set */
+}
 
-       if (mutex_trylock(&eb->mutex))
-               return 0;
+/*
+ * clearing the blocking flag will take the spinlock again.
+ * After this you can't safely schedule
+ */
+void btrfs_clear_lock_blocking(struct extent_buffer *eb)
+{
+       if (test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags)) {
+               spin_nested(eb);
+               clear_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags);
+               smp_mb__after_clear_bit();
+       }
+       /* exit with the spin lock held */
+}
+
+/*
+ * unfortunately, many of the places that currently set a lock to blocking
+ * don't end up blocking for every long, and often they don't block
+ * at all.  For a dbench 50 run, if we don't spin one the blocking bit
+ * at all, the context switch rate can jump up to 400,000/sec or more.
+ *
+ * So, we're still stuck with this crummy spin on the blocking bit,
+ * at least until the most common causes of the short blocks
+ * can be dealt with.
+ */
+static int btrfs_spin_on_block(struct extent_buffer *eb)
+{
+       int i;
        for (i = 0; i < 512; i++) {
                cpu_relax();
-               if (mutex_trylock(&eb->mutex))
+               if (!test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags))
+                       return 1;
+               if (need_resched())
+                       break;
+       }
+       return 0;
+}
+
+/*
+ * This is somewhat different from trylock.  It will take the
+ * spinlock but if it finds the lock is set to blocking, it will
+ * return without the lock held.
+ *
+ * returns 1 if it was able to take the lock and zero otherwise
+ *
+ * After this call, scheduling is not safe without first calling
+ * btrfs_set_lock_blocking()
+ */
+int btrfs_try_spin_lock(struct extent_buffer *eb)
+{
+       int i;
+
+       spin_nested(eb);
+       if (!test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags))
+               return 1;
+       spin_unlock(&eb->lock);
+
+       /* spin for a bit on the BLOCKING flag */
+       for (i = 0; i < 2; i++) {
+               if (!btrfs_spin_on_block(eb))
+                       break;
+
+               spin_nested(eb);
+               if (!test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags))
+                       return 1;
+               spin_unlock(&eb->lock);
+       }
+       return 0;
+}
+
+/*
+ * the autoremove wake function will return 0 if it tried to wake up
+ * a process that was already awake, which means that process won't
+ * count as an exclusive wakeup.  The waitq code will continue waking
+ * procs until it finds one that was actually sleeping.
+ *
+ * For btrfs, this isn't quite what we want.  We want a single proc
+ * to be notified that the lock is ready for taking.  If that proc
+ * already happen to be awake, great, it will loop around and try for
+ * the lock.
+ *
+ * So, btrfs_wake_function always returns 1, even when the proc that we
+ * tried to wake up was already awake.
+ */
+static int btrfs_wake_function(wait_queue_t *wait, unsigned mode,
+                              int sync, void *key)
+{
+       autoremove_wake_function(wait, mode, sync, key);
+       return 1;
+}
+
+/*
+ * returns with the extent buffer spinlocked.
+ *
+ * This will spin and/or wait as required to take the lock, and then
+ * return with the spinlock held.
+ *
+ * After this call, scheduling is not safe without first calling
+ * btrfs_set_lock_blocking()
+ */
+int btrfs_tree_lock(struct extent_buffer *eb)
+{
+       DEFINE_WAIT(wait);
+       wait.func = btrfs_wake_function;
+
+       while(1) {
+               spin_nested(eb);
+
+               /* nobody is blocking, exit with the spinlock held */
+               if (!test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags))
                        return 0;
+
+               /*
+                * we have the spinlock, but the real owner is blocking.
+                * wait for them
+                */
+               spin_unlock(&eb->lock);
+
+               /*
+                * spin for a bit, and if the blocking flag goes away,
+                * loop around
+                */
+               if (btrfs_spin_on_block(eb))
+                       continue;
+
+               prepare_to_wait_exclusive(&eb->lock_wq, &wait,
+                                         TASK_UNINTERRUPTIBLE);
+
+               if (test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags))
+                       schedule();
+
+               finish_wait(&eb->lock_wq, &wait);
        }
-       cpu_relax();
-       mutex_lock_nested(&eb->mutex, BTRFS_MAX_LEVEL - btrfs_header_level(eb));
        return 0;
 }
 
+/*
+ * Very quick trylock, this does not spin or schedule.  It returns
+ * 1 with the spinlock held if it was able to take the lock, or it
+ * returns zero if it was unable to take the lock.
+ *
+ * After this call, scheduling is not safe without first calling
+ * btrfs_set_lock_blocking()
+ */
 int btrfs_try_tree_lock(struct extent_buffer *eb)
 {
-       return mutex_trylock(&eb->mutex);
+       if (spin_trylock(&eb->lock)) {
+               if (test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags)) {
+                       /*
+                        * we've got the spinlock, but the real owner is
+                        * blocking.  Drop the spinlock and return failure
+                        */
+                       spin_unlock(&eb->lock);
+                       return 0;
+               }
+               return 1;
+       }
+       /* someone else has the spinlock giveup */
+       return 0;
 }
 
 int btrfs_tree_unlock(struct extent_buffer *eb)
 {
-       mutex_unlock(&eb->mutex);
+       /*
+        * if we were a blocking owner, we don't have the spinlock held
+        * just clear the bit and look for waiters
+        */
+       if (test_and_clear_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags))
+               smp_mb__after_clear_bit();
+       else
+               spin_unlock(&eb->lock);
+
+       if (waitqueue_active(&eb->lock_wq))
+               wake_up(&eb->lock_wq);
        return 0;
 }
 
 int btrfs_tree_locked(struct extent_buffer *eb)
 {
-       return mutex_is_locked(&eb->mutex);
+       return test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags) ||
+                       spin_is_locked(&eb->lock);
 }
 
 /*
@@ -75,12 +245,14 @@ int btrfs_path_lock_waiting(struct btrfs_path *path, int level)
 {
        int i;
        struct extent_buffer *eb;
+
        for (i = level; i <= level + 1 && i < BTRFS_MAX_LEVEL; i++) {
                eb = path->nodes[i];
                if (!eb)
                        break;
                smp_mb();
-               if (!list_empty(&eb->mutex.wait_list))
+               if (spin_is_contended(&eb->lock) ||
+                   waitqueue_active(&eb->lock_wq))
                        return 1;
        }
        return 0;
index bc1faef..d92e707 100644 (file)
 int btrfs_tree_lock(struct extent_buffer *eb);
 int btrfs_tree_unlock(struct extent_buffer *eb);
 int btrfs_tree_locked(struct extent_buffer *eb);
+
 int btrfs_try_tree_lock(struct extent_buffer *eb);
+int btrfs_try_spin_lock(struct extent_buffer *eb);
+
 int btrfs_path_lock_waiting(struct btrfs_path *path, int level);
+
+void btrfs_set_lock_blocking(struct extent_buffer *eb);
+void btrfs_clear_lock_blocking(struct extent_buffer *eb);
 #endif
index a209401..77c2411 100644 (file)
@@ -613,7 +613,6 @@ int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u64 disk_bytenr,
        struct btrfs_sector_sum *sector_sums;
        struct btrfs_ordered_extent *ordered;
        struct btrfs_ordered_inode_tree *tree = &BTRFS_I(inode)->ordered_tree;
-       struct list_head *cur;
        unsigned long num_sectors;
        unsigned long i;
        u32 sectorsize = BTRFS_I(inode)->root->sectorsize;
@@ -624,8 +623,7 @@ int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u64 disk_bytenr,
                return 1;
 
        mutex_lock(&tree->mutex);
-       list_for_each_prev(cur, &ordered->list) {
-               ordered_sum = list_entry(cur, struct btrfs_ordered_sum, list);
+       list_for_each_entry_reverse(ordered_sum, &ordered->list, list) {
                if (disk_bytenr >= ordered_sum->bytenr) {
                        num_sectors = ordered_sum->len / sectorsize;
                        sector_sums = ordered_sum->sums;
index 6f0acc4..d0cc62b 100644 (file)
@@ -17,6 +17,7 @@
  */
 
 #include <linux/sched.h>
+#include <linux/sort.h>
 #include "ctree.h"
 #include "ref-cache.h"
 #include "transaction.h"
index 16f3183..bc283ad 100644 (file)
@@ -73,5 +73,4 @@ int btrfs_add_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref,
 int btrfs_remove_leaf_refs(struct btrfs_root *root, u64 max_root_gen,
                           int shared);
 int btrfs_remove_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref);
-
 #endif
index db9fb3b..f3fd7e2 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/ctype.h>
 #include <linux/namei.h>
 #include <linux/miscdevice.h>
-#include <linux/version.h>
 #include <linux/magic.h>
 #include "compat.h"
 #include "ctree.h"
@@ -583,17 +582,18 @@ static long btrfs_control_ioctl(struct file *file, unsigned int cmd,
        struct btrfs_ioctl_vol_args *vol;
        struct btrfs_fs_devices *fs_devices;
        int ret = -ENOTTY;
-       int len;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
        vol = kmalloc(sizeof(*vol), GFP_KERNEL);
+       if (!vol)
+               return -ENOMEM;
+
        if (copy_from_user(vol, (void __user *)arg, sizeof(*vol))) {
                ret = -EFAULT;
                goto out;
        }
-       len = strnlen(vol->name, BTRFS_PATH_NAME_MAX);
 
        switch (cmd) {
        case BTRFS_IOC_SCAN_DEV:
index 8a08f94..919172d 100644 (file)
@@ -852,11 +852,9 @@ static noinline int create_pending_snapshots(struct btrfs_trans_handle *trans,
 {
        struct btrfs_pending_snapshot *pending;
        struct list_head *head = &trans->transaction->pending_snapshots;
-       struct list_head *cur;
        int ret;
 
-       list_for_each(cur, head) {
-               pending = list_entry(cur, struct btrfs_pending_snapshot, list);
+       list_for_each_entry(pending, head, list) {
                ret = create_pending_snapshot(trans, fs_info, pending);
                BUG_ON(ret);
        }
index 3e8358c..98d25fa 100644 (file)
@@ -74,6 +74,7 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
                u32 nritems;
 
                root_node = btrfs_lock_root_node(root);
+               btrfs_set_lock_blocking(root_node);
                nritems = btrfs_header_nritems(root_node);
                root->defrag_max.objectid = 0;
                /* from above we know this is not a leaf */
index d81cda2..2079429 100644 (file)
@@ -77,104 +77,6 @@ static int link_to_fixup_dir(struct btrfs_trans_handle *trans,
  * and once to do all the other items.
  */
 
-/*
- * btrfs_add_log_tree adds a new per-subvolume log tree into the
- * tree of log tree roots.  This must be called with a tree log transaction
- * running (see start_log_trans).
- */
-static int btrfs_add_log_tree(struct btrfs_trans_handle *trans,
-                     struct btrfs_root *root)
-{
-       struct btrfs_key key;
-       struct btrfs_root_item root_item;
-       struct btrfs_inode_item *inode_item;
-       struct extent_buffer *leaf;
-       struct btrfs_root *new_root = root;
-       int ret;
-       u64 objectid = root->root_key.objectid;
-
-       leaf = btrfs_alloc_free_block(trans, root, root->leafsize, 0,
-                                     BTRFS_TREE_LOG_OBJECTID,
-                                     trans->transid, 0, 0, 0);
-       if (IS_ERR(leaf)) {
-               ret = PTR_ERR(leaf);
-               return ret;
-       }
-
-       btrfs_set_header_nritems(leaf, 0);
-       btrfs_set_header_level(leaf, 0);
-       btrfs_set_header_bytenr(leaf, leaf->start);
-       btrfs_set_header_generation(leaf, trans->transid);
-       btrfs_set_header_owner(leaf, BTRFS_TREE_LOG_OBJECTID);
-
-       write_extent_buffer(leaf, root->fs_info->fsid,
-                           (unsigned long)btrfs_header_fsid(leaf),
-                           BTRFS_FSID_SIZE);
-       btrfs_mark_buffer_dirty(leaf);
-
-       inode_item = &root_item.inode;
-       memset(inode_item, 0, sizeof(*inode_item));
-       inode_item->generation = cpu_to_le64(1);
-       inode_item->size = cpu_to_le64(3);
-       inode_item->nlink = cpu_to_le32(1);
-       inode_item->nbytes = cpu_to_le64(root->leafsize);
-       inode_item->mode = cpu_to_le32(S_IFDIR | 0755);
-
-       btrfs_set_root_bytenr(&root_item, leaf->start);
-       btrfs_set_root_generation(&root_item, trans->transid);
-       btrfs_set_root_level(&root_item, 0);
-       btrfs_set_root_refs(&root_item, 0);
-       btrfs_set_root_used(&root_item, 0);
-
-       memset(&root_item.drop_progress, 0, sizeof(root_item.drop_progress));
-       root_item.drop_level = 0;
-
-       btrfs_tree_unlock(leaf);
-       free_extent_buffer(leaf);
-       leaf = NULL;
-
-       btrfs_set_root_dirid(&root_item, 0);
-
-       key.objectid = BTRFS_TREE_LOG_OBJECTID;
-       key.offset = objectid;
-       btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY);
-       ret = btrfs_insert_root(trans, root->fs_info->log_root_tree, &key,
-                               &root_item);
-       if (ret)
-               goto fail;
-
-       new_root = btrfs_read_fs_root_no_radix(root->fs_info->log_root_tree,
-                                              &key);
-       BUG_ON(!new_root);
-
-       WARN_ON(root->log_root);
-       root->log_root = new_root;
-
-       /*
-        * log trees do not get reference counted because they go away
-        * before a real commit is actually done.  They do store pointers
-        * to file data extents, and those reference counts still get
-        * updated (along with back refs to the log tree).
-        */
-       new_root->ref_cows = 0;
-       new_root->last_trans = trans->transid;
-
-       /*
-        * we need to make sure the root block for this new tree
-        * is marked as dirty in the dirty_log_pages tree.  This
-        * is how it gets flushed down to disk at tree log commit time.
-        *
-        * the tree logging mutex keeps others from coming in and changing
-        * the new_root->node, so we can safely access it here
-        */
-       set_extent_dirty(&new_root->dirty_log_pages, new_root->node->start,
-                        new_root->node->start + new_root->node->len - 1,
-                        GFP_NOFS);
-
-fail:
-       return ret;
-}
-
 /*
  * start a sub transaction and setup the log tree
  * this increments the log tree writer count to make the people
@@ -184,6 +86,14 @@ static int start_log_trans(struct btrfs_trans_handle *trans,
                           struct btrfs_root *root)
 {
        int ret;
+
+       mutex_lock(&root->log_mutex);
+       if (root->log_root) {
+               root->log_batch++;
+               atomic_inc(&root->log_writers);
+               mutex_unlock(&root->log_mutex);
+               return 0;
+       }
        mutex_lock(&root->fs_info->tree_log_mutex);
        if (!root->fs_info->log_root_tree) {
                ret = btrfs_init_log_root_tree(trans, root->fs_info);
@@ -193,9 +103,10 @@ static int start_log_trans(struct btrfs_trans_handle *trans,
                ret = btrfs_add_log_tree(trans, root);
                BUG_ON(ret);
        }
-       atomic_inc(&root->fs_info->tree_log_writers);
-       root->fs_info->tree_log_batch++;
        mutex_unlock(&root->fs_info->tree_log_mutex);
+       root->log_batch++;
+       atomic_inc(&root->log_writers);
+       mutex_unlock(&root->log_mutex);
        return 0;
 }
 
@@ -212,13 +123,12 @@ static int join_running_log_trans(struct btrfs_root *root)
        if (!root->log_root)
                return -ENOENT;
 
-       mutex_lock(&root->fs_info->tree_log_mutex);
+       mutex_lock(&root->log_mutex);
        if (root->log_root) {
                ret = 0;
-               atomic_inc(&root->fs_info->tree_log_writers);
-               root->fs_info->tree_log_batch++;
+               atomic_inc(&root->log_writers);
        }
-       mutex_unlock(&root->fs_info->tree_log_mutex);
+       mutex_unlock(&root->log_mutex);
        return ret;
 }
 
@@ -228,10 +138,11 @@ static int join_running_log_trans(struct btrfs_root *root)
  */
 static int end_log_trans(struct btrfs_root *root)
 {
-       atomic_dec(&root->fs_info->tree_log_writers);
-       smp_mb();
-       if (waitqueue_active(&root->fs_info->tree_log_wait))
-               wake_up(&root->fs_info->tree_log_wait);
+       if (atomic_dec_and_test(&root->log_writers)) {
+               smp_mb();
+               if (waitqueue_active(&root->log_writer_wait))
+                       wake_up(&root->log_writer_wait);
+       }
        return 0;
 }
 
@@ -1704,6 +1615,7 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,
 
                                btrfs_tree_lock(next);
                                clean_tree_block(trans, root, next);
+                               btrfs_set_lock_blocking(next);
                                btrfs_wait_tree_block_writeback(next);
                                btrfs_tree_unlock(next);
 
@@ -1750,6 +1662,7 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,
                next = path->nodes[*level];
                btrfs_tree_lock(next);
                clean_tree_block(trans, root, next);
+               btrfs_set_lock_blocking(next);
                btrfs_wait_tree_block_writeback(next);
                btrfs_tree_unlock(next);
 
@@ -1807,6 +1720,7 @@ static noinline int walk_up_log_tree(struct btrfs_trans_handle *trans,
 
                                btrfs_tree_lock(next);
                                clean_tree_block(trans, root, next);
+                               btrfs_set_lock_blocking(next);
                                btrfs_wait_tree_block_writeback(next);
                                btrfs_tree_unlock(next);
 
@@ -1879,6 +1793,7 @@ static int walk_log_tree(struct btrfs_trans_handle *trans,
 
                        btrfs_tree_lock(next);
                        clean_tree_block(trans, log, next);
+                       btrfs_set_lock_blocking(next);
                        btrfs_wait_tree_block_writeback(next);
                        btrfs_tree_unlock(next);
 
@@ -1902,26 +1817,65 @@ static int walk_log_tree(struct btrfs_trans_handle *trans,
                }
        }
        btrfs_free_path(path);
-       if (wc->free)
-               free_extent_buffer(log->node);
        return ret;
 }
 
-static int wait_log_commit(struct btrfs_root *log)
+/*
+ * helper function to update the item for a given subvolumes log root
+ * in the tree of log roots
+ */
+static int update_log_root(struct btrfs_trans_handle *trans,
+                          struct btrfs_root *log)
+{
+       int ret;
+
+       if (log->log_transid == 1) {
+               /* insert root item on the first sync */
+               ret = btrfs_insert_root(trans, log->fs_info->log_root_tree,
+                               &log->root_key, &log->root_item);
+       } else {
+               ret = btrfs_update_root(trans, log->fs_info->log_root_tree,
+                               &log->root_key, &log->root_item);
+       }
+       return ret;
+}
+
+static int wait_log_commit(struct btrfs_root *root, unsigned long transid)
 {
        DEFINE_WAIT(wait);
-       u64 transid = log->fs_info->tree_log_transid;
+       int index = transid % 2;
 
+       /*
+        * we only allow two pending log transactions at a time,
+        * so we know that if ours is more than 2 older than the
+        * current transaction, we're done
+        */
        do {
-               prepare_to_wait(&log->fs_info->tree_log_wait, &wait,
-                               TASK_UNINTERRUPTIBLE);
-               mutex_unlock(&log->fs_info->tree_log_mutex);
-               if (atomic_read(&log->fs_info->tree_log_commit))
+               prepare_to_wait(&root->log_commit_wait[index],
+                               &wait, TASK_UNINTERRUPTIBLE);
+               mutex_unlock(&root->log_mutex);
+               if (root->log_transid < transid + 2 &&
+                   atomic_read(&root->log_commit[index]))
                        schedule();
-               finish_wait(&log->fs_info->tree_log_wait, &wait);
-               mutex_lock(&log->fs_info->tree_log_mutex);
-       } while (transid == log->fs_info->tree_log_transid &&
-               atomic_read(&log->fs_info->tree_log_commit));
+               finish_wait(&root->log_commit_wait[index], &wait);
+               mutex_lock(&root->log_mutex);
+       } while (root->log_transid < transid + 2 &&
+                atomic_read(&root->log_commit[index]));
+       return 0;
+}
+
+static int wait_for_writer(struct btrfs_root *root)
+{
+       DEFINE_WAIT(wait);
+       while (atomic_read(&root->log_writers)) {
+               prepare_to_wait(&root->log_writer_wait,
+                               &wait, TASK_UNINTERRUPTIBLE);
+               mutex_unlock(&root->log_mutex);
+               if (atomic_read(&root->log_writers))
+                       schedule();
+               mutex_lock(&root->log_mutex);
+               finish_wait(&root->log_writer_wait, &wait);
+       }
        return 0;
 }
 
@@ -1933,57 +1887,114 @@ static int wait_log_commit(struct btrfs_root *log)
 int btrfs_sync_log(struct btrfs_trans_handle *trans,
                   struct btrfs_root *root)
 {
+       int index1;
+       int index2;
        int ret;
-       unsigned long batch;
        struct btrfs_root *log = root->log_root;
+       struct btrfs_root *log_root_tree = root->fs_info->log_root_tree;
 
-       mutex_lock(&log->fs_info->tree_log_mutex);
-       if (atomic_read(&log->fs_info->tree_log_commit)) {
-               wait_log_commit(log);
-               goto out;
+       mutex_lock(&root->log_mutex);
+       index1 = root->log_transid % 2;
+       if (atomic_read(&root->log_commit[index1])) {
+               wait_log_commit(root, root->log_transid);
+               mutex_unlock(&root->log_mutex);
+               return 0;
        }
-       atomic_set(&log->fs_info->tree_log_commit, 1);
+       atomic_set(&root->log_commit[index1], 1);
+
+       /* wait for previous tree log sync to complete */
+       if (atomic_read(&root->log_commit[(index1 + 1) % 2]))
+               wait_log_commit(root, root->log_transid - 1);
 
        while (1) {
-               batch = log->fs_info->tree_log_batch;
-               mutex_unlock(&log->fs_info->tree_log_mutex);
+               unsigned long batch = root->log_batch;
+               mutex_unlock(&root->log_mutex);
                schedule_timeout_uninterruptible(1);
-               mutex_lock(&log->fs_info->tree_log_mutex);
-
-               while (atomic_read(&log->fs_info->tree_log_writers)) {
-                       DEFINE_WAIT(wait);
-                       prepare_to_wait(&log->fs_info->tree_log_wait, &wait,
-                                       TASK_UNINTERRUPTIBLE);
-                       mutex_unlock(&log->fs_info->tree_log_mutex);
-                       if (atomic_read(&log->fs_info->tree_log_writers))
-                               schedule();
-                       mutex_lock(&log->fs_info->tree_log_mutex);
-                       finish_wait(&log->fs_info->tree_log_wait, &wait);
-               }
-               if (batch == log->fs_info->tree_log_batch)
+               mutex_lock(&root->log_mutex);
+               wait_for_writer(root);
+               if (batch == root->log_batch)
                        break;
        }
 
        ret = btrfs_write_and_wait_marked_extents(log, &log->dirty_log_pages);
        BUG_ON(ret);
-       ret = btrfs_write_and_wait_marked_extents(root->fs_info->log_root_tree,
-                              &root->fs_info->log_root_tree->dirty_log_pages);
+
+       btrfs_set_root_bytenr(&log->root_item, log->node->start);
+       btrfs_set_root_generation(&log->root_item, trans->transid);
+       btrfs_set_root_level(&log->root_item, btrfs_header_level(log->node));
+
+       root->log_batch = 0;
+       root->log_transid++;
+       log->log_transid = root->log_transid;
+       smp_mb();
+       /*
+        * log tree has been flushed to disk, new modifications of
+        * the log will be written to new positions. so it's safe to
+        * allow log writers to go in.
+        */
+       mutex_unlock(&root->log_mutex);
+
+       mutex_lock(&log_root_tree->log_mutex);
+       log_root_tree->log_batch++;
+       atomic_inc(&log_root_tree->log_writers);
+       mutex_unlock(&log_root_tree->log_mutex);
+
+       ret = update_log_root(trans, log);
+       BUG_ON(ret);
+
+       mutex_lock(&log_root_tree->log_mutex);
+       if (atomic_dec_and_test(&log_root_tree->log_writers)) {
+               smp_mb();
+               if (waitqueue_active(&log_root_tree->log_writer_wait))
+                       wake_up(&log_root_tree->log_writer_wait);
+       }
+
+       index2 = log_root_tree->log_transid % 2;
+       if (atomic_read(&log_root_tree->log_commit[index2])) {
+               wait_log_commit(log_root_tree, log_root_tree->log_transid);
+               mutex_unlock(&log_root_tree->log_mutex);
+               goto out;
+       }
+       atomic_set(&log_root_tree->log_commit[index2], 1);
+
+       if (atomic_read(&log_root_tree->log_commit[(index2 + 1) % 2]))
+               wait_log_commit(log_root_tree, log_root_tree->log_transid - 1);
+
+       wait_for_writer(log_root_tree);
+
+       ret = btrfs_write_and_wait_marked_extents(log_root_tree,
+                               &log_root_tree->dirty_log_pages);
        BUG_ON(ret);
 
        btrfs_set_super_log_root(&root->fs_info->super_for_commit,
-                                log->fs_info->log_root_tree->node->start);
+                               log_root_tree->node->start);
        btrfs_set_super_log_root_level(&root->fs_info->super_for_commit,
-                      btrfs_header_level(log->fs_info->log_root_tree->node));
+                               btrfs_header_level(log_root_tree->node));
+
+       log_root_tree->log_batch = 0;
+       log_root_tree->log_transid++;
+       smp_mb();
+
+       mutex_unlock(&log_root_tree->log_mutex);
+
+       /*
+        * nobody else is going to jump in and write the the ctree
+        * super here because the log_commit atomic below is protecting
+        * us.  We must be called with a transaction handle pinning
+        * the running transaction open, so a full commit can't hop
+        * in and cause problems either.
+        */
+       write_ctree_super(trans, root->fs_info->tree_root, 2);
 
-       write_ctree_super(trans, log->fs_info->tree_root, 2);
-       log->fs_info->tree_log_transid++;
-       log->fs_info->tree_log_batch = 0;
-       atomic_set(&log->fs_info->tree_log_commit, 0);
+       atomic_set(&log_root_tree->log_commit[index2], 0);
        smp_mb();
-       if (waitqueue_active(&log->fs_info->tree_log_wait))
-               wake_up(&log->fs_info->tree_log_wait);
+       if (waitqueue_active(&log_root_tree->log_commit_wait[index2]))
+               wake_up(&log_root_tree->log_commit_wait[index2]);
 out:
-       mutex_unlock(&log->fs_info->tree_log_mutex);
+       atomic_set(&root->log_commit[index1], 0);
+       smp_mb();
+       if (waitqueue_active(&root->log_commit_wait[index1]))
+               wake_up(&root->log_commit_wait[index1]);
        return 0;
 }
 
@@ -2019,37 +2030,17 @@ int btrfs_free_log(struct btrfs_trans_handle *trans, struct btrfs_root *root)
                                   start, end, GFP_NOFS);
        }
 
-       log = root->log_root;
-       ret = btrfs_del_root(trans, root->fs_info->log_root_tree,
-                            &log->root_key);
-       BUG_ON(ret);
+       if (log->log_transid > 0) {
+               ret = btrfs_del_root(trans, root->fs_info->log_root_tree,
+                                    &log->root_key);
+               BUG_ON(ret);
+       }
        root->log_root = NULL;
-       kfree(root->log_root);
+       free_extent_buffer(log->node);
+       kfree(log);
        return 0;
 }
 
-/*
- * helper function to update the item for a given subvolumes log root
- * in the tree of log roots
- */
-static int update_log_root(struct btrfs_trans_handle *trans,
-                          struct btrfs_root *log)
-{
-       u64 bytenr = btrfs_root_bytenr(&log->root_item);
-       int ret;
-
-       if (log->node->start == bytenr)
-               return 0;
-
-       btrfs_set_root_bytenr(&log->root_item, log->node->start);
-       btrfs_set_root_generation(&log->root_item, trans->transid);
-       btrfs_set_root_level(&log->root_item, btrfs_header_level(log->node));
-       ret = btrfs_update_root(trans, log->fs_info->log_root_tree,
-                               &log->root_key, &log->root_item);
-       BUG_ON(ret);
-       return ret;
-}
-
 /*
  * If both a file and directory are logged, and unlinks or renames are
  * mixed in, we have a few interesting corners:
@@ -2711,11 +2702,6 @@ next_slot:
 
        btrfs_free_path(path);
        btrfs_free_path(dst_path);
-
-       mutex_lock(&root->fs_info->tree_log_mutex);
-       ret = update_log_root(trans, log);
-       BUG_ON(ret);
-       mutex_unlock(&root->fs_info->tree_log_mutex);
 out:
        return 0;
 }
index 3451e1c..bcd14eb 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/buffer_head.h>
 #include <linux/blkdev.h>
 #include <linux/random.h>
-#include <linux/version.h>
 #include <asm/div64.h>
 #include "compat.h"
 #include "ctree.h"
@@ -104,10 +103,8 @@ static noinline struct btrfs_device *__find_device(struct list_head *head,
                                                   u64 devid, u8 *uuid)
 {
        struct btrfs_device *dev;
-       struct list_head *cur;
 
-       list_for_each(cur, head) {
-               dev = list_entry(cur, struct btrfs_device, dev_list);
+       list_for_each_entry(dev, head, dev_list) {
                if (dev->devid == devid &&
                    (!uuid || !memcmp(dev->uuid, uuid, BTRFS_UUID_SIZE))) {
                        return dev;
@@ -118,11 +115,9 @@ static noinline struct btrfs_device *__find_device(struct list_head *head,
 
 static noinline struct btrfs_fs_devices *find_fsid(u8 *fsid)
 {
-       struct list_head *cur;
        struct btrfs_fs_devices *fs_devices;
 
-       list_for_each(cur, &fs_uuids) {
-               fs_devices = list_entry(cur, struct btrfs_fs_devices, list);
+       list_for_each_entry(fs_devices, &fs_uuids, list) {
                if (memcmp(fsid, fs_devices->fsid, BTRFS_FSID_SIZE) == 0)
                        return fs_devices;
        }
@@ -159,6 +154,7 @@ static noinline int run_scheduled_bios(struct btrfs_device *device)
 loop:
        spin_lock(&device->io_lock);
 
+loop_lock:
        /* take all the bios off the list at once and process them
         * later on (without the lock held).  But, remember the
         * tail and other pointers so the bios can be properly reinserted
@@ -208,7 +204,7 @@ loop:
                 * is now congested.  Back off and let other work structs
                 * run instead
                 */
-               if (pending && bdi_write_congested(bdi) &&
+               if (pending && bdi_write_congested(bdi) && num_run > 16 &&
                    fs_info->fs_devices->open_devices > 1) {
                        struct bio *old_head;
 
@@ -220,7 +216,8 @@ loop:
                                tail->bi_next = old_head;
                        else
                                device->pending_bio_tail = tail;
-                       device->running_pending = 0;
+
+                       device->running_pending = 1;
 
                        spin_unlock(&device->io_lock);
                        btrfs_requeue_work(&device->work);
@@ -229,6 +226,11 @@ loop:
        }
        if (again)
                goto loop;
+
+       spin_lock(&device->io_lock);
+       if (device->pending_bios)
+               goto loop_lock;
+       spin_unlock(&device->io_lock);
 done:
        return 0;
 }
@@ -345,14 +347,11 @@ error:
 
 int btrfs_close_extra_devices(struct btrfs_fs_devices *fs_devices)
 {
-       struct list_head *tmp;
-       struct list_head *cur;
-       struct btrfs_device *device;
+       struct btrfs_device *device, *next;
 
        mutex_lock(&uuid_mutex);
 again:
-       list_for_each_safe(cur, tmp, &fs_devices->devices) {
-               device = list_entry(cur, struct btrfs_device, dev_list);
+       list_for_each_entry_safe(device, next, &fs_devices->devices, dev_list) {
                if (device->in_fs_metadata)
                        continue;
 
@@ -383,14 +382,12 @@ again:
 
 static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
 {
-       struct list_head *cur;
        struct btrfs_device *device;
 
        if (--fs_devices->opened > 0)
                return 0;
 
-       list_for_each(cur, &fs_devices->devices) {
-               device = list_entry(cur, struct btrfs_device, dev_list);
+       list_for_each_entry(device, &fs_devices->devices, dev_list) {
                if (device->bdev) {
                        close_bdev_exclusive(device->bdev, device->mode);
                        fs_devices->open_devices--;
@@ -439,7 +436,6 @@ static int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
 {
        struct block_device *bdev;
        struct list_head *head = &fs_devices->devices;
-       struct list_head *cur;
        struct btrfs_device *device;
        struct block_device *latest_bdev = NULL;
        struct buffer_head *bh;
@@ -450,8 +446,7 @@ static int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
        int seeding = 1;
        int ret = 0;
 
-       list_for_each(cur, head) {
-               device = list_entry(cur, struct btrfs_device, dev_list);
+       list_for_each_entry(device, head, dev_list) {
                if (device->bdev)
                        continue;
                if (!device->name)
@@ -578,7 +573,7 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder,
                       *(unsigned long long *)disk_super->fsid,
                       *(unsigned long long *)(disk_super->fsid + 8));
        }
-       printk(KERN_INFO "devid %llu transid %llu %s\n",
+       printk(KERN_CONT "devid %llu transid %llu %s\n",
               (unsigned long long)devid, (unsigned long long)transid, path);
        ret = device_list_add(path, disk_super, devid, fs_devices_ret);
 
@@ -1017,14 +1012,12 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
        }
 
        if (strcmp(device_path, "missing") == 0) {
-               struct list_head *cur;
                struct list_head *devices;
                struct btrfs_device *tmp;
 
                device = NULL;
                devices = &root->fs_info->fs_devices->devices;
-               list_for_each(cur, devices) {
-                       tmp = list_entry(cur, struct btrfs_device, dev_list);
+               list_for_each_entry(tmp, devices, dev_list) {
                        if (tmp->in_fs_metadata && !tmp->bdev) {
                                device = tmp;
                                break;
@@ -1280,7 +1273,6 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
        struct btrfs_trans_handle *trans;
        struct btrfs_device *device;
        struct block_device *bdev;
-       struct list_head *cur;
        struct list_head *devices;
        struct super_block *sb = root->fs_info->sb;
        u64 total_bytes;
@@ -1304,8 +1296,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
        mutex_lock(&root->fs_info->volume_mutex);
 
        devices = &root->fs_info->fs_devices->devices;
-       list_for_each(cur, devices) {
-               device = list_entry(cur, struct btrfs_device, dev_list);
+       list_for_each_entry(device, devices, dev_list) {
                if (device->bdev == bdev) {
                        ret = -EEXIST;
                        goto error;
@@ -1704,7 +1695,6 @@ static u64 div_factor(u64 num, int factor)
 int btrfs_balance(struct btrfs_root *dev_root)
 {
        int ret;
-       struct list_head *cur;
        struct list_head *devices = &dev_root->fs_info->fs_devices->devices;
        struct btrfs_device *device;
        u64 old_size;
@@ -1723,8 +1713,7 @@ int btrfs_balance(struct btrfs_root *dev_root)
        dev_root = dev_root->fs_info->dev_root;
 
        /* step one make some room on all the devices */
-       list_for_each(cur, devices) {
-               device = list_entry(cur, struct btrfs_device, dev_list);
+       list_for_each_entry(device, devices, dev_list) {
                old_size = device->total_bytes;
                size_to_free = div_factor(old_size, 1);
                size_to_free = min(size_to_free, (u64)1 * 1024 * 1024);
index 7f332e2..a9d3bf4 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/slab.h>
 #include <linux/rwsem.h>
 #include <linux/xattr.h>
+#include <linux/security.h>
 #include "ctree.h"
 #include "btrfs_inode.h"
 #include "transaction.h"
@@ -45,9 +46,12 @@ ssize_t __btrfs_getxattr(struct inode *inode, const char *name,
        /* lookup the xattr by name */
        di = btrfs_lookup_xattr(NULL, root, path, inode->i_ino, name,
                                strlen(name), 0);
-       if (!di || IS_ERR(di)) {
+       if (!di) {
                ret = -ENODATA;
                goto out;
+       } else if (IS_ERR(di)) {
+               ret = PTR_ERR(di);
+               goto out;
        }
 
        leaf = path->nodes[0];
@@ -62,6 +66,14 @@ ssize_t __btrfs_getxattr(struct inode *inode, const char *name,
                ret = -ERANGE;
                goto out;
        }
+
+       /*
+        * The way things are packed into the leaf is like this
+        * |struct btrfs_dir_item|name|data|
+        * where name is the xattr name, so security.foo, and data is the
+        * content of the xattr.  data_ptr points to the location in memory
+        * where the data starts in the in memory leaf
+        */
        data_ptr = (unsigned long)((char *)(di + 1) +
                                   btrfs_dir_name_len(leaf, di));
        read_extent_buffer(leaf, buffer, data_ptr,
@@ -86,7 +98,7 @@ int __btrfs_setxattr(struct inode *inode, const char *name,
        if (!path)
                return -ENOMEM;
 
-       trans = btrfs_start_transaction(root, 1);
+       trans = btrfs_join_transaction(root, 1);
        btrfs_set_trans_block_group(trans, inode);
 
        /* first lets see if we already have this xattr */
@@ -176,7 +188,6 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
        ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
        if (ret < 0)
                goto err;
-       ret = 0;
        advance = 0;
        while (1) {
                leaf = path->nodes[0];
@@ -320,3 +331,34 @@ int btrfs_removexattr(struct dentry *dentry, const char *name)
                return -EOPNOTSUPP;
        return __btrfs_setxattr(dentry->d_inode, name, NULL, 0, XATTR_REPLACE);
 }
+
+int btrfs_xattr_security_init(struct inode *inode, struct inode *dir)
+{
+       int err;
+       size_t len;
+       void *value;
+       char *suffix;
+       char *name;
+
+       err = security_inode_init_security(inode, dir, &suffix, &value, &len);
+       if (err) {
+               if (err == -EOPNOTSUPP)
+                       return 0;
+               return err;
+       }
+
+       name = kmalloc(XATTR_SECURITY_PREFIX_LEN + strlen(suffix) + 1,
+                      GFP_NOFS);
+       if (!name) {
+               err = -ENOMEM;
+       } else {
+               strcpy(name, XATTR_SECURITY_PREFIX);
+               strcpy(name + XATTR_SECURITY_PREFIX_LEN, suffix);
+               err = __btrfs_setxattr(inode, name, value, len, 0);
+               kfree(name);
+       }
+
+       kfree(suffix);
+       kfree(value);
+       return err;
+}
index 5b1d08f..c71e9c3 100644 (file)
@@ -36,4 +36,6 @@ extern int btrfs_setxattr(struct dentry *dentry, const char *name,
                const void *value, size_t size, int flags);
 extern int btrfs_removexattr(struct dentry *dentry, const char *name);
 
+extern int btrfs_xattr_security_init(struct inode *inode, struct inode *dir);
+
 #endif /* __XATTR__ */
index b58208f..665d446 100644 (file)
@@ -2688,7 +2688,7 @@ int nobh_write_end(struct file *file, struct address_space *mapping,
        struct buffer_head *bh;
        BUG_ON(fsdata != NULL && page_has_buffers(page));
 
-       if (unlikely(copied < len) && !page_has_buffers(page))
+       if (unlikely(copied < len) && head)
                attach_nobh_buffers(page, head);
        if (page_has_buffers(page))
                return generic_write_end(file, mapping, pos, len,
index c8f8d59..9c6d815 100644 (file)
@@ -785,7 +785,7 @@ static int sg_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
 
        if (copy_in_user(&sgio->status, &sgio32->status,
                         (4 * sizeof(unsigned char)) +
-                        (2 * sizeof(unsigned (short))) +
+                        (2 * sizeof(unsigned short)) +
                         (3 * sizeof(int))))
                return -EFAULT;
 
index c01e043..f6caeb1 100644 (file)
@@ -1716,7 +1716,7 @@ static int ecryptfs_copy_filename(char **copied_name, size_t *copied_name_size,
 {
        int rc = 0;
 
-       (*copied_name) = kmalloc((name_size + 2), GFP_KERNEL);
+       (*copied_name) = kmalloc((name_size + 1), GFP_KERNEL);
        if (!(*copied_name)) {
                rc = -ENOMEM;
                goto out;
@@ -1726,7 +1726,7 @@ static int ecryptfs_copy_filename(char **copied_name, size_t *copied_name_size,
                                                 * in printing out the
                                                 * string in debug
                                                 * messages */
-       (*copied_name_size) = (name_size + 1);
+       (*copied_name_size) = name_size;
 out:
        return rc;
 }
index d861096..60fe740 100644 (file)
@@ -5390,6 +5390,9 @@ int ocfs2_remove_btree_range(struct inode *inode,
                goto out;
        }
 
+       vfs_dq_free_space_nodirty(inode,
+                                 ocfs2_clusters_to_bytes(inode->i_sb, len));
+
        ret = ocfs2_remove_extent(inode, et, cpos, len, handle, meta_ac,
                                  dealloc);
        if (ret) {
index b1cc7c3..e9d7c20 100644 (file)
@@ -38,6 +38,7 @@
 #include "dlmglue.h"
 #include "file.h"
 #include "inode.h"
+#include "super.h"
 
 
 static int ocfs2_dentry_revalidate(struct dentry *dentry,
@@ -294,6 +295,34 @@ out_attach:
        return ret;
 }
 
+static DEFINE_SPINLOCK(dentry_list_lock);
+
+/* We limit the number of dentry locks to drop in one go. We have
+ * this limit so that we don't starve other users of ocfs2_wq. */
+#define DL_INODE_DROP_COUNT 64
+
+/* Drop inode references from dentry locks */
+void ocfs2_drop_dl_inodes(struct work_struct *work)
+{
+       struct ocfs2_super *osb = container_of(work, struct ocfs2_super,
+                                              dentry_lock_work);
+       struct ocfs2_dentry_lock *dl;
+       int drop_count = DL_INODE_DROP_COUNT;
+
+       spin_lock(&dentry_list_lock);
+       while (osb->dentry_lock_list && drop_count--) {
+               dl = osb->dentry_lock_list;
+               osb->dentry_lock_list = dl->dl_next;
+               spin_unlock(&dentry_list_lock);
+               iput(dl->dl_inode);
+               kfree(dl);
+               spin_lock(&dentry_list_lock);
+       }
+       if (osb->dentry_lock_list)
+               queue_work(ocfs2_wq, &osb->dentry_lock_work);
+       spin_unlock(&dentry_list_lock);
+}
+
 /*
  * ocfs2_dentry_iput() and friends.
  *
@@ -318,16 +347,23 @@ out_attach:
 static void ocfs2_drop_dentry_lock(struct ocfs2_super *osb,
                                   struct ocfs2_dentry_lock *dl)
 {
-       iput(dl->dl_inode);
        ocfs2_simple_drop_lockres(osb, &dl->dl_lockres);
        ocfs2_lock_res_free(&dl->dl_lockres);
-       kfree(dl);
+
+       /* We leave dropping of inode reference to ocfs2_wq as that can
+        * possibly lead to inode deletion which gets tricky */
+       spin_lock(&dentry_list_lock);
+       if (!osb->dentry_lock_list)
+               queue_work(ocfs2_wq, &osb->dentry_lock_work);
+       dl->dl_next = osb->dentry_lock_list;
+       osb->dentry_lock_list = dl;
+       spin_unlock(&dentry_list_lock);
 }
 
 void ocfs2_dentry_lock_put(struct ocfs2_super *osb,
                           struct ocfs2_dentry_lock *dl)
 {
-       int unlock = 0;
+       int unlock;
 
        BUG_ON(dl->dl_count == 0);
 
index c091c34..d06e16c 100644 (file)
 extern struct dentry_operations ocfs2_dentry_ops;
 
 struct ocfs2_dentry_lock {
+       /* Use count of dentry lock */
        unsigned int            dl_count;
-       u64                     dl_parent_blkno;
+       union {
+               /* Linked list of dentry locks to release */
+               struct ocfs2_dentry_lock *dl_next;
+               u64                     dl_parent_blkno;
+       };
 
        /*
         * The ocfs2_dentry_lock keeps an inode reference until
@@ -47,6 +52,8 @@ int ocfs2_dentry_attach_lock(struct dentry *dentry, struct inode *inode,
 void ocfs2_dentry_lock_put(struct ocfs2_super *osb,
                           struct ocfs2_dentry_lock *dl);
 
+void ocfs2_drop_dl_inodes(struct work_struct *work);
+
 struct dentry *ocfs2_find_local_alias(struct inode *inode, u64 parent_blkno,
                                      int skip_unhashed);
 
index b0c4cad..206a237 100644 (file)
@@ -2860,6 +2860,10 @@ static void ocfs2_unlock_ast(void *opaque, int error)
        case OCFS2_UNLOCK_CANCEL_CONVERT:
                mlog(0, "Cancel convert success for %s\n", lockres->l_name);
                lockres->l_action = OCFS2_AST_INVALID;
+               /* Downconvert thread may have requeued this lock, we
+                * need to wake it. */
+               if (lockres->l_flags & OCFS2_LOCK_BLOCKED)
+                       ocfs2_wake_downconvert_thread(ocfs2_get_lockres_osb(lockres));
                break;
        case OCFS2_UNLOCK_DROP_LOCK:
                lockres->l_level = DLM_LOCK_IV;
index ad5c24a..0773841 100644 (file)
@@ -210,6 +210,7 @@ struct ocfs2_journal;
 struct ocfs2_slot_info;
 struct ocfs2_recovery_map;
 struct ocfs2_quota_recovery;
+struct ocfs2_dentry_lock;
 struct ocfs2_super
 {
        struct task_struct *commit_task;
@@ -325,6 +326,11 @@ struct ocfs2_super
        struct list_head blocked_lock_list;
        unsigned long blocked_lock_count;
 
+       /* List of dentry locks to release. Anyone can add locks to
+        * the list, ocfs2_wq processes the list  */
+       struct ocfs2_dentry_lock *dentry_lock_list;
+       struct work_struct dentry_lock_work;
+
        wait_queue_head_t               osb_mount_event;
 
        /* Truncate log info */
index f4efa89..1ed0f7c 100644 (file)
@@ -754,7 +754,9 @@ static int ocfs2_mark_dquot_dirty(struct dquot *dquot)
        if (dquot->dq_flags & mask)
                sync = 1;
        spin_unlock(&dq_data_lock);
-       if (!sync) {
+       /* This is a slight hack but we can't afford getting global quota
+        * lock if we already have a transaction started. */
+       if (!sync || journal_current_handle()) {
                status = ocfs2_write_dquot(dquot);
                goto out;
        }
index 43ed113..b1cb38f 100644 (file)
@@ -1887,6 +1887,9 @@ static int ocfs2_initialize_super(struct super_block *sb,
        INIT_WORK(&journal->j_recovery_work, ocfs2_complete_recovery);
        journal->j_state = OCFS2_JOURNAL_FREE;
 
+       INIT_WORK(&osb->dentry_lock_work, ocfs2_drop_dl_inodes);
+       osb->dentry_lock_list = NULL;
+
        /* get some pseudo constants for clustersize bits */
        osb->s_clustersize_bits =
                le32_to_cpu(di->id2.i_super.s_clustersize_bits);
index e1d638a..915039f 100644 (file)
@@ -4729,13 +4729,6 @@ static int ocfs2_xattr_bucket_value_truncate(struct inode *inode,
        vb.vb_xv = (struct ocfs2_xattr_value_root *)
                (vb.vb_bh->b_data + offset % blocksize);
 
-       ret = ocfs2_xattr_bucket_journal_access(ctxt->handle, bucket,
-                                               OCFS2_JOURNAL_ACCESS_WRITE);
-       if (ret) {
-               mlog_errno(ret);
-               goto out;
-       }
-
        /*
         * From here on out we have to dirty the bucket.  The generic
         * value calls only modify one of the bucket's bhs, but we need
@@ -4748,12 +4741,18 @@ static int ocfs2_xattr_bucket_value_truncate(struct inode *inode,
        ret = ocfs2_xattr_value_truncate(inode, &vb, len, ctxt);
        if (ret) {
                mlog_errno(ret);
-               goto out_dirty;
+               goto out;
+       }
+
+       ret = ocfs2_xattr_bucket_journal_access(ctxt->handle, bucket,
+                                               OCFS2_JOURNAL_ACCESS_WRITE);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
        }
 
        xe->xe_value_size = cpu_to_le64(len);
 
-out_dirty:
        ocfs2_xattr_bucket_journal_dirty(ctxt->handle, bucket);
 
 out:
index b569ff1..5267098 100644 (file)
@@ -54,6 +54,64 @@ int seq_open(struct file *file, const struct seq_operations *op)
 }
 EXPORT_SYMBOL(seq_open);
 
+static int traverse(struct seq_file *m, loff_t offset)
+{
+       loff_t pos = 0, index;
+       int error = 0;
+       void *p;
+
+       m->version = 0;
+       index = 0;
+       m->count = m->from = 0;
+       if (!offset) {
+               m->index = index;
+               return 0;
+       }
+       if (!m->buf) {
+               m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL);
+               if (!m->buf)
+                       return -ENOMEM;
+       }
+       p = m->op->start(m, &index);
+       while (p) {
+               error = PTR_ERR(p);
+               if (IS_ERR(p))
+                       break;
+               error = m->op->show(m, p);
+               if (error < 0)
+                       break;
+               if (unlikely(error)) {
+                       error = 0;
+                       m->count = 0;
+               }
+               if (m->count == m->size)
+                       goto Eoverflow;
+               if (pos + m->count > offset) {
+                       m->from = offset - pos;
+                       m->count -= m->from;
+                       m->index = index;
+                       break;
+               }
+               pos += m->count;
+               m->count = 0;
+               if (pos == offset) {
+                       index++;
+                       m->index = index;
+                       break;
+               }
+               p = m->op->next(m, p, &index);
+       }
+       m->op->stop(m, p);
+       m->index = index;
+       return error;
+
+Eoverflow:
+       m->op->stop(m, p);
+       kfree(m->buf);
+       m->buf = kmalloc(m->size <<= 1, GFP_KERNEL);
+       return !m->buf ? -ENOMEM : -EAGAIN;
+}
+
 /**
  *     seq_read -      ->read() method for sequential files.
  *     @file: the file to read from
@@ -186,63 +244,6 @@ Efault:
 }
 EXPORT_SYMBOL(seq_read);
 
-static int traverse(struct seq_file *m, loff_t offset)
-{
-       loff_t pos = 0, index;
-       int error = 0;
-       void *p;
-
-       m->version = 0;
-       index = 0;
-       m->count = m->from = 0;
-       if (!offset) {
-               m->index = index;
-               return 0;
-       }
-       if (!m->buf) {
-               m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL);
-               if (!m->buf)
-                       return -ENOMEM;
-       }
-       p = m->op->start(m, &index);
-       while (p) {
-               error = PTR_ERR(p);
-               if (IS_ERR(p))
-                       break;
-               error = m->op->show(m, p);
-               if (error < 0)
-                       break;
-               if (unlikely(error)) {
-                       error = 0;
-                       m->count = 0;
-               }
-               if (m->count == m->size)
-                       goto Eoverflow;
-               if (pos + m->count > offset) {
-                       m->from = offset - pos;
-                       m->count -= m->from;
-                       m->index = index;
-                       break;
-               }
-               pos += m->count;
-               m->count = 0;
-               if (pos == offset) {
-                       index++;
-                       m->index = index;
-                       break;
-               }
-               p = m->op->next(m, p, &index);
-       }
-       m->op->stop(m, p);
-       return error;
-
-Eoverflow:
-       m->op->stop(m, p);
-       kfree(m->buf);
-       m->buf = kmalloc(m->size <<= 1, GFP_KERNEL);
-       return !m->buf ? -ENOMEM : -EAGAIN;
-}
-
 /**
  *     seq_lseek -     ->llseek() method for sequential files.
  *     @file: the file in question
index 175f9c5..f393620 100644 (file)
@@ -689,7 +689,7 @@ long long ubifs_reported_space(const struct ubifs_info *c, long long free)
 }
 
 /**
- * ubifs_get_free_space - return amount of free space.
+ * ubifs_get_free_space_nolock - return amount of free space.
  * @c: UBIFS file-system description object
  *
  * This function calculates amount of free space to report to user-space.
@@ -704,16 +704,14 @@ long long ubifs_reported_space(const struct ubifs_info *c, long long free)
  * traditional file-systems, because they have way less overhead than UBIFS.
  * So, to keep users happy, UBIFS tries to take the overhead into account.
  */
-long long ubifs_get_free_space(struct ubifs_info *c)
+long long ubifs_get_free_space_nolock(struct ubifs_info *c)
 {
-       int min_idx_lebs, rsvd_idx_lebs, lebs;
+       int rsvd_idx_lebs, lebs;
        long long available, outstanding, free;
 
-       spin_lock(&c->space_lock);
-       min_idx_lebs = c->min_idx_lebs;
-       ubifs_assert(min_idx_lebs == ubifs_calc_min_idx_lebs(c));
+       ubifs_assert(c->min_idx_lebs == ubifs_calc_min_idx_lebs(c));
        outstanding = c->budg_data_growth + c->budg_dd_growth;
-       available = ubifs_calc_available(c, min_idx_lebs);
+       available = ubifs_calc_available(c, c->min_idx_lebs);
 
        /*
         * When reporting free space to user-space, UBIFS guarantees that it is
@@ -726,15 +724,14 @@ long long ubifs_get_free_space(struct ubifs_info *c)
         * Note, the calculations below are similar to what we have in
         * 'do_budget_space()', so refer there for comments.
         */
-       if (min_idx_lebs > c->lst.idx_lebs)
-               rsvd_idx_lebs = min_idx_lebs - c->lst.idx_lebs;
+       if (c->min_idx_lebs > c->lst.idx_lebs)
+               rsvd_idx_lebs = c->min_idx_lebs - c->lst.idx_lebs;
        else
                rsvd_idx_lebs = 0;
        lebs = c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt -
               c->lst.taken_empty_lebs;
        lebs -= rsvd_idx_lebs;
        available += lebs * (c->dark_wm - c->leb_overhead);
-       spin_unlock(&c->space_lock);
 
        if (available > outstanding)
                free = ubifs_reported_space(c, available - outstanding);
@@ -742,3 +739,21 @@ long long ubifs_get_free_space(struct ubifs_info *c)
                free = 0;
        return free;
 }
+
+/**
+ * ubifs_get_free_space - return amount of free space.
+ * @c: UBIFS file-system description object
+ *
+ * This function calculates and retuns amount of free space to report to
+ * user-space.
+ */
+long long ubifs_get_free_space(struct ubifs_info *c)
+{
+       long long free;
+
+       spin_lock(&c->space_lock);
+       free = ubifs_get_free_space_nolock(c);
+       spin_unlock(&c->space_lock);
+
+       return free;
+}
index 792c5a1..e975bd8 100644 (file)
@@ -620,9 +620,11 @@ void dbg_dump_budg(struct ubifs_info *c)
               c->dark_wm, c->dead_wm, c->max_idx_node_sz);
        printk(KERN_DEBUG "\tgc_lnum %d, ihead_lnum %d\n",
               c->gc_lnum, c->ihead_lnum);
-       for (i = 0; i < c->jhead_cnt; i++)
-               printk(KERN_DEBUG "\tjhead %d\t LEB %d\n",
-                      c->jheads[i].wbuf.jhead, c->jheads[i].wbuf.lnum);
+       /* If we are in R/O mode, journal heads do not exist */
+       if (c->jheads)
+               for (i = 0; i < c->jhead_cnt; i++)
+                       printk(KERN_DEBUG "\tjhead %d\t LEB %d\n",
+                              c->jheads[i].wbuf.jhead, c->jheads[i].wbuf.lnum);
        for (rb = rb_first(&c->buds); rb; rb = rb_next(rb)) {
                bud = rb_entry(rb, struct ubifs_bud, rb);
                printk(KERN_DEBUG "\tbud LEB %d\n", bud->lnum);
@@ -637,10 +639,7 @@ void dbg_dump_budg(struct ubifs_info *c)
        /* Print budgeting predictions */
        available = ubifs_calc_available(c, c->min_idx_lebs);
        outstanding = c->budg_data_growth + c->budg_dd_growth;
-       if (available > outstanding)
-               free = ubifs_reported_space(c, available - outstanding);
-       else
-               free = 0;
+       free = ubifs_get_free_space_nolock(c);
        printk(KERN_DEBUG "Budgeting predictions:\n");
        printk(KERN_DEBUG "\tavailable: %lld, outstanding %lld, free %lld\n",
               available, outstanding, free);
@@ -860,6 +859,65 @@ void dbg_dump_index(struct ubifs_info *c)
        dbg_walk_index(c, NULL, dump_znode, NULL);
 }
 
+/**
+ * dbg_save_space_info - save information about flash space.
+ * @c: UBIFS file-system description object
+ *
+ * This function saves information about UBIFS free space, dirty space, etc, in
+ * order to check it later.
+ */
+void dbg_save_space_info(struct ubifs_info *c)
+{
+       struct ubifs_debug_info *d = c->dbg;
+
+       ubifs_get_lp_stats(c, &d->saved_lst);
+
+       spin_lock(&c->space_lock);
+       d->saved_free = ubifs_get_free_space_nolock(c);
+       spin_unlock(&c->space_lock);
+}
+
+/**
+ * dbg_check_space_info - check flash space information.
+ * @c: UBIFS file-system description object
+ *
+ * This function compares current flash space information with the information
+ * which was saved when the 'dbg_save_space_info()' function was called.
+ * Returns zero if the information has not changed, and %-EINVAL it it has
+ * changed.
+ */
+int dbg_check_space_info(struct ubifs_info *c)
+{
+       struct ubifs_debug_info *d = c->dbg;
+       struct ubifs_lp_stats lst;
+       long long avail, free;
+
+       spin_lock(&c->space_lock);
+       avail = ubifs_calc_available(c, c->min_idx_lebs);
+       spin_unlock(&c->space_lock);
+       free = ubifs_get_free_space(c);
+
+       if (free != d->saved_free) {
+               ubifs_err("free space changed from %lld to %lld",
+                         d->saved_free, free);
+               goto out;
+       }
+
+       return 0;
+
+out:
+       ubifs_msg("saved lprops statistics dump");
+       dbg_dump_lstats(&d->saved_lst);
+       ubifs_get_lp_stats(c, &lst);
+       ubifs_msg("current lprops statistics dump");
+       dbg_dump_lstats(&d->saved_lst);
+       spin_lock(&c->space_lock);
+       dbg_dump_budg(c);
+       spin_unlock(&c->space_lock);
+       dump_stack();
+       return -EINVAL;
+}
+
 /**
  * dbg_check_synced_i_size - check synchronized inode size.
  * @inode: inode to check
@@ -1349,7 +1407,7 @@ int dbg_check_tnc(struct ubifs_info *c, int extra)
  * @c: UBIFS file-system description object
  * @leaf_cb: called for each leaf node
  * @znode_cb: called for each indexing node
- * @priv: private date which is passed to callbacks
+ * @priv: private data which is passed to callbacks
  *
  * This function walks the UBIFS index and calls the @leaf_cb for each leaf
  * node and @znode_cb for each indexing node. Returns zero in case of success
@@ -2409,7 +2467,7 @@ void ubifs_debugging_exit(struct ubifs_info *c)
  * Root directory for UBIFS stuff in debugfs. Contains sub-directories which
  * contain the stuff specific to particular file-system mounts.
  */
-static struct dentry *debugfs_rootdir;
+static struct dentry *dfs_rootdir;
 
 /**
  * dbg_debugfs_init - initialize debugfs file-system.
@@ -2421,9 +2479,9 @@ static struct dentry *debugfs_rootdir;
  */
 int dbg_debugfs_init(void)
 {
-       debugfs_rootdir = debugfs_create_dir("ubifs", NULL);
-       if (IS_ERR(debugfs_rootdir)) {
-               int err = PTR_ERR(debugfs_rootdir);
+       dfs_rootdir = debugfs_create_dir("ubifs", NULL);
+       if (IS_ERR(dfs_rootdir)) {
+               int err = PTR_ERR(dfs_rootdir);
                ubifs_err("cannot create \"ubifs\" debugfs directory, "
                          "error %d\n", err);
                return err;
@@ -2437,7 +2495,7 @@ int dbg_debugfs_init(void)
  */
 void dbg_debugfs_exit(void)
 {
-       debugfs_remove(debugfs_rootdir);
+       debugfs_remove(dfs_rootdir);
 }
 
 static int open_debugfs_file(struct inode *inode, struct file *file)
@@ -2452,13 +2510,13 @@ static ssize_t write_debugfs_file(struct file *file, const char __user *buf,
        struct ubifs_info *c = file->private_data;
        struct ubifs_debug_info *d = c->dbg;
 
-       if (file->f_path.dentry == d->dump_lprops)
+       if (file->f_path.dentry == d->dfs_dump_lprops)
                dbg_dump_lprops(c);
-       else if (file->f_path.dentry == d->dump_budg) {
+       else if (file->f_path.dentry == d->dfs_dump_budg) {
                spin_lock(&c->space_lock);
                dbg_dump_budg(c);
                spin_unlock(&c->space_lock);
-       } else if (file->f_path.dentry == d->dump_tnc) {
+       } else if (file->f_path.dentry == d->dfs_dump_tnc) {
                mutex_lock(&c->tnc_mutex);
                dbg_dump_tnc(c);
                mutex_unlock(&c->tnc_mutex);
@@ -2469,7 +2527,7 @@ static ssize_t write_debugfs_file(struct file *file, const char __user *buf,
        return count;
 }
 
-static const struct file_operations debugfs_fops = {
+static const struct file_operations dfs_fops = {
        .open = open_debugfs_file,
        .write = write_debugfs_file,
        .owner = THIS_MODULE,
@@ -2494,36 +2552,32 @@ int dbg_debugfs_init_fs(struct ubifs_info *c)
        struct dentry *dent;
        struct ubifs_debug_info *d = c->dbg;
 
-       sprintf(d->debugfs_dir_name, "ubi%d_%d", c->vi.ubi_num, c->vi.vol_id);
-       d->debugfs_dir = debugfs_create_dir(d->debugfs_dir_name,
-                                             debugfs_rootdir);
-       if (IS_ERR(d->debugfs_dir)) {
-               err = PTR_ERR(d->debugfs_dir);
+       sprintf(d->dfs_dir_name, "ubi%d_%d", c->vi.ubi_num, c->vi.vol_id);
+       d->dfs_dir = debugfs_create_dir(d->dfs_dir_name, dfs_rootdir);
+       if (IS_ERR(d->dfs_dir)) {
+               err = PTR_ERR(d->dfs_dir);
                ubifs_err("cannot create \"%s\" debugfs directory, error %d\n",
-                         d->debugfs_dir_name, err);
+                         d->dfs_dir_name, err);
                goto out;
        }
 
        fname = "dump_lprops";
-       dent = debugfs_create_file(fname, S_IWUGO, d->debugfs_dir, c,
-                                  &debugfs_fops);
+       dent = debugfs_create_file(fname, S_IWUGO, d->dfs_dir, c, &dfs_fops);
        if (IS_ERR(dent))
                goto out_remove;
-       d->dump_lprops = dent;
+       d->dfs_dump_lprops = dent;
 
        fname = "dump_budg";
-       dent = debugfs_create_file(fname, S_IWUGO, d->debugfs_dir, c,
-                                  &debugfs_fops);
+       dent = debugfs_create_file(fname, S_IWUGO, d->dfs_dir, c, &dfs_fops);
        if (IS_ERR(dent))
                goto out_remove;
-       d->dump_budg = dent;
+       d->dfs_dump_budg = dent;
 
        fname = "dump_tnc";
-       dent = debugfs_create_file(fname, S_IWUGO, d->debugfs_dir, c,
-                                  &debugfs_fops);
+       dent = debugfs_create_file(fname, S_IWUGO, d->dfs_dir, c, &dfs_fops);
        if (IS_ERR(dent))
                goto out_remove;
-       d->dump_tnc = dent;
+       d->dfs_dump_tnc = dent;
 
        return 0;
 
@@ -2531,7 +2585,7 @@ out_remove:
        err = PTR_ERR(dent);
        ubifs_err("cannot create \"%s\" debugfs directory, error %d\n",
                  fname, err);
-       debugfs_remove_recursive(d->debugfs_dir);
+       debugfs_remove_recursive(d->dfs_dir);
 out:
        return err;
 }
@@ -2542,7 +2596,7 @@ out:
  */
 void dbg_debugfs_exit_fs(struct ubifs_info *c)
 {
-       debugfs_remove_recursive(c->dbg->debugfs_dir);
+       debugfs_remove_recursive(c->dbg->dfs_dir);
 }
 
 #endif /* CONFIG_UBIFS_FS_DEBUG */
index 9820d69..c1cd73b 100644 (file)
  * @chk_lpt_wastage: used by LPT tree size checker
  * @chk_lpt_lebs: used by LPT tree size checker
  * @new_nhead_offs: used by LPT tree size checker
- * @new_ihead_lnum: used by debugging to check ihead_lnum
- * @new_ihead_offs: used by debugging to check ihead_offs
+ * @new_ihead_lnum: used by debugging to check @c->ihead_lnum
+ * @new_ihead_offs: used by debugging to check @c->ihead_offs
  *
- * debugfs_dir_name: name of debugfs directory containing this file-system's
- *                   files
- * debugfs_dir: direntry object of the file-system debugfs directory
- * dump_lprops: "dump lprops" debugfs knob
- * dump_budg: "dump budgeting information" debugfs knob
- * dump_tnc: "dump TNC" debugfs knob
+ * @saved_lst: saved lprops statistics (used by 'dbg_save_space_info()')
+ * @saved_free: saved free space (used by 'dbg_save_space_info()')
+ *
+ * dfs_dir_name: name of debugfs directory containing this file-system's files
+ * dfs_dir: direntry object of the file-system debugfs directory
+ * dfs_dump_lprops: "dump lprops" debugfs knob
+ * dfs_dump_budg: "dump budgeting information" debugfs knob
+ * dfs_dump_tnc: "dump TNC" debugfs knob
  */
 struct ubifs_debug_info {
        void *buf;
@@ -69,11 +71,14 @@ struct ubifs_debug_info {
        int new_ihead_lnum;
        int new_ihead_offs;
 
-       char debugfs_dir_name[100];
-       struct dentry *debugfs_dir;
-       struct dentry *dump_lprops;
-       struct dentry *dump_budg;
-       struct dentry *dump_tnc;
+       struct ubifs_lp_stats saved_lst;
+       long long saved_free;
+
+       char dfs_dir_name[100];
+       struct dentry *dfs_dir;
+       struct dentry *dfs_dump_lprops;
+       struct dentry *dfs_dump_budg;
+       struct dentry *dfs_dump_tnc;
 };
 
 #define ubifs_assert(expr) do {                                                \
@@ -297,7 +302,8 @@ int dbg_walk_index(struct ubifs_info *c, dbg_leaf_callback leaf_cb,
                   dbg_znode_callback znode_cb, void *priv);
 
 /* Checking functions */
-
+void dbg_save_space_info(struct ubifs_info *c);
+int dbg_check_space_info(struct ubifs_info *c);
 int dbg_check_lprops(struct ubifs_info *c);
 int dbg_old_index_check_init(struct ubifs_info *c, struct ubifs_zbranch *zroot);
 int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot);
@@ -439,6 +445,8 @@ void dbg_debugfs_exit_fs(struct ubifs_info *c);
 
 #define dbg_walk_index(c, leaf_cb, znode_cb, priv) 0
 #define dbg_old_index_check_init(c, zroot)         0
+#define dbg_save_space_info(c)                     ({})
+#define dbg_check_space_info(c)                    0
 #define dbg_check_old_index(c, zroot)              0
 #define dbg_check_cats(c)                          0
 #define dbg_check_ltab(c)                          0
index f448ab1..f55d523 100644 (file)
@@ -482,30 +482,29 @@ static int ubifs_dir_release(struct inode *dir, struct file *file)
 }
 
 /**
- * lock_2_inodes - lock two UBIFS inodes.
+ * lock_2_inodes - a wrapper for locking two UBIFS inodes.
  * @inode1: first inode
  * @inode2: second inode
+ *
+ * We do not implement any tricks to guarantee strict lock ordering, because
+ * VFS has already done it for us on the @i_mutex. So this is just a simple
+ * wrapper function.
  */
 static void lock_2_inodes(struct inode *inode1, struct inode *inode2)
 {
-       if (inode1->i_ino < inode2->i_ino) {
-               mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_2);
-               mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_3);
-       } else {
-               mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_2);
-               mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_3);
-       }
+       mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_1);
+       mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_2);
 }
 
 /**
- * unlock_2_inodes - unlock two UBIFS inodes inodes.
+ * unlock_2_inodes - a wrapper for unlocking two UBIFS inodes.
  * @inode1: first inode
  * @inode2: second inode
  */
 static void unlock_2_inodes(struct inode *inode1, struct inode *inode2)
 {
-       mutex_unlock(&ubifs_inode(inode1)->ui_mutex);
        mutex_unlock(&ubifs_inode(inode2)->ui_mutex);
+       mutex_unlock(&ubifs_inode(inode1)->ui_mutex);
 }
 
 static int ubifs_link(struct dentry *old_dentry, struct inode *dir,
@@ -527,6 +526,8 @@ static int ubifs_link(struct dentry *old_dentry, struct inode *dir,
        dbg_gen("dent '%.*s' to ino %lu (nlink %d) in dir ino %lu",
                dentry->d_name.len, dentry->d_name.name, inode->i_ino,
                inode->i_nlink, dir->i_ino);
+       ubifs_assert(mutex_is_locked(&dir->i_mutex));
+       ubifs_assert(mutex_is_locked(&inode->i_mutex));
        err = dbg_check_synced_i_size(inode);
        if (err)
                return err;
@@ -580,6 +581,8 @@ static int ubifs_unlink(struct inode *dir, struct dentry *dentry)
        dbg_gen("dent '%.*s' from ino %lu (nlink %d) in dir ino %lu",
                dentry->d_name.len, dentry->d_name.name, inode->i_ino,
                inode->i_nlink, dir->i_ino);
+       ubifs_assert(mutex_is_locked(&dir->i_mutex));
+       ubifs_assert(mutex_is_locked(&inode->i_mutex));
        err = dbg_check_synced_i_size(inode);
        if (err)
                return err;
@@ -667,7 +670,8 @@ static int ubifs_rmdir(struct inode *dir, struct dentry *dentry)
 
        dbg_gen("directory '%.*s', ino %lu in dir ino %lu", dentry->d_name.len,
                dentry->d_name.name, inode->i_ino, dir->i_ino);
-
+       ubifs_assert(mutex_is_locked(&dir->i_mutex));
+       ubifs_assert(mutex_is_locked(&inode->i_mutex));
        err = check_dir_empty(c, dentry->d_inode);
        if (err)
                return err;
@@ -922,59 +926,30 @@ out_budg:
 }
 
 /**
- * lock_3_inodes - lock three UBIFS inodes for rename.
+ * lock_3_inodes - a wrapper for locking three UBIFS inodes.
  * @inode1: first inode
  * @inode2: second inode
  * @inode3: third inode
  *
- * For 'ubifs_rename()', @inode1 may be the same as @inode2 whereas @inode3 may
- * be null.
+ * This function is used for 'ubifs_rename()' and @inode1 may be the same as
+ * @inode2 whereas @inode3 may be %NULL.
+ *
+ * We do not implement any tricks to guarantee strict lock ordering, because
+ * VFS has already done it for us on the @i_mutex. So this is just a simple
+ * wrapper function.
  */
 static void lock_3_inodes(struct inode *inode1, struct inode *inode2,
                          struct inode *inode3)
 {
-       struct inode *i1, *i2, *i3;
-
-       if (!inode3) {
-               if (inode1 != inode2) {
-                       lock_2_inodes(inode1, inode2);
-                       return;
-               }
-               mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_1);
-               return;
-       }
-
-       if (inode1 == inode2) {
-               lock_2_inodes(inode1, inode3);
-               return;
-       }
-
-       /* 3 different inodes */
-       if (inode1 < inode2) {
-               i3 = inode2;
-               if (inode1 < inode3) {
-                       i1 = inode1;
-                       i2 = inode3;
-               } else {
-                       i1 = inode3;
-                       i2 = inode1;
-               }
-       } else {
-               i3 = inode1;
-               if (inode2 < inode3) {
-                       i1 = inode2;
-                       i2 = inode3;
-               } else {
-                       i1 = inode3;
-                       i2 = inode2;
-               }
-       }
-       mutex_lock_nested(&ubifs_inode(i1)->ui_mutex, WB_MUTEX_1);
-       lock_2_inodes(i2, i3);
+       mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_1);
+       if (inode2 != inode1)
+               mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_2);
+       if (inode3)
+               mutex_lock_nested(&ubifs_inode(inode3)->ui_mutex, WB_MUTEX_3);
 }
 
 /**
- * unlock_3_inodes - unlock three UBIFS inodes for rename.
+ * unlock_3_inodes - a wrapper for unlocking three UBIFS inodes for rename.
  * @inode1: first inode
  * @inode2: second inode
  * @inode3: third inode
@@ -982,11 +957,11 @@ static void lock_3_inodes(struct inode *inode1, struct inode *inode2,
 static void unlock_3_inodes(struct inode *inode1, struct inode *inode2,
                            struct inode *inode3)
 {
-       mutex_unlock(&ubifs_inode(inode1)->ui_mutex);
-       if (inode1 != inode2)
-               mutex_unlock(&ubifs_inode(inode2)->ui_mutex);
        if (inode3)
                mutex_unlock(&ubifs_inode(inode3)->ui_mutex);
+       if (inode1 != inode2)
+               mutex_unlock(&ubifs_inode(inode2)->ui_mutex);
+       mutex_unlock(&ubifs_inode(inode1)->ui_mutex);
 }
 
 static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry,
@@ -1020,6 +995,11 @@ static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry,
                "dir ino %lu", old_dentry->d_name.len, old_dentry->d_name.name,
                old_inode->i_ino, old_dir->i_ino, new_dentry->d_name.len,
                new_dentry->d_name.name, new_dir->i_ino);
+       ubifs_assert(mutex_is_locked(&old_dir->i_mutex));
+       ubifs_assert(mutex_is_locked(&new_dir->i_mutex));
+       if (unlink)
+               ubifs_assert(mutex_is_locked(&new_inode->i_mutex));
+
 
        if (unlink && is_dir) {
                err = check_dir_empty(c, new_inode);
@@ -1199,7 +1179,7 @@ int ubifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
        return 0;
 }
 
-struct inode_operations ubifs_dir_inode_operations = {
+const struct inode_operations ubifs_dir_inode_operations = {
        .lookup      = ubifs_lookup,
        .create      = ubifs_create,
        .link        = ubifs_link,
@@ -1219,7 +1199,7 @@ struct inode_operations ubifs_dir_inode_operations = {
 #endif
 };
 
-struct file_operations ubifs_dir_operations = {
+const struct file_operations ubifs_dir_operations = {
        .llseek         = ubifs_dir_llseek,
        .release        = ubifs_dir_release,
        .read           = generic_read_dir,
index bf37374..93b6de5 100644 (file)
@@ -432,7 +432,6 @@ static int ubifs_write_begin(struct file *file, struct address_space *mapping,
        int uninitialized_var(err), appending = !!(pos + len > inode->i_size);
        struct page *page;
 
-
        ubifs_assert(ubifs_inode(inode)->ui_size == inode->i_size);
 
        if (unlikely(c->ro_media))
@@ -1541,7 +1540,7 @@ static int ubifs_file_mmap(struct file *file, struct vm_area_struct *vma)
        return 0;
 }
 
-struct address_space_operations ubifs_file_address_operations = {
+const struct address_space_operations ubifs_file_address_operations = {
        .readpage       = ubifs_readpage,
        .writepage      = ubifs_writepage,
        .write_begin    = ubifs_write_begin,
@@ -1551,7 +1550,7 @@ struct address_space_operations ubifs_file_address_operations = {
        .releasepage    = ubifs_releasepage,
 };
 
-struct inode_operations ubifs_file_inode_operations = {
+const struct inode_operations ubifs_file_inode_operations = {
        .setattr     = ubifs_setattr,
        .getattr     = ubifs_getattr,
 #ifdef CONFIG_UBIFS_FS_XATTR
@@ -1562,14 +1561,14 @@ struct inode_operations ubifs_file_inode_operations = {
 #endif
 };
 
-struct inode_operations ubifs_symlink_inode_operations = {
+const struct inode_operations ubifs_symlink_inode_operations = {
        .readlink    = generic_readlink,
        .follow_link = ubifs_follow_link,
        .setattr     = ubifs_setattr,
        .getattr     = ubifs_getattr,
 };
 
-struct file_operations ubifs_file_operations = {
+const struct file_operations ubifs_file_operations = {
        .llseek         = generic_file_llseek,
        .read           = do_sync_read,
        .write          = do_sync_write,
index 9832f9a..a711d33 100644 (file)
  * to be reused. Garbage collection will cause the number of dirty index nodes
  * to grow, however sufficient space is reserved for the index to ensure the
  * commit will never run out of space.
+ *
+ * Notes about dead watermark. At current UBIFS implementation we assume that
+ * LEBs which have less than @c->dead_wm bytes of free + dirty space are full
+ * and not worth garbage-collecting. The dead watermark is one min. I/O unit
+ * size, or min. UBIFS node size, depending on what is greater. Indeed, UBIFS
+ * Garbage Collector has to synchronize the GC head's write buffer before
+ * returning, so this is about wasting one min. I/O unit. However, UBIFS GC can
+ * actually reclaim even very small pieces of dirty space by garbage collecting
+ * enough dirty LEBs, but we do not bother doing this at this implementation.
+ *
+ * Notes about dark watermark. The results of GC work depends on how big are
+ * the UBIFS nodes GC deals with. Large nodes make GC waste more space. Indeed,
+ * if GC move data from LEB A to LEB B and nodes in LEB A are large, GC would
+ * have to waste large pieces of free space at the end of LEB B, because nodes
+ * from LEB A would not fit. And the worst situation is when all nodes are of
+ * maximum size. So dark watermark is the amount of free + dirty space in LEB
+ * which are guaranteed to be reclaimable. If LEB has less space, the GC migh
+ * be unable to reclaim it. So, LEBs with free + dirty greater than dark
+ * watermark are "good" LEBs from GC's point of few. The other LEBs are not so
+ * good, and GC takes extra care when moving them.
  */
 
 #include <linux/pagemap.h>
@@ -381,7 +401,7 @@ int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp)
 
                /*
                 * Don't release the LEB until after the next commit, because
-                * it may contain date which is needed for recovery. So
+                * it may contain data which is needed for recovery. So
                 * although we freed this LEB, it will become usable only after
                 * the commit.
                 */
@@ -810,8 +830,9 @@ out:
  * ubifs_destroy_idx_gc - destroy idx_gc list.
  * @c: UBIFS file-system description object
  *
- * This function destroys the idx_gc list. It is called when unmounting or
- * remounting read-only so locks are not needed.
+ * This function destroys the @c->idx_gc list. It is called when unmounting
+ * so locks are not needed. Returns zero in case of success and a negative
+ * error code in case of failure.
  */
 void ubifs_destroy_idx_gc(struct ubifs_info *c)
 {
@@ -824,7 +845,6 @@ void ubifs_destroy_idx_gc(struct ubifs_info *c)
                list_del(&idx_gc->list);
                kfree(idx_gc);
        }
-
 }
 
 /**
index 0168271..e8e632a 100644 (file)
@@ -29,7 +29,7 @@
  * would have been wasted for padding to the nearest minimal I/O unit boundary.
  * Instead, data first goes to the write-buffer and is flushed when the
  * buffer is full or when it is not used for some time (by timer). This is
- * similarto the mechanism is used by JFFS2.
+ * similar to the mechanism is used by JFFS2.
  *
  * Write-buffers are defined by 'struct ubifs_wbuf' objects and protected by
  * mutexes defined inside these objects. Since sometimes upper-level code
@@ -75,7 +75,7 @@ void ubifs_ro_mode(struct ubifs_info *c, int err)
  * @lnum: logical eraseblock number
  * @offs: offset within the logical eraseblock
  * @quiet: print no messages
- * @chk_crc: indicates whether to always check the CRC
+ * @must_chk_crc: indicates whether to always check the CRC
  *
  * This function checks node magic number and CRC checksum. This function also
  * validates node length to prevent UBIFS from becoming crazy when an attacker
@@ -83,11 +83,17 @@ void ubifs_ro_mode(struct ubifs_info *c, int err)
  * node length in the common header could cause UBIFS to read memory outside of
  * allocated buffer when checking the CRC checksum.
  *
- * This function returns zero in case of success %-EUCLEAN in case of bad CRC
- * or magic.
+ * This function may skip data nodes CRC checking if @c->no_chk_data_crc is
+ * true, which is controlled by corresponding UBIFS mount option. However, if
+ * @must_chk_crc is true, then @c->no_chk_data_crc is ignored and CRC is
+ * checked. Similarly, if @c->always_chk_crc is true, @c->no_chk_data_crc is
+ * ignored and CRC is checked.
+ *
+ * This function returns zero in case of success and %-EUCLEAN in case of bad
+ * CRC or magic.
  */
 int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum,
-                    int offs, int quiet, int chk_crc)
+                    int offs, int quiet, int must_chk_crc)
 {
        int err = -EINVAL, type, node_len;
        uint32_t crc, node_crc, magic;
@@ -123,9 +129,9 @@ int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum,
                   node_len > c->ranges[type].max_len)
                goto out_len;
 
-       if (!chk_crc && type == UBIFS_DATA_NODE && !c->always_chk_crc)
-               if (c->no_chk_data_crc)
-                       return 0;
+       if (!must_chk_crc && type == UBIFS_DATA_NODE && !c->always_chk_crc &&
+            c->no_chk_data_crc)
+               return 0;
 
        crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8);
        node_crc = le32_to_cpu(ch->crc);
index 9b7c54e..a11ca09 100644 (file)
@@ -208,7 +208,7 @@ again:
        offs = 0;
 
 out:
-       err = ubifs_wbuf_seek_nolock(wbuf, lnum, offs, UBI_SHORTTERM);
+       err = ubifs_wbuf_seek_nolock(wbuf, lnum, offs, wbuf->dtype);
        if (err)
                goto out_unlock;
 
index dfd2bce..4cdd284 100644 (file)
@@ -635,10 +635,10 @@ const struct ubifs_lprops *ubifs_change_lp(struct ubifs_info *c,
  * @c: UBIFS file-system description object
  * @st: return statistics
  */
-void ubifs_get_lp_stats(struct ubifs_info *c, struct ubifs_lp_stats *st)
+void ubifs_get_lp_stats(struct ubifs_info *c, struct ubifs_lp_stats *lst)
 {
        spin_lock(&c->space_lock);
-       memcpy(st, &c->lst, sizeof(struct ubifs_lp_stats));
+       memcpy(lst, &c->lst, sizeof(struct ubifs_lp_stats));
        spin_unlock(&c->space_lock);
 }
 
@@ -678,6 +678,9 @@ int ubifs_change_one_lp(struct ubifs_info *c, int lnum, int free, int dirty,
 
 out:
        ubifs_release_lprops(c);
+       if (err)
+               ubifs_err("cannot change properties of LEB %d, error %d",
+                         lnum, err);
        return err;
 }
 
@@ -714,6 +717,9 @@ int ubifs_update_one_lp(struct ubifs_info *c, int lnum, int free, int dirty,
 
 out:
        ubifs_release_lprops(c);
+       if (err)
+               ubifs_err("cannot update properties of LEB %d, error %d",
+                         lnum, err);
        return err;
 }
 
@@ -737,6 +743,8 @@ int ubifs_read_one_lp(struct ubifs_info *c, int lnum, struct ubifs_lprops *lp)
        lpp = ubifs_lpt_lookup(c, lnum);
        if (IS_ERR(lpp)) {
                err = PTR_ERR(lpp);
+               ubifs_err("cannot read properties of LEB %d, error %d",
+                         lnum, err);
                goto out;
        }
 
index 96ca957..3216a1f 100644 (file)
@@ -556,23 +556,23 @@ no_space:
 }
 
 /**
- * next_pnode - find next pnode.
+ * next_pnode_to_dirty - find next pnode to dirty.
  * @c: UBIFS file-system description object
  * @pnode: pnode
  *
- * This function returns the next pnode or %NULL if there are no more pnodes.
+ * This function returns the next pnode to dirty or %NULL if there are no more
+ * pnodes.  Note that pnodes that have never been written (lnum == 0) are
+ * skipped.
  */
-static struct ubifs_pnode *next_pnode(struct ubifs_info *c,
-                                     struct ubifs_pnode *pnode)
+static struct ubifs_pnode *next_pnode_to_dirty(struct ubifs_info *c,
+                                              struct ubifs_pnode *pnode)
 {
        struct ubifs_nnode *nnode;
        int iip;
 
        /* Try to go right */
        nnode = pnode->parent;
-       iip = pnode->iip + 1;
-       if (iip < UBIFS_LPT_FANOUT) {
-               /* We assume here that LEB zero is never an LPT LEB */
+       for (iip = pnode->iip + 1; iip < UBIFS_LPT_FANOUT; iip++) {
                if (nnode->nbranch[iip].lnum)
                        return ubifs_get_pnode(c, nnode, iip);
        }
@@ -583,8 +583,11 @@ static struct ubifs_pnode *next_pnode(struct ubifs_info *c,
                nnode = nnode->parent;
                if (!nnode)
                        return NULL;
-               /* We assume here that LEB zero is never an LPT LEB */
-       } while (iip >= UBIFS_LPT_FANOUT || !nnode->nbranch[iip].lnum);
+               for (; iip < UBIFS_LPT_FANOUT; iip++) {
+                       if (nnode->nbranch[iip].lnum)
+                               break;
+               }
+       } while (iip >= UBIFS_LPT_FANOUT);
 
        /* Go right */
        nnode = ubifs_get_nnode(c, nnode, iip);
@@ -593,12 +596,29 @@ static struct ubifs_pnode *next_pnode(struct ubifs_info *c,
 
        /* Go down to level 1 */
        while (nnode->level > 1) {
-               nnode = ubifs_get_nnode(c, nnode, 0);
+               for (iip = 0; iip < UBIFS_LPT_FANOUT; iip++) {
+                       if (nnode->nbranch[iip].lnum)
+                               break;
+               }
+               if (iip >= UBIFS_LPT_FANOUT) {
+                       /*
+                        * Should not happen, but we need to keep going
+                        * if it does.
+                        */
+                       iip = 0;
+               }
+               nnode = ubifs_get_nnode(c, nnode, iip);
                if (IS_ERR(nnode))
                        return (void *)nnode;
        }
 
-       return ubifs_get_pnode(c, nnode, 0);
+       for (iip = 0; iip < UBIFS_LPT_FANOUT; iip++)
+               if (nnode->nbranch[iip].lnum)
+                       break;
+       if (iip >= UBIFS_LPT_FANOUT)
+               /* Should not happen, but we need to keep going if it does */
+               iip = 0;
+       return ubifs_get_pnode(c, nnode, iip);
 }
 
 /**
@@ -688,7 +708,7 @@ static int make_tree_dirty(struct ubifs_info *c)
        pnode = pnode_lookup(c, 0);
        while (pnode) {
                do_make_pnode_dirty(c, pnode);
-               pnode = next_pnode(c, pnode);
+               pnode = next_pnode_to_dirty(c, pnode);
                if (IS_ERR(pnode))
                        return PTR_ERR(pnode);
        }
index 71d5493..a88f338 100644 (file)
@@ -354,7 +354,7 @@ int ubifs_write_master(struct ubifs_info *c)
        int err, lnum, offs, len;
 
        if (c->ro_media)
-               return -EINVAL;
+               return -EROFS;
 
        lnum = UBIFS_MST_LNUM;
        offs = c->mst_offs + c->mst_node_alsz;
index 9e6f403..152a7b3 100644 (file)
@@ -46,7 +46,7 @@
  * Orphans are accumulated in a rb-tree. When an inode's link count drops to
  * zero, the inode number is added to the rb-tree. It is removed from the tree
  * when the inode is deleted.  Any new orphans that are in the orphan tree when
- * the commit is run, are written to the orphan area in 1 or more orph nodes.
+ * the commit is run, are written to the orphan area in 1 or more orphan nodes.
  * If the orphan area is full, it is consolidated to make space.  There is
  * always enough space because validation prevents the user from creating more
  * than the maximum number of orphans allowed.
@@ -231,7 +231,7 @@ static int tot_avail_orphs(struct ubifs_info *c)
 }
 
 /**
- * do_write_orph_node - write a node
+ * do_write_orph_node - write a node to the orphan head.
  * @c: UBIFS file-system description object
  * @len: length of node
  * @atomic: write atomically
@@ -264,11 +264,11 @@ static int do_write_orph_node(struct ubifs_info *c, int len, int atomic)
 }
 
 /**
- * write_orph_node - write an orph node
+ * write_orph_node - write an orphan node.
  * @c: UBIFS file-system description object
  * @atomic: write atomically
  *
- * This function builds an orph node from the cnext list and writes it to the
+ * This function builds an orphan node from the cnext list and writes it to the
  * orphan head. On success, %0 is returned, otherwise a negative error code
  * is returned.
  */
@@ -326,11 +326,11 @@ static int write_orph_node(struct ubifs_info *c, int atomic)
 }
 
 /**
- * write_orph_nodes - write orph nodes until there are no more to commit
+ * write_orph_nodes - write orphan nodes until there are no more to commit.
  * @c: UBIFS file-system description object
  * @atomic: write atomically
  *
- * This function writes orph nodes for all the orphans to commit. On success,
+ * This function writes orphan nodes for all the orphans to commit. On success,
  * %0 is returned, otherwise a negative error code is returned.
  */
 static int write_orph_nodes(struct ubifs_info *c, int atomic)
@@ -478,14 +478,14 @@ int ubifs_orphan_end_commit(struct ubifs_info *c)
 }
 
 /**
- * clear_orphans - erase all LEBs used for orphans.
+ * ubifs_clear_orphans - erase all LEBs used for orphans.
  * @c: UBIFS file-system description object
  *
  * If recovery is not required, then the orphans from the previous session
  * are not needed. This function locates the LEBs used to record
  * orphans, and un-maps them.
  */
-static int clear_orphans(struct ubifs_info *c)
+int ubifs_clear_orphans(struct ubifs_info *c)
 {
        int lnum, err;
 
@@ -547,9 +547,9 @@ static int insert_dead_orphan(struct ubifs_info *c, ino_t inum)
  * do_kill_orphans - remove orphan inodes from the index.
  * @c: UBIFS file-system description object
  * @sleb: scanned LEB
- * @last_cmt_no: cmt_no of last orph node read is passed and returned here
+ * @last_cmt_no: cmt_no of last orphan node read is passed and returned here
  * @outofdate: whether the LEB is out of date is returned here
- * @last_flagged: whether the end orph node is encountered
+ * @last_flagged: whether the end orphan node is encountered
  *
  * This function is a helper to the 'kill_orphans()' function. It goes through
  * every orphan node in a LEB and for every inode number recorded, removes
@@ -580,8 +580,8 @@ static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
                /*
                 * The commit number on the master node may be less, because
                 * of a failed commit. If there are several failed commits in a
-                * row, the commit number written on orph nodes will continue to
-                * increase (because the commit number is adjusted here) even
+                * row, the commit number written on orphan nodes will continue
+                * to increase (because the commit number is adjusted here) even
                 * though the commit number on the master node stays the same
                 * because the master node has not been re-written.
                 */
@@ -589,9 +589,9 @@ static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
                        c->cmt_no = cmt_no;
                if (cmt_no < *last_cmt_no && *last_flagged) {
                        /*
-                        * The last orph node had a higher commit number and was
-                        * flagged as the last written for that commit number.
-                        * That makes this orph node, out of date.
+                        * The last orphan node had a higher commit number and
+                        * was flagged as the last written for that commit
+                        * number. That makes this orphan node, out of date.
                         */
                        if (!first) {
                                ubifs_err("out of order commit number %llu in "
@@ -658,10 +658,10 @@ static int kill_orphans(struct ubifs_info *c)
        /*
         * Orph nodes always start at c->orph_first and are written to each
         * successive LEB in turn. Generally unused LEBs will have been unmapped
-        * but may contain out of date orph nodes if the unmap didn't go
-        * through. In addition, the last orph node written for each commit is
+        * but may contain out of date orphan nodes if the unmap didn't go
+        * through. In addition, the last orphan node written for each commit is
         * marked (top bit of orph->cmt_no is set to 1). It is possible that
-        * there are orph nodes from the next commit (i.e. the commit did not
+        * there are orphan nodes from the next commit (i.e. the commit did not
         * complete successfully). In that case, no orphans will have been lost
         * due to the way that orphans are written, and any orphans added will
         * be valid orphans anyway and so can be deleted.
@@ -718,7 +718,7 @@ int ubifs_mount_orphans(struct ubifs_info *c, int unclean, int read_only)
        if (unclean)
                err = kill_orphans(c);
        else if (!read_only)
-               err = clear_orphans(c);
+               err = ubifs_clear_orphans(c);
 
        return err;
 }
index 89556ee..1182b66 100644 (file)
@@ -397,6 +397,7 @@ static int ubifs_statfs(struct dentry *dentry, struct kstatfs *buf)
        buf->f_namelen = UBIFS_MAX_NLEN;
        buf->f_fsid.val[0] = le32_to_cpu(uuid[0]) ^ le32_to_cpu(uuid[2]);
        buf->f_fsid.val[1] = le32_to_cpu(uuid[1]) ^ le32_to_cpu(uuid[3]);
+       ubifs_assert(buf->f_bfree <= c->block_cnt);
        return 0;
 }
 
@@ -432,32 +433,23 @@ static int ubifs_sync_fs(struct super_block *sb, int wait)
        int i, err;
        struct ubifs_info *c = sb->s_fs_info;
        struct writeback_control wbc = {
-               .sync_mode   = wait ? WB_SYNC_ALL : WB_SYNC_NONE,
+               .sync_mode   = WB_SYNC_ALL,
                .range_start = 0,
                .range_end   = LLONG_MAX,
                .nr_to_write = LONG_MAX,
        };
 
        /*
-        * Note by akpm about WB_SYNC_NONE used above: zero @wait is just an
-        * advisory thing to help the file system shove lots of data into the
-        * queues. If some gets missed then it'll be picked up on the second
+        * Zero @wait is just an advisory thing to help the file system shove
+        * lots of data into the queues, and there will be the second
         * '->sync_fs()' call, with non-zero @wait.
         */
+       if (!wait)
+               return 0;
 
        if (sb->s_flags & MS_RDONLY)
                return 0;
 
-       /*
-        * Synchronize write buffers, because 'ubifs_run_commit()' does not
-        * do this if it waits for an already running commit.
-        */
-       for (i = 0; i < c->jhead_cnt; i++) {
-               err = ubifs_wbuf_sync(&c->jheads[i].wbuf);
-               if (err)
-                       return err;
-       }
-
        /*
         * VFS calls '->sync_fs()' before synchronizing all dirty inodes and
         * pages, so synchronize them first, then commit the journal. Strictly
@@ -469,6 +461,16 @@ static int ubifs_sync_fs(struct super_block *sb, int wait)
         */
        generic_sync_sb_inodes(sb, &wbc);
 
+       /*
+        * Synchronize write buffers, because 'ubifs_run_commit()' does not
+        * do this if it waits for an already running commit.
+        */
+       for (i = 0; i < c->jhead_cnt; i++) {
+               err = ubifs_wbuf_sync(&c->jheads[i].wbuf);
+               if (err)
+                       return err;
+       }
+
        err = ubifs_run_commit(c);
        if (err)
                return err;
@@ -572,15 +574,8 @@ static int init_constants_early(struct ubifs_info *c)
        c->ranges[UBIFS_IDX_NODE].max_len = INT_MAX;
 
        /*
-        * Initialize dead and dark LEB space watermarks.
-        *
-        * Dead space is the space which cannot be used. Its watermark is
-        * equivalent to min. I/O unit or minimum node size if it is greater
-        * then min. I/O unit.
-        *
-        * Dark space is the space which might be used, or might not, depending
-        * on which node should be written to the LEB. Its watermark is
-        * equivalent to maximum UBIFS node size.
+        * Initialize dead and dark LEB space watermarks. See gc.c for comments
+        * about these values.
         */
        c->dead_wm = ALIGN(MIN_WRITE_SZ, c->min_io_size);
        c->dark_wm = ALIGN(UBIFS_MAX_NODE_SZ, c->min_io_size);
@@ -741,12 +736,12 @@ static void init_constants_master(struct ubifs_info *c)
  * take_gc_lnum - reserve GC LEB.
  * @c: UBIFS file-system description object
  *
- * This function ensures that the LEB reserved for garbage collection is
- * unmapped and is marked as "taken" in lprops. We also have to set free space
- * to LEB size and dirty space to zero, because lprops may contain out-of-date
- * information if the file-system was un-mounted before it has been committed.
- * This function returns zero in case of success and a negative error code in
- * case of failure.
+ * This function ensures that the LEB reserved for garbage collection is marked
+ * as "taken" in lprops. We also have to set free space to LEB size and dirty
+ * space to zero, because lprops may contain out-of-date information if the
+ * file-system was un-mounted before it has been committed. This function
+ * returns zero in case of success and a negative error code in case of
+ * failure.
  */
 static int take_gc_lnum(struct ubifs_info *c)
 {
@@ -757,10 +752,6 @@ static int take_gc_lnum(struct ubifs_info *c)
                return -EINVAL;
        }
 
-       err = ubifs_leb_unmap(c, c->gc_lnum);
-       if (err)
-               return err;
-
        /* And we have to tell lprops that this LEB is taken */
        err = ubifs_change_one_lp(c, c->gc_lnum, c->leb_size, 0,
                                  LPROPS_TAKEN, 0, 0);
@@ -966,13 +957,16 @@ static int ubifs_parse_options(struct ubifs_info *c, char *options,
 
                token = match_token(p, tokens, args);
                switch (token) {
+               /*
+                * %Opt_fast_unmount and %Opt_norm_unmount options are ignored.
+                * We accepte them in order to be backware-compatible. But this
+                * should be removed at some point.
+                */
                case Opt_fast_unmount:
                        c->mount_opts.unmount_mode = 2;
-                       c->fast_unmount = 1;
                        break;
                case Opt_norm_unmount:
                        c->mount_opts.unmount_mode = 1;
-                       c->fast_unmount = 0;
                        break;
                case Opt_bulk_read:
                        c->mount_opts.bulk_read = 2;
@@ -1094,12 +1088,7 @@ static int check_free_space(struct ubifs_info *c)
                ubifs_err("insufficient free space to mount in read/write mode");
                dbg_dump_budg(c);
                dbg_dump_lprops(c);
-               /*
-                * We return %-EINVAL instead of %-ENOSPC because it seems to
-                * be the closest error code mentioned in the mount function
-                * documentation.
-                */
-               return -EINVAL;
+               return -ENOSPC;
        }
        return 0;
 }
@@ -1286,10 +1275,19 @@ static int mount_ubifs(struct ubifs_info *c)
                        if (err)
                                goto out_orphans;
                        err = ubifs_rcvry_gc_commit(c);
-               } else
+               } else {
                        err = take_gc_lnum(c);
-               if (err)
-                       goto out_orphans;
+                       if (err)
+                               goto out_orphans;
+
+                       /*
+                        * GC LEB may contain garbage if there was an unclean
+                        * reboot, and it should be un-mapped.
+                        */
+                       err = ubifs_leb_unmap(c, c->gc_lnum);
+                       if (err)
+                               return err;
+               }
 
                err = dbg_check_lprops(c);
                if (err)
@@ -1298,6 +1296,16 @@ static int mount_ubifs(struct ubifs_info *c)
                err = ubifs_recover_size(c);
                if (err)
                        goto out_orphans;
+       } else {
+               /*
+                * Even if we mount read-only, we have to set space in GC LEB
+                * to proper value because this affects UBIFS free space
+                * reporting. We do not want to have a situation when
+                * re-mounting from R/O to R/W changes amount of free space.
+                */
+               err = take_gc_lnum(c);
+               if (err)
+                       goto out_orphans;
        }
 
        spin_lock(&ubifs_infos_lock);
@@ -1310,14 +1318,17 @@ static int mount_ubifs(struct ubifs_info *c)
                else {
                        c->need_recovery = 0;
                        ubifs_msg("recovery completed");
+                       /* GC LEB has to be empty and taken at this point */
+                       ubifs_assert(c->lst.taken_empty_lebs == 1);
                }
-       }
+       } else
+               ubifs_assert(c->lst.taken_empty_lebs == 1);
 
-       err = dbg_debugfs_init_fs(c);
+       err = dbg_check_filesystem(c);
        if (err)
                goto out_infos;
 
-       err = dbg_check_filesystem(c);
+       err = dbg_debugfs_init_fs(c);
        if (err)
                goto out_infos;
 
@@ -1351,7 +1362,6 @@ static int mount_ubifs(struct ubifs_info *c)
               c->uuid[4], c->uuid[5], c->uuid[6], c->uuid[7],
               c->uuid[8], c->uuid[9], c->uuid[10], c->uuid[11],
               c->uuid[12], c->uuid[13], c->uuid[14], c->uuid[15]);
-       dbg_msg("fast unmount:        %d", c->fast_unmount);
        dbg_msg("big_lpt              %d", c->big_lpt);
        dbg_msg("log LEBs:            %d (%d - %d)",
                c->log_lebs, UBIFS_LOG_LNUM, c->log_last);
@@ -1475,10 +1485,8 @@ static int ubifs_remount_rw(struct ubifs_info *c)
 {
        int err, lnum;
 
-       if (c->ro_media)
-               return -EINVAL;
-
        mutex_lock(&c->umount_mutex);
+       dbg_save_space_info(c);
        c->remounting_rw = 1;
        c->always_chk_crc = 1;
 
@@ -1514,6 +1522,12 @@ static int ubifs_remount_rw(struct ubifs_info *c)
                err = ubifs_recover_inl_heads(c, c->sbuf);
                if (err)
                        goto out;
+       } else {
+               /* A readonly mount is not allowed to have orphans */
+               ubifs_assert(c->tot_orphans == 0);
+               err = ubifs_clear_orphans(c);
+               if (err)
+                       goto out;
        }
 
        if (!(c->mst_node->flags & cpu_to_le32(UBIFS_MST_DIRTY))) {
@@ -1569,7 +1583,7 @@ static int ubifs_remount_rw(struct ubifs_info *c)
        if (c->need_recovery)
                err = ubifs_rcvry_gc_commit(c);
        else
-               err = take_gc_lnum(c);
+               err = ubifs_leb_unmap(c, c->gc_lnum);
        if (err)
                goto out;
 
@@ -1582,8 +1596,9 @@ static int ubifs_remount_rw(struct ubifs_info *c)
        c->vfs_sb->s_flags &= ~MS_RDONLY;
        c->remounting_rw = 0;
        c->always_chk_crc = 0;
+       err = dbg_check_space_info(c);
        mutex_unlock(&c->umount_mutex);
-       return 0;
+       return err;
 
 out:
        vfree(c->orph_buf);
@@ -1602,44 +1617,19 @@ out:
        return err;
 }
 
-/**
- * commit_on_unmount - commit the journal when un-mounting.
- * @c: UBIFS file-system description object
- *
- * This function is called during un-mounting and re-mounting, and it commits
- * the journal unless the "fast unmount" mode is enabled.
- */
-static void commit_on_unmount(struct ubifs_info *c)
-{
-       struct super_block *sb = c->vfs_sb;
-       long long bud_bytes;
-
-       /*
-        * This function is called before the background thread is stopped, so
-        * we may race with ongoing commit, which means we have to take
-        * @c->bud_lock to access @c->bud_bytes.
-        */
-       spin_lock(&c->buds_lock);
-       bud_bytes = c->bud_bytes;
-       spin_unlock(&c->buds_lock);
-
-       if (!c->fast_unmount && !(sb->s_flags & MS_RDONLY) && bud_bytes)
-               ubifs_run_commit(c);
-}
-
 /**
  * ubifs_remount_ro - re-mount in read-only mode.
  * @c: UBIFS file-system description object
  *
- * We rely on VFS to have stopped writing. Possibly the background thread could
- * be running a commit, however kthread_stop will wait in that case.
+ * We assume VFS has stopped writing. Possibly the background thread could be
+ * running a commit, however kthread_stop will wait in that case.
  */
 static void ubifs_remount_ro(struct ubifs_info *c)
 {
        int i, err;
 
        ubifs_assert(!c->need_recovery);
-       commit_on_unmount(c);
+       ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY));
 
        mutex_lock(&c->umount_mutex);
        if (c->bgt) {
@@ -1647,27 +1637,29 @@ static void ubifs_remount_ro(struct ubifs_info *c)
                c->bgt = NULL;
        }
 
+       dbg_save_space_info(c);
+
        for (i = 0; i < c->jhead_cnt; i++) {
                ubifs_wbuf_sync(&c->jheads[i].wbuf);
                del_timer_sync(&c->jheads[i].wbuf.timer);
        }
 
-       if (!c->ro_media) {
-               c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY);
-               c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS);
-               c->mst_node->gc_lnum = cpu_to_le32(c->gc_lnum);
-               err = ubifs_write_master(c);
-               if (err)
-                       ubifs_ro_mode(c, err);
-       }
+       c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY);
+       c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS);
+       c->mst_node->gc_lnum = cpu_to_le32(c->gc_lnum);
+       err = ubifs_write_master(c);
+       if (err)
+               ubifs_ro_mode(c, err);
 
-       ubifs_destroy_idx_gc(c);
        free_wbufs(c);
        vfree(c->orph_buf);
        c->orph_buf = NULL;
        vfree(c->ileb_buf);
        c->ileb_buf = NULL;
        ubifs_lpt_free(c, 1);
+       err = dbg_check_space_info(c);
+       if (err)
+               ubifs_ro_mode(c, err);
        mutex_unlock(&c->umount_mutex);
 }
 
@@ -1760,11 +1752,20 @@ static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data)
        }
 
        if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) {
+               if (c->ro_media) {
+                       ubifs_msg("cannot re-mount due to prior errors");
+                       return -EROFS;
+               }
                err = ubifs_remount_rw(c);
                if (err)
                        return err;
-       } else if (!(sb->s_flags & MS_RDONLY) && (*flags & MS_RDONLY))
+       } else if (!(sb->s_flags & MS_RDONLY) && (*flags & MS_RDONLY)) {
+               if (c->ro_media) {
+                       ubifs_msg("cannot re-mount due to prior errors");
+                       return -EROFS;
+               }
                ubifs_remount_ro(c);
+       }
 
        if (c->bulk_read == 1)
                bu_init(c);
@@ -1774,10 +1775,11 @@ static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data)
                c->bu.buf = NULL;
        }
 
+       ubifs_assert(c->lst.taken_empty_lebs == 1);
        return 0;
 }
 
-struct super_operations ubifs_super_operations = {
+const struct super_operations ubifs_super_operations = {
        .alloc_inode   = ubifs_alloc_inode,
        .destroy_inode = ubifs_destroy_inode,
        .put_super     = ubifs_put_super,
@@ -2044,15 +2046,6 @@ out_close:
 
 static void ubifs_kill_sb(struct super_block *sb)
 {
-       struct ubifs_info *c = sb->s_fs_info;
-
-       /*
-        * We do 'commit_on_unmount()' here instead of 'ubifs_put_super()'
-        * in order to be outside BKL.
-        */
-       if (sb->s_root)
-               commit_on_unmount(c);
-       /* The un-mount routine is actually done in put_super() */
        generic_shutdown_super(sb);
 }
 
index f7e36f5..fa28a84 100644 (file)
@@ -443,6 +443,11 @@ static int tnc_read_node_nm(struct ubifs_info *c, struct ubifs_zbranch *zbr,
  * This function performs that same function as ubifs_read_node except that
  * it does not require that there is actually a node present and instead
  * the return code indicates if a node was read.
+ *
+ * Note, this function does not check CRC of data nodes if @c->no_chk_data_crc
+ * is true (it is controlled by corresponding mount option). However, if
+ * @c->always_chk_crc is true, @c->no_chk_data_crc is ignored and CRC is always
+ * checked.
  */
 static int try_read_node(const struct ubifs_info *c, void *buf, int type,
                         int len, int lnum, int offs)
@@ -470,9 +475,8 @@ static int try_read_node(const struct ubifs_info *c, void *buf, int type,
        if (node_len != len)
                return 0;
 
-       if (type == UBIFS_DATA_NODE && !c->always_chk_crc)
-               if (c->no_chk_data_crc)
-                       return 0;
+       if (type == UBIFS_DATA_NODE && !c->always_chk_crc && c->no_chk_data_crc)
+               return 1;
 
        crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8);
        node_crc = le32_to_cpu(ch->crc);
@@ -1506,7 +1510,7 @@ out:
  *
  * Note, if the bulk-read buffer length (@bu->buf_len) is known, this function
  * makes sure bulk-read nodes fit the buffer. Otherwise, this function prepares
- * maxumum possible amount of nodes for bulk-read.
+ * maximum possible amount of nodes for bulk-read.
  */
 int ubifs_tnc_get_bu_keys(struct ubifs_info *c, struct bu_info *bu)
 {
index fc2a4cc..039a68b 100644 (file)
@@ -426,9 +426,9 @@ struct ubifs_unclean_leb {
  * LEB properties flags.
  *
  * LPROPS_UNCAT: not categorized
- * LPROPS_DIRTY: dirty > 0, not index
+ * LPROPS_DIRTY: dirty > free, dirty >= @c->dead_wm, not index
  * LPROPS_DIRTY_IDX: dirty + free > @c->min_idx_node_sze and index
- * LPROPS_FREE: free > 0, not empty, not index
+ * LPROPS_FREE: free > 0, dirty < @c->dead_wm, not empty, not index
  * LPROPS_HEAP_CNT: number of heaps used for storing categorized LEBs
  * LPROPS_EMPTY: LEB is empty, not taken
  * LPROPS_FREEABLE: free + dirty == leb_size, not index, not taken
@@ -961,7 +961,6 @@ struct ubifs_debug_info;
  * @cs_lock: commit state lock
  * @cmt_wq: wait queue to sleep on if the log is full and a commit is running
  *
- * @fast_unmount: do not run journal commit before un-mounting
  * @big_lpt: flag that LPT is too big to write whole during commit
  * @no_chk_data_crc: do not check CRCs when reading data nodes (except during
  *                   recovery)
@@ -1202,7 +1201,6 @@ struct ubifs_info {
        spinlock_t cs_lock;
        wait_queue_head_t cmt_wq;
 
-       unsigned int fast_unmount:1;
        unsigned int big_lpt:1;
        unsigned int no_chk_data_crc:1;
        unsigned int bulk_read:1;
@@ -1405,13 +1403,13 @@ extern struct list_head ubifs_infos;
 extern spinlock_t ubifs_infos_lock;
 extern atomic_long_t ubifs_clean_zn_cnt;
 extern struct kmem_cache *ubifs_inode_slab;
-extern struct super_operations ubifs_super_operations;
-extern struct address_space_operations ubifs_file_address_operations;
-extern struct file_operations ubifs_file_operations;
-extern struct inode_operations ubifs_file_inode_operations;
-extern struct file_operations ubifs_dir_operations;
-extern struct inode_operations ubifs_dir_inode_operations;
-extern struct inode_operations ubifs_symlink_inode_operations;
+extern const struct super_operations ubifs_super_operations;
+extern const struct address_space_operations ubifs_file_address_operations;
+extern const struct file_operations ubifs_file_operations;
+extern const struct inode_operations ubifs_file_inode_operations;
+extern const struct file_operations ubifs_dir_operations;
+extern const struct inode_operations ubifs_dir_inode_operations;
+extern const struct inode_operations ubifs_symlink_inode_operations;
 extern struct backing_dev_info ubifs_backing_dev_info;
 extern struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT];
 
@@ -1428,7 +1426,7 @@ int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len,
 int ubifs_write_node(struct ubifs_info *c, void *node, int len, int lnum,
                     int offs, int dtype);
 int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum,
-                    int offs, int quiet, int chk_crc);
+                    int offs, int quiet, int must_chk_crc);
 void ubifs_prepare_node(struct ubifs_info *c, void *buf, int len, int pad);
 void ubifs_prep_grp_node(struct ubifs_info *c, void *node, int len, int last);
 int ubifs_io_init(struct ubifs_info *c);
@@ -1495,6 +1493,7 @@ void ubifs_release_ino_dirty(struct ubifs_info *c, struct inode *inode,
 void ubifs_cancel_ino_op(struct ubifs_info *c, struct inode *inode,
                         struct ubifs_budget_req *req);
 long long ubifs_get_free_space(struct ubifs_info *c);
+long long ubifs_get_free_space_nolock(struct ubifs_info *c);
 int ubifs_calc_min_idx_lebs(struct ubifs_info *c);
 void ubifs_convert_page_budget(struct ubifs_info *c);
 long long ubifs_reported_space(const struct ubifs_info *c, long long free);
@@ -1603,6 +1602,7 @@ void ubifs_delete_orphan(struct ubifs_info *c, ino_t inum);
 int ubifs_orphan_start_commit(struct ubifs_info *c);
 int ubifs_orphan_end_commit(struct ubifs_info *c);
 int ubifs_mount_orphans(struct ubifs_info *c, int unclean, int read_only);
+int ubifs_clear_orphans(struct ubifs_info *c);
 
 /* lpt.c */
 int ubifs_calc_lpt_geom(struct ubifs_info *c);
@@ -1646,7 +1646,7 @@ const struct ubifs_lprops *ubifs_change_lp(struct ubifs_info *c,
                                           const struct ubifs_lprops *lp,
                                           int free, int dirty, int flags,
                                           int idx_gc_cnt);
-void ubifs_get_lp_stats(struct ubifs_info *c, struct ubifs_lp_stats *stats);
+void ubifs_get_lp_stats(struct ubifs_info *c, struct ubifs_lp_stats *lst);
 void ubifs_add_to_cat(struct ubifs_info *c, struct ubifs_lprops *lprops,
                      int cat);
 void ubifs_replace_cat(struct ubifs_info *c, struct ubifs_lprops *old_lprops,
index 2ed0353..a608e72 100644 (file)
@@ -371,7 +371,11 @@ xfs_quiesce_attr(
        /* flush inodes and push all remaining buffers out to disk */
        xfs_quiesce_fs(mp);
 
-       ASSERT_ALWAYS(atomic_read(&mp->m_active_trans) == 0);
+       /*
+        * Just warn here till VFS can correctly support
+        * read-only remount without racing.
+        */
+       WARN_ON(atomic_read(&mp->m_active_trans) != 0);
 
        /* Push the superblock and write an unmount record */
        error = xfs_log_sbcount(mp, 1);
index b4c1ee7..f8278cf 100644 (file)
@@ -55,17 +55,11 @@ xfs_swapext(
        struct file     *file, *target_file;
        int             error = 0;
 
-       sxp = kmem_alloc(sizeof(xfs_swapext_t), KM_MAYFAIL);
-       if (!sxp) {
-               error = XFS_ERROR(ENOMEM);
-               goto out;
-       }
-
        /* Pull information for the target fd */
        file = fget((int)sxp->sx_fdtarget);
        if (!file) {
                error = XFS_ERROR(EINVAL);
-               goto out_free_sxp;
+               goto out;
        }
 
        if (!(file->f_mode & FMODE_WRITE) || (file->f_flags & O_APPEND)) {
@@ -109,8 +103,6 @@ xfs_swapext(
        fput(target_file);
  out_put_file:
        fput(file);
- out_free_sxp:
-       kmem_free(sxp);
  out:
        return error;
 }
index 35cca98..b1047de 100644 (file)
@@ -70,16 +70,21 @@ STATIC void xlog_recover_check_summary(xlog_t *);
 xfs_buf_t *
 xlog_get_bp(
        xlog_t          *log,
-       int             num_bblks)
+       int             nbblks)
 {
-       ASSERT(num_bblks > 0);
+       if (nbblks <= 0 || nbblks > log->l_logBBsize) {
+               xlog_warn("XFS: Invalid block length (0x%x) given for buffer", nbblks);
+               XFS_ERROR_REPORT("xlog_get_bp(1)",
+                                XFS_ERRLEVEL_HIGH, log->l_mp);
+               return NULL;
+       }
 
        if (log->l_sectbb_log) {
-               if (num_bblks > 1)
-                       num_bblks += XLOG_SECTOR_ROUNDUP_BBCOUNT(log, 1);
-               num_bblks = XLOG_SECTOR_ROUNDUP_BBCOUNT(log, num_bblks);
+               if (nbblks > 1)
+                       nbblks += XLOG_SECTOR_ROUNDUP_BBCOUNT(log, 1);
+               nbblks = XLOG_SECTOR_ROUNDUP_BBCOUNT(log, nbblks);
        }
-       return xfs_buf_get_noaddr(BBTOB(num_bblks), log->l_mp->m_logdev_targp);
+       return xfs_buf_get_noaddr(BBTOB(nbblks), log->l_mp->m_logdev_targp);
 }
 
 void
@@ -102,6 +107,13 @@ xlog_bread(
 {
        int             error;
 
+       if (nbblks <= 0 || nbblks > log->l_logBBsize) {
+               xlog_warn("XFS: Invalid block length (0x%x) given for buffer", nbblks);
+               XFS_ERROR_REPORT("xlog_bread(1)",
+                                XFS_ERRLEVEL_HIGH, log->l_mp);
+               return EFSCORRUPTED;
+       }
+
        if (log->l_sectbb_log) {
                blk_no = XLOG_SECTOR_ROUNDDOWN_BLKNO(log, blk_no);
                nbblks = XLOG_SECTOR_ROUNDUP_BBCOUNT(log, nbblks);
@@ -139,6 +151,13 @@ xlog_bwrite(
 {
        int             error;
 
+       if (nbblks <= 0 || nbblks > log->l_logBBsize) {
+               xlog_warn("XFS: Invalid block length (0x%x) given for buffer", nbblks);
+               XFS_ERROR_REPORT("xlog_bwrite(1)",
+                                XFS_ERRLEVEL_HIGH, log->l_mp);
+               return EFSCORRUPTED;
+       }
+
        if (log->l_sectbb_log) {
                blk_no = XLOG_SECTOR_ROUNDDOWN_BLKNO(log, blk_no);
                nbblks = XLOG_SECTOR_ROUNDUP_BBCOUNT(log, nbblks);
index 2124c06..b97cdc5 100644 (file)
@@ -90,7 +90,6 @@ header-y += if_ppp.h
 header-y += if_slip.h
 header-y += if_strip.h
 header-y += if_tun.h
-header-y += if_tunnel.h
 header-y += in_route.h
 header-y += ioctl.h
 header-y += ip6_tunnel.h
@@ -236,6 +235,7 @@ unifdef-y += if_phonet.h
 unifdef-y += if_pppol2tp.h
 unifdef-y += if_pppox.h
 unifdef-y += if_tr.h
+unifdef-y += if_tunnel.h
 unifdef-y += if_vlan.h
 unifdef-y += igmp.h
 unifdef-y += inet_diag.h
index a53318b..08a86d5 100644 (file)
@@ -731,12 +731,17 @@ static inline int ata_id_current_chs_valid(const u16 *id)
 
 static inline int ata_id_is_cfa(const u16 *id)
 {
-       if (id[ATA_ID_CONFIG] == 0x848A)        /* Standard CF */
+       if (id[ATA_ID_CONFIG] == 0x848A)        /* Traditional CF */
                return 1;
-       /* Could be CF hiding as standard ATA */
-       if (ata_id_major_version(id) >= 3 &&
-           id[ATA_ID_COMMAND_SET_1] != 0xFFFF &&
-          (id[ATA_ID_COMMAND_SET_1] & (1 << 2)))
+       /*
+        * CF specs don't require specific value in the word 0 anymore and yet
+        * they forbid to report the ATA version in the word 80 and require the
+        * CFA feature set support to be indicated in the word 83 in this case.
+        * Unfortunately, some cards only follow either of this requirements,
+        * and while those that don't indicate CFA feature support need some
+        * sort of quirk list, it seems impractical for the ones that do...
+        */
+       if ((id[ATA_ID_COMMAND_SET_2] & 0xC004) == 0x4004)
                return 1;
        return 0;
 }
index 818fe21..31527e1 100644 (file)
@@ -960,6 +960,21 @@ extern struct fb_info *registered_fb[FB_MAX];
 extern int num_registered_fb;
 extern struct class *fb_class;
 
+static inline int lock_fb_info(struct fb_info *info)
+{
+       mutex_lock(&info->lock);
+       if (!info->fbops) {
+               mutex_unlock(&info->lock);
+               return 0;
+       }
+       return 1;
+}
+
+static inline void unlock_fb_info(struct fb_info *info)
+{
+       mutex_unlock(&info->lock);
+}
+
 static inline void __fb_pad_aligned_buffer(u8 *dst, u32 d_pitch,
                                           u8 *src, u32 s_pitch, u32 height)
 {
index aeab2cb..82c4362 100644 (file)
@@ -2,7 +2,10 @@
 #define _IF_TUNNEL_H_
 
 #include <linux/types.h>
+
+#ifdef __KERNEL__
 #include <linux/ip.h>
+#endif
 
 #define SIOCGETTUNNEL   (SIOCDEVPRIVATE + 0)
 #define SIOCADDTUNNEL   (SIOCDEVPRIVATE + 1)
index 343df9e..7fa3718 100644 (file)
@@ -480,7 +480,8 @@ static inline char *pack_hex_byte(char *buf, u8 byte)
 /*
  * swap - swap value of @a and @b
  */
-#define swap(a, b) ({ typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; })
+#define swap(a, b) \
+       do { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0)
 
 /**
  * container_of - cast a member of a structure out to the containing structure
index bca3ba2..5d87bc0 100644 (file)
@@ -380,6 +380,7 @@ enum {
        ATA_HORKAGE_ATAPI_MOD16_DMA = (1 << 11), /* use ATAPI DMA for commands
                                                    not multiple of 16 bytes */
        ATA_HORKAGE_FIRMWARE_WARN = (1 << 12),  /* firwmare update warning */
+       ATA_HORKAGE_1_5_GBPS    = (1 << 13),    /* force 1.5 Gbps */
 
         /* DMA mask for user DMA control: User visible values; DO NOT
            renumber */
@@ -580,7 +581,7 @@ struct ata_device {
        acpi_handle             acpi_handle;
        union acpi_object       *gtf_cache;
 #endif
-       /* n_sector is used as CLEAR_OFFSET, read comment above CLEAR_OFFSET */
+       /* n_sector is CLEAR_BEGIN, read comment above CLEAR_BEGIN */
        u64                     n_sectors;      /* size of device, if ATA */
        unsigned int            class;          /* ATA_DEV_xxx */
        unsigned long           unpark_deadline;
@@ -605,20 +606,22 @@ struct ata_device {
        u16                     heads;          /* Number of heads */
        u16                     sectors;        /* Number of sectors per track */
 
-       /* error history */
-       int                     spdn_cnt;
-       struct ata_ering        ering;
-
        union {
                u16             id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */
                u32             gscr[SATA_PMP_GSCR_DWORDS]; /* PMP GSCR block */
        };
+
+       /* error history */
+       int                     spdn_cnt;
+       /* ering is CLEAR_END, read comment above CLEAR_END */
+       struct ata_ering        ering;
 };
 
-/* Offset into struct ata_device.  Fields above it are maintained
- * acress device init.  Fields below are zeroed.
+/* Fields between ATA_DEVICE_CLEAR_BEGIN and ATA_DEVICE_CLEAR_END are
+ * cleared to zero on ata_dev_init().
  */
-#define ATA_DEVICE_CLEAR_OFFSET                offsetof(struct ata_device, n_sectors)
+#define ATA_DEVICE_CLEAR_BEGIN         offsetof(struct ata_device, n_sectors)
+#define ATA_DEVICE_CLEAR_END           offsetof(struct ata_device, ering)
 
 struct ata_eh_info {
        struct ata_device       *dev;           /* offending device */
index ef609f8..a210ede 100644 (file)
@@ -132,6 +132,8 @@ static inline void __remove_wait_queue(wait_queue_head_t *head,
        list_del(&old->task_list);
 }
 
+void __wake_up_common(wait_queue_head_t *q, unsigned int mode,
+                       int nr_exclusive, int sync, void *key);
 void __wake_up(wait_queue_head_t *q, unsigned int mode, int nr, void *key);
 extern void __wake_up_locked(wait_queue_head_t *q, unsigned int mode);
 extern void __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr);
@@ -333,16 +335,19 @@ do {                                                                      \
        for (;;) {                                                      \
                prepare_to_wait_exclusive(&wq, &__wait,                 \
                                        TASK_INTERRUPTIBLE);            \
-               if (condition)                                          \
+               if (condition) {                                        \
+                       finish_wait(&wq, &__wait);                      \
                        break;                                          \
+               }                                                       \
                if (!signal_pending(current)) {                         \
                        schedule();                                     \
                        continue;                                       \
                }                                                       \
                ret = -ERESTARTSYS;                                     \
+               abort_exclusive_wait(&wq, &__wait,                      \
+                               TASK_INTERRUPTIBLE, NULL);              \
                break;                                                  \
        }                                                               \
-       finish_wait(&wq, &__wait);                                      \
 } while (0)
 
 #define wait_event_interruptible_exclusive(wq, condition)              \
@@ -431,6 +436,8 @@ extern long interruptible_sleep_on_timeout(wait_queue_head_t *q,
 void prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int state);
 void prepare_to_wait_exclusive(wait_queue_head_t *q, wait_queue_t *wait, int state);
 void finish_wait(wait_queue_head_t *q, wait_queue_t *wait);
+void abort_exclusive_wait(wait_queue_head_t *q, wait_queue_t *wait,
+                       unsigned int mode, void *key);
 int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key);
 int wake_bit_function(wait_queue_t *wait, unsigned mode, int sync, void *key);
 
index 7079beb..51ac69f 100644 (file)
@@ -21,9 +21,9 @@
 #define I2C_CNTL_1                             0x0094
 #define PALETTE_INDEX                          0x00b0
 #define PALETTE_DATA                           0x00b4
-#define CONFIG_CNTL                            0x00e0
+#define CNFG_CNTL                              0x00e0
 #define GEN_RESET_CNTL                         0x00f0
-#define CONFIG_MEMSIZE                         0x00f8
+#define CNFG_MEMSIZE                           0x00f8
 #define MEM_CNTL                               0x0140
 #define MEM_POWER_MISC                         0x015c
 #define AGP_BASE                               0x0170
index a8332e5..89e91c0 100644 (file)
 #define CUR_HORZ_VERT_OFF      0x0070  /* Dword offset 0_1C */
 #define CUR2_HORZ_VERT_OFF     0x0070  /* Dword offset 0_1C */
 
-#define CONFIG_PANEL_LG                0x0074  /* Dword offset 0_1D (LG) */
+#define CNFG_PANEL_LG          0x0074  /* Dword offset 0_1D (LG) */
 
 /* General I/O Control */
 #define GP_IO                  0x0078  /* Dword offset 0_1E */
 #define CLOCK_SEL_CNTL         0x0090  /* Dword offset 0_24 */
 
 /* Configuration */
-#define CONFIG_STAT1           0x0094  /* Dword offset 0_25 */
-#define CONFIG_STAT2           0x0098  /* Dword offset 0_26 */
+#define CNFG_STAT1             0x0094  /* Dword offset 0_25 */
+#define CNFG_STAT2             0x0098  /* Dword offset 0_26 */
 
 /* Bus Control */
 #define BUS_CNTL               0x00A0  /* Dword offset 0_28 */
 #define POWER_MANAGEMENT_LG    0x00D8  /* Dword offset 0_36 (LG) */
 
 /* Configuration */
-#define CONFIG_CNTL            0x00DC  /* Dword offset 0_37 (CT, ET, VT) */
-#define CONFIG_CHIP_ID         0x00E0  /* Dword offset 0_38 */
-#define CONFIG_STAT0           0x00E4  /* Dword offset 0_39 */
+#define CNFG_CNTL              0x00DC  /* Dword offset 0_37 (CT, ET, VT) */
+#define CNFG_CHIP_ID           0x00E0  /* Dword offset 0_38 */
+#define CNFG_STAT0             0x00E4  /* Dword offset 0_39 */
 
 /* Test and Debug */
 #define CRC_SIG                        0x00E8  /* Dword offset 0_3A */
 #define PLL_YCLK_CNTL          0x29
 #define PM_DYN_CLK_CNTL                0x2A
 
-/* CONFIG_CNTL register constants */
+/* CNFG_CNTL register constants */
 #define APERTURE_4M_ENABLE     1
 #define APERTURE_8M_ENABLE     2
 #define VGA_APERTURE_ENABLE    4
 
-/* CONFIG_STAT0 register constants (GX, CX) */
+/* CNFG_STAT0 register constants (GX, CX) */
 #define CFG_BUS_TYPE           0x00000007
 #define CFG_MEM_TYPE           0x00000038
 #define CFG_INIT_DAC_TYPE      0x00000e00
 
-/* CONFIG_STAT0 register constants (CT, ET, VT) */
+/* CNFG_STAT0 register constants (CT, ET, VT) */
 #define CFG_MEM_TYPE_xT                0x00000007
 
 #define ISA                    0
 #define PCI_ATI_VENDOR_ID      0x1002
 
 
-/* CONFIG_CHIP_ID register constants */
+/* CNFG_CHIP_ID register constants */
 #define CFG_CHIP_TYPE          0x0000FFFF
 #define CFG_CHIP_CLASS         0x00FF0000
 #define CFG_CHIP_REV           0xFF000000
 #define CFG_CHIP_MINOR         0xC0000000
 
 
-/* Chip IDs read from CONFIG_CHIP_ID */
+/* Chip IDs read from CNFG_CHIP_ID */
 
 /* mach64GX family */
 #define GX_CHIP_ID     0xD7    /* mach64GX (ATI888GX00) */
 #define CRTC2_DISPLAY_DIS      0x00000400
 
 /* LCD register indices */
-#define CONFIG_PANEL           0x00
+#define CNFG_PANEL             0x00
 #define LCD_GEN_CNTL           0x01
 #define DSTN_CONTROL           0x02
 #define HFB_PITCH_ADDR         0x03
index 1cd09cc..e072b16 100644 (file)
 #define HI_STAT                                0x004C  
 #define BUS_CNTL1                              0x0034
 #define I2C_CNTL_1                            0x0094  
-#define CONFIG_CNTL                            0x00E0  
-#define CONFIG_MEMSIZE                         0x00F8  
-#define CONFIG_APER_0_BASE                     0x0100  
-#define CONFIG_APER_1_BASE                     0x0104  
-#define CONFIG_APER_SIZE                       0x0108  
-#define CONFIG_REG_1_BASE                      0x010C  
-#define CONFIG_REG_APER_SIZE                   0x0110  
+#define CNFG_CNTL                              0x00E0
+#define CNFG_MEMSIZE                           0x00F8
+#define CNFG_APER_0_BASE                       0x0100
+#define CNFG_APER_1_BASE                       0x0104
+#define CNFG_APER_SIZE                         0x0108
+#define CNFG_REG_1_BASE                        0x010C
+#define CNFG_REG_APER_SIZE                     0x0110
 #define PAD_AGPINPUT_DELAY                     0x0164  
 #define PAD_CTLR_STRENGTH                      0x0168  
 #define PAD_CTLR_UPDATE                        0x016C
 /* CLOCK_CNTL_INDEX bit constants */
 #define PLL_WR_EN                                  0x00000080
 
-/* CONFIG_CNTL bit constants */
+/* CNFG_CNTL bit constants */
 #define CFG_VGA_RAM_EN                             0x00000100
 #define CFG_ATI_REV_ID_MASK                       (0xf << 16)
 #define CFG_ATI_REV_A11                                   (0 << 16)
 
 /* masks */
 
-#define CONFIG_MEMSIZE_MASK            0x1f000000
+#define CNFG_MEMSIZE_MASK              0x1f000000
 #define MEM_CFG_TYPE                   0x40000000
 #define DST_OFFSET_MASK                        0x003fffff
 #define DST_PITCH_MASK                 0x3fc00000
index c0a021f..f8f69fa 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -565,11 +565,15 @@ static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss,
                        struct hstate *h = hstate_file(shp->shm_file);
                        *rss += pages_per_huge_page(h) * mapping->nrpages;
                } else {
+#ifdef CONFIG_SHMEM
                        struct shmem_inode_info *info = SHMEM_I(inode);
                        spin_lock(&info->lock);
                        *rss += inode->i_mapping->nrpages;
                        *swp += info->swapped;
                        spin_unlock(&info->lock);
+#else
+                       *rss += inode->i_mapping->nrpages;
+#endif
                }
 
                total++;
index 608b32b..67a2be7 100644 (file)
@@ -138,15 +138,18 @@ static void run_one_entry(void)
 
        /* 3) run it (and print duration)*/
        if (initcall_debug && system_state == SYSTEM_BOOTING) {
-               printk("calling  %lli_%pF @ %i\n", entry->cookie, entry->func, task_pid_nr(current));
+               printk("calling  %lli_%pF @ %i\n", (long long)entry->cookie,
+                       entry->func, task_pid_nr(current));
                calltime = ktime_get();
        }
        entry->func(entry->data, entry->cookie);
        if (initcall_debug && system_state == SYSTEM_BOOTING) {
                rettime = ktime_get();
                delta = ktime_sub(rettime, calltime);
-               printk("initcall %lli_%pF returned 0 after %lld usecs\n", entry->cookie,
-                       entry->func, ktime_to_ns(delta) >> 10);
+               printk("initcall %lli_%pF returned 0 after %lld usecs\n",
+                       (long long)entry->cookie,
+                       entry->func,
+                       (long long)ktime_to_ns(delta) >> 10);
        }
 
        /* 4) remove it from the running queue */
@@ -247,7 +250,8 @@ void async_synchronize_cookie_special(async_cookie_t cookie, struct list_head *r
                delta = ktime_sub(endtime, starttime);
 
                printk("async_continuing @ %i after %lli usec\n",
-                       task_pid_nr(current), ktime_to_ns(delta) >> 10);
+                       task_pid_nr(current),
+                       (long long)ktime_to_ns(delta) >> 10);
        }
 }
 EXPORT_SYMBOL_GPL(async_synchronize_cookie_special);
index e8e854a..bb5fe56 100644 (file)
@@ -1006,6 +1006,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
         * triggers too late. This doesn't hurt, the check is only there
         * to stop root fork bombs.
         */
+       retval = -EAGAIN;
        if (nr_threads >= max_threads)
                goto bad_fork_cleanup_count;
 
index ecf765c..acd8835 100644 (file)
@@ -71,7 +71,7 @@ static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc,
        desc = irq_desc_ptrs[irq];
 
        if (desc && old_desc != desc)
-                       goto out_unlock;
+               goto out_unlock;
 
        node = cpu_to_node(cpu);
        desc = kzalloc_node(sizeof(*desc), GFP_ATOMIC, node);
@@ -84,10 +84,15 @@ static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc,
        init_copy_one_irq_desc(irq, old_desc, desc, cpu);
 
        irq_desc_ptrs[irq] = desc;
+       spin_unlock_irqrestore(&sparse_irq_lock, flags);
 
        /* free the old one */
        free_one_irq_desc(old_desc, desc);
+       spin_unlock(&old_desc->lock);
        kfree(old_desc);
+       spin_lock(&desc->lock);
+
+       return desc;
 
 out_unlock:
        spin_unlock_irqrestore(&sparse_irq_lock, flags);
index e1fc67d..e724850 100644 (file)
@@ -4702,8 +4702,8 @@ EXPORT_SYMBOL(default_wake_function);
  * started to run but is not in state TASK_RUNNING. try_to_wake_up() returns
  * zero in this (rare) case, and we handle it by continuing to scan the queue.
  */
-static void __wake_up_common(wait_queue_head_t *q, unsigned int mode,
-                            int nr_exclusive, int sync, void *key)
+void __wake_up_common(wait_queue_head_t *q, unsigned int mode,
+                       int nr_exclusive, int sync, void *key)
 {
        wait_queue_t *curr, *next;
 
index e7dc0e1..f145c41 100644 (file)
@@ -1525,22 +1525,14 @@ SYSCALL_DEFINE2(setrlimit, unsigned int, resource, struct rlimit __user *, rlim)
                return -EINVAL;
        if (copy_from_user(&new_rlim, rlim, sizeof(*rlim)))
                return -EFAULT;
+       if (new_rlim.rlim_cur > new_rlim.rlim_max)
+               return -EINVAL;
        old_rlim = current->signal->rlim + resource;
        if ((new_rlim.rlim_max > old_rlim->rlim_max) &&
            !capable(CAP_SYS_RESOURCE))
                return -EPERM;
-
-       if (resource == RLIMIT_NOFILE) {
-               if (new_rlim.rlim_max == RLIM_INFINITY)
-                       new_rlim.rlim_max = sysctl_nr_open;
-               if (new_rlim.rlim_cur == RLIM_INFINITY)
-                       new_rlim.rlim_cur = sysctl_nr_open;
-               if (new_rlim.rlim_max > sysctl_nr_open)
-                       return -EPERM;
-       }
-
-       if (new_rlim.rlim_cur > new_rlim.rlim_max)
-               return -EINVAL;
+       if (resource == RLIMIT_NOFILE && new_rlim.rlim_max > sysctl_nr_open)
+               return -EPERM;
 
        retval = security_task_setrlimit(resource, &new_rlim);
        if (retval)
index ea2f48a..d13be21 100644 (file)
@@ -68,6 +68,17 @@ void clockevents_set_mode(struct clock_event_device *dev,
        if (dev->mode != mode) {
                dev->set_mode(mode, dev);
                dev->mode = mode;
+
+               /*
+                * A nsec2cyc multiplicator of 0 is invalid and we'd crash
+                * on it, so fix it up and emit a warning:
+                */
+               if (mode == CLOCK_EVT_MODE_ONESHOT) {
+                       if (unlikely(!dev->mult)) {
+                               dev->mult = 1;
+                               WARN_ON(1);
+                       }
+               }
        }
 }
 
@@ -168,15 +179,6 @@ void clockevents_register_device(struct clock_event_device *dev)
        BUG_ON(dev->mode != CLOCK_EVT_MODE_UNUSED);
        BUG_ON(!dev->cpumask);
 
-       /*
-        * A nsec2cyc multiplicator of 0 is invalid and we'd crash
-        * on it, so fix it up and emit a warning:
-        */
-       if (unlikely(!dev->mult)) {
-               dev->mult = 1;
-               WARN_ON(1);
-       }
-
        spin_lock(&clockevents_lock);
 
        list_add(&dev->list, &clockevent_devices);
index 7dcf6e9..9a236ff 100644 (file)
@@ -1737,9 +1737,12 @@ static void clear_ftrace_pid(struct pid *pid)
 {
        struct task_struct *p;
 
+       rcu_read_lock();
        do_each_pid_task(pid, PIDTYPE_PID, p) {
                clear_tsk_trace_trace(p);
        } while_each_pid_task(pid, PIDTYPE_PID, p);
+       rcu_read_unlock();
+
        put_pid(pid);
 }
 
@@ -1747,9 +1750,11 @@ static void set_ftrace_pid(struct pid *pid)
 {
        struct task_struct *p;
 
+       rcu_read_lock();
        do_each_pid_task(pid, PIDTYPE_PID, p) {
                set_tsk_trace_trace(p);
        } while_each_pid_task(pid, PIDTYPE_PID, p);
+       rcu_read_unlock();
 }
 
 static void clear_ftrace_pid_task(struct pid **pid)
index cd87131..42a2dbc 100644 (file)
@@ -91,6 +91,15 @@ prepare_to_wait_exclusive(wait_queue_head_t *q, wait_queue_t *wait, int state)
 }
 EXPORT_SYMBOL(prepare_to_wait_exclusive);
 
+/*
+ * finish_wait - clean up after waiting in a queue
+ * @q: waitqueue waited on
+ * @wait: wait descriptor
+ *
+ * Sets current thread back to running state and removes
+ * the wait descriptor from the given waitqueue if still
+ * queued.
+ */
 void finish_wait(wait_queue_head_t *q, wait_queue_t *wait)
 {
        unsigned long flags;
@@ -117,6 +126,39 @@ void finish_wait(wait_queue_head_t *q, wait_queue_t *wait)
 }
 EXPORT_SYMBOL(finish_wait);
 
+/*
+ * abort_exclusive_wait - abort exclusive waiting in a queue
+ * @q: waitqueue waited on
+ * @wait: wait descriptor
+ * @state: runstate of the waiter to be woken
+ * @key: key to identify a wait bit queue or %NULL
+ *
+ * Sets current thread back to running state and removes
+ * the wait descriptor from the given waitqueue if still
+ * queued.
+ *
+ * Wakes up the next waiter if the caller is concurrently
+ * woken up through the queue.
+ *
+ * This prevents waiter starvation where an exclusive waiter
+ * aborts and is woken up concurrently and noone wakes up
+ * the next waiter.
+ */
+void abort_exclusive_wait(wait_queue_head_t *q, wait_queue_t *wait,
+                       unsigned int mode, void *key)
+{
+       unsigned long flags;
+
+       __set_current_state(TASK_RUNNING);
+       spin_lock_irqsave(&q->lock, flags);
+       if (!list_empty(&wait->task_list))
+               list_del_init(&wait->task_list);
+       else if (waitqueue_active(q))
+               __wake_up_common(q, mode, 1, 0, key);
+       spin_unlock_irqrestore(&q->lock, flags);
+}
+EXPORT_SYMBOL(abort_exclusive_wait);
+
 int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key)
 {
        int ret = default_wake_function(wait, mode, sync, key);
@@ -177,17 +219,20 @@ int __sched
 __wait_on_bit_lock(wait_queue_head_t *wq, struct wait_bit_queue *q,
                        int (*action)(void *), unsigned mode)
 {
-       int ret = 0;
-
        do {
+               int ret;
+
                prepare_to_wait_exclusive(wq, &q->wait, mode);
-               if (test_bit(q->key.bit_nr, q->key.flags)) {
-                       if ((ret = (*action)(q->key.flags)))
-                               break;
-               }
+               if (!test_bit(q->key.bit_nr, q->key.flags))
+                       continue;
+               ret = action(q->key.flags);
+               if (!ret)
+                       continue;
+               abort_exclusive_wait(wq, &q->wait, mode, &q->key);
+               return ret;
        } while (test_and_set_bit(q->key.bit_nr, q->key.flags));
        finish_wait(wq, &q->wait);
-       return ret;
+       return 0;
 }
 EXPORT_SYMBOL(__wait_on_bit_lock);
 
index 22bfa7a..baa999e 100644 (file)
@@ -1999,7 +1999,7 @@ gotten:
         * Don't let another task, with possibly unlocked vma,
         * keep the mlocked page.
         */
-       if (vma->vm_flags & VM_LOCKED) {
+       if ((vma->vm_flags & VM_LOCKED) && old_page) {
                lock_page(old_page);    /* for LRU manipulation */
                clear_page_mlock(old_page);
                unlock_page(old_page);
index b493db7..dc32dae 100644 (file)
@@ -1051,13 +1051,22 @@ continue_unlock:
                                }
                        }
 
-                       if (wbc->sync_mode == WB_SYNC_NONE) {
-                               wbc->nr_to_write--;
-                               if (wbc->nr_to_write <= 0) {
-                                       done = 1;
-                                       break;
-                               }
+                       if (nr_to_write > 0)
+                               nr_to_write--;
+                       else if (wbc->sync_mode == WB_SYNC_NONE) {
+                               /*
+                                * We stop writing back only if we are not
+                                * doing integrity sync. In case of integrity
+                                * sync we have to keep going because someone
+                                * may be concurrently dirtying pages, and we
+                                * might have synced a lot of newly appeared
+                                * dirty pages, but have not synced all of the
+                                * old dirty pages.
+                                */
+                               done = 1;
+                               break;
                        }
+
                        if (wbc->nonblocking && bdi_write_congested(bdi)) {
                                wbc->encountered_congestion = 1;
                                done = 1;
index 557fe16..dda42f0 100644 (file)
@@ -663,14 +663,10 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
        th->urg_ptr             = 0;
 
        /* The urg_mode check is necessary during a below snd_una win probe */
-       if (unlikely(tcp_urg_mode(tp))) {
-               if (between(tp->snd_up, tcb->seq + 1, tcb->seq + 0xFFFF)) {
-                       th->urg_ptr = htons(tp->snd_up - tcb->seq);
-                       th->urg = 1;
-               } else if (after(tcb->seq + 0xFFFF, tp->snd_nxt)) {
-                       th->urg_ptr = 0xFFFF;
-                       th->urg = 1;
-               }
+       if (unlikely(tcp_urg_mode(tp) &&
+                    between(tp->snd_up, tcb->seq + 1, tcb->seq + 0xFFFF))) {
+               th->urg_ptr             = htons(tp->snd_up - tcb->seq);
+               th->urg                 = 1;
        }
 
        tcp_options_write((__be32 *)(th + 1), tp, &opts, &md5_hash_location);
index b7faffe..cc3a0a0 100644 (file)
@@ -1015,9 +1015,11 @@ static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
 
        if ((rc = sock_queue_rcv_skb(sk, skb)) < 0) {
                /* Note that an ENOMEM error is charged twice */
-               if (rc == -ENOMEM)
+               if (rc == -ENOMEM) {
                        UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_RCVBUFERRORS,
                                         is_udplite);
+                       atomic_inc(&sk->sk_drops);
+               }
                goto drop;
        }
 
@@ -1229,7 +1231,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
                   int proto)
 {
        struct sock *sk;
-       struct udphdr *uh = udp_hdr(skb);
+       struct udphdr *uh;
        unsigned short ulen;
        struct rtable *rt = (struct rtable*)skb->dst;
        __be32 saddr = ip_hdr(skb)->saddr;
@@ -1242,6 +1244,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
        if (!pskb_may_pull(skb, sizeof(struct udphdr)))
                goto drop;              /* No space for header. */
 
+       uh   = udp_hdr(skb);
        ulen = ntohs(uh->len);
        if (ulen > skb->len)
                goto short_packet;
index 4b15938..9fb49c3 100644 (file)
@@ -1105,6 +1105,18 @@ static inline int ip6_ufo_append_data(struct sock *sk,
        return err;
 }
 
+static inline struct ipv6_opt_hdr *ip6_opt_dup(struct ipv6_opt_hdr *src,
+                                              gfp_t gfp)
+{
+       return src ? kmemdup(src, (src->hdrlen + 1) * 8, gfp) : NULL;
+}
+
+static inline struct ipv6_rt_hdr *ip6_rthdr_dup(struct ipv6_rt_hdr *src,
+                                               gfp_t gfp)
+{
+       return src ? kmemdup(src, (src->hdrlen + 1) * 8, gfp) : NULL;
+}
+
 int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
        int offset, int len, int odd, struct sk_buff *skb),
        void *from, int length, int transhdrlen,
@@ -1130,17 +1142,37 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
                 * setup for corking
                 */
                if (opt) {
-                       if (np->cork.opt == NULL) {
-                               np->cork.opt = kmalloc(opt->tot_len,
-                                                      sk->sk_allocation);
-                               if (unlikely(np->cork.opt == NULL))
-                                       return -ENOBUFS;
-                       } else if (np->cork.opt->tot_len < opt->tot_len) {
-                               printk(KERN_DEBUG "ip6_append_data: invalid option length\n");
+                       if (WARN_ON(np->cork.opt))
                                return -EINVAL;
-                       }
-                       memcpy(np->cork.opt, opt, opt->tot_len);
-                       inet->cork.flags |= IPCORK_OPT;
+
+                       np->cork.opt = kmalloc(opt->tot_len, sk->sk_allocation);
+                       if (unlikely(np->cork.opt == NULL))
+                               return -ENOBUFS;
+
+                       np->cork.opt->tot_len = opt->tot_len;
+                       np->cork.opt->opt_flen = opt->opt_flen;
+                       np->cork.opt->opt_nflen = opt->opt_nflen;
+
+                       np->cork.opt->dst0opt = ip6_opt_dup(opt->dst0opt,
+                                                           sk->sk_allocation);
+                       if (opt->dst0opt && !np->cork.opt->dst0opt)
+                               return -ENOBUFS;
+
+                       np->cork.opt->dst1opt = ip6_opt_dup(opt->dst1opt,
+                                                           sk->sk_allocation);
+                       if (opt->dst1opt && !np->cork.opt->dst1opt)
+                               return -ENOBUFS;
+
+                       np->cork.opt->hopopt = ip6_opt_dup(opt->hopopt,
+                                                          sk->sk_allocation);
+                       if (opt->hopopt && !np->cork.opt->hopopt)
+                               return -ENOBUFS;
+
+                       np->cork.opt->srcrt = ip6_rthdr_dup(opt->srcrt,
+                                                           sk->sk_allocation);
+                       if (opt->srcrt && !np->cork.opt->srcrt)
+                               return -ENOBUFS;
+
                        /* need source address above miyazawa*/
                }
                dst_hold(&rt->u.dst);
@@ -1167,8 +1199,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
        } else {
                rt = (struct rt6_info *)inet->cork.dst;
                fl = &inet->cork.fl;
-               if (inet->cork.flags & IPCORK_OPT)
-                       opt = np->cork.opt;
+               opt = np->cork.opt;
                transhdrlen = 0;
                exthdrlen = 0;
                mtu = inet->cork.fragsize;
@@ -1407,9 +1438,15 @@ error:
 
 static void ip6_cork_release(struct inet_sock *inet, struct ipv6_pinfo *np)
 {
-       inet->cork.flags &= ~IPCORK_OPT;
-       kfree(np->cork.opt);
-       np->cork.opt = NULL;
+       if (np->cork.opt) {
+               kfree(np->cork.opt->dst0opt);
+               kfree(np->cork.opt->dst1opt);
+               kfree(np->cork.opt->hopopt);
+               kfree(np->cork.opt->srcrt);
+               kfree(np->cork.opt);
+               np->cork.opt = NULL;
+       }
+
        if (inet->cork.dst) {
                dst_release(inet->cork.dst);
                inet->cork.dst = NULL;
index 9454d4a..1fc4a78 100644 (file)
@@ -222,13 +222,13 @@ static void *packet_lookup_frame(struct packet_sock *po, unsigned int position,
        h.raw = po->pg_vec[pg_vec_pos] + (frame_offset * po->frame_size);
        switch (po->tp_version) {
        case TPACKET_V1:
-               if (status != h.h1->tp_status ? TP_STATUS_USER :
-                                               TP_STATUS_KERNEL)
+               if (status != (h.h1->tp_status ? TP_STATUS_USER :
+                                               TP_STATUS_KERNEL))
                        return NULL;
                break;
        case TPACKET_V2:
-               if (status != h.h2->tp_status ? TP_STATUS_USER :
-                                               TP_STATUS_KERNEL)
+               if (status != (h.h2->tp_status ? TP_STATUS_USER :
+                                               TP_STATUS_KERNEL))
                        return NULL;
                break;
        }
index dcef600..5592883 100644 (file)
@@ -6,7 +6,7 @@ config SUNRPC_GSS
 
 config SUNRPC_XPRT_RDMA
        tristate
-       depends on SUNRPC && INFINIBAND && EXPERIMENTAL
+       depends on SUNRPC && INFINIBAND && INFINIBAND_ADDR_TRANS && EXPERIMENTAL
        default SUNRPC && INFINIBAND
        help
          This option allows the NFS client and server to support
index e178366..0a1798e 100644 (file)
@@ -1767,7 +1767,7 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file)
                       AFMT_S8 | AFMT_U16_LE |
                       AFMT_U16_BE |
                        AFMT_S32_LE | AFMT_S32_BE |
-                       AFMT_S24_LE | AFMT_S24_LE |
+                       AFMT_S24_LE | AFMT_S24_BE |
                        AFMT_S24_PACKED;
        params = kmalloc(sizeof(*params), GFP_KERNEL);
        if (!params)
index b7bba7d..0b70813 100644 (file)
@@ -487,7 +487,6 @@ int /*__devinit*/ snd_hda_bus_new(struct snd_card *card,
 {
        struct hda_bus *bus;
        int err;
-       char qname[8];
        static struct snd_device_ops dev_ops = {
                .dev_register = snd_hda_bus_dev_register,
                .dev_free = snd_hda_bus_dev_free,
@@ -517,10 +516,12 @@ int /*__devinit*/ snd_hda_bus_new(struct snd_card *card,
        mutex_init(&bus->cmd_mutex);
        INIT_LIST_HEAD(&bus->codec_list);
 
-       snprintf(qname, sizeof(qname), "hda%d", card->number);
-       bus->workq = create_workqueue(qname);
+       snprintf(bus->workq_name, sizeof(bus->workq_name),
+                "hd-audio%d", card->number);
+       bus->workq = create_singlethread_workqueue(bus->workq_name);
        if (!bus->workq) {
-               snd_printk(KERN_ERR "cannot create workqueue %s\n", qname);
+               snd_printk(KERN_ERR "cannot create workqueue %s\n",
+                          bus->workq_name);
                kfree(bus);
                return -ENOMEM;
        }
index 5810ef5..09a332a 100644 (file)
@@ -614,6 +614,7 @@ struct hda_bus {
 
        /* unsolicited event queue */
        struct hda_bus_unsolicited *unsol;
+       char workq_name[16];
        struct workqueue_struct *workq; /* common workqueue for codecs */
 
        /* assigned PCMs */
index 7ca66d6..144b852 100644 (file)
@@ -399,7 +399,8 @@ static void print_conn_list(struct snd_info_buffer *buffer,
 {
        int c, curr = -1;
 
-       if (conn_len > 1 && wid_type != AC_WID_AUD_MIX)
+       if (conn_len > 1 && wid_type != AC_WID_AUD_MIX &&
+           wid_type != AC_WID_VOL_KNB)
                curr = snd_hda_codec_read(codec, nid, 0,
                                          AC_VERB_GET_CONNECT_SEL, 0);
        snd_iprintf(buffer, "  Connection: %d\n", conn_len);
index 7884a4e..ae5c8a0 100644 (file)
@@ -1037,6 +1037,7 @@ do_sku:
                case 0x10ec0267:
                case 0x10ec0268:
                case 0x10ec0269:
+               case 0x10ec0272:
                case 0x10ec0660:
                case 0x10ec0662:
                case 0x10ec0663:
@@ -1065,6 +1066,7 @@ do_sku:
                case 0x10ec0882:
                case 0x10ec0883:
                case 0x10ec0885:
+               case 0x10ec0887:
                case 0x10ec0889:
                        snd_hda_codec_write(codec, 0x20, 0,
                                            AC_VERB_SET_COEF_INDEX, 7);
@@ -7012,6 +7014,7 @@ static int patch_alc882(struct hda_codec *codec)
                        break;
                case 0x106b1000: /* iMac 24 */
                case 0x106b2800: /* AppleTV */
+               case 0x106b3e00: /* iMac 24 Aluminium */
                        board_config = ALC885_IMAC24;
                        break;
                case 0x106b00a1: /* Macbook (might be wrong - PCI SSID?) */
@@ -8514,6 +8517,8 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1558, 0, "Clevo laptop", ALC883_LAPTOP_EAPD),
        SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch),
        SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION),
+       SND_PCI_QUIRK(0x1734, 0x1107, "FSC AMILO Xi2550",
+                     ALC883_FUJITSU_PI2515),
        SND_PCI_QUIRK(0x1734, 0x1108, "Fujitsu AMILO Pi2515", ALC883_FUJITSU_PI2515),
        SND_PCI_QUIRK(0x1734, 0x113d, "Fujitsu AMILO Xa3530",
                ALC888_FUJITSU_XA3530),
index b787b3c..38428e2 100644 (file)
@@ -1804,6 +1804,8 @@ static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = {
                      "HP dv4", STAC_HP_DV5),
        SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30fc,
                      "HP dv7", STAC_HP_M4),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3600,
+                     "HP dv5", STAC_HP_DV5),
        SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3603,
                      "HP dv5", STAC_HP_DV5),
        SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x361a,
index 19d3391..e900cdc 100644 (file)
@@ -617,7 +617,7 @@ static int snd_intel8x0_ali_codec_semaphore(struct intel8x0 *chip)
        int time = 100;
        if (chip->buggy_semaphore)
                return 0; /* just ignore ... */
-       while (time-- && (igetdword(chip, ICHREG(ALI_CAS)) & ALI_CAS_SEM_BUSY))
+       while (--time && (igetdword(chip, ICHREG(ALI_CAS)) & ALI_CAS_SEM_BUSY))
                udelay(1);
        if (! time && ! chip->in_ac97_init)
                snd_printk(KERN_WARNING "ali_codec_semaphore timeout\n");
index c5d6790..ff0054b 100644 (file)
@@ -10,7 +10,7 @@
  * Based on at91-ssc.c by
  * Frank Mandarino <fmandarino@endrelia.com>
  * Based on pxa2xx Platform drivers by
- * Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ * Liam Girdwood <lrg@slimlogic.co.uk>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index a828746..391135f 100644 (file)
@@ -10,7 +10,7 @@
  * Based on at91-ssc.c by
  * Frank Mandarino <fmandarino@endrelia.com>
  * Based on pxa2xx Platform drivers by
- * Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ * Liam Girdwood <lrg@slimlogic.co.uk>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index e3989d4..35d9975 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2007, 2008 Wolfson Microelectronics PLC.
  *
- * Author: Liam Girdwood <lg@opensource.wolfsonmicro.com>
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
  *
  * 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
index 5b5afc1..1cbb7b9 100644 (file)
@@ -2,8 +2,7 @@
  * wm8990.c  --  WM8990 ALSA Soc Audio driver
  *
  * Copyright 2008 Wolfson Microelectronics PLC.
- * Author: Liam Girdwood
- *         lg@opensource.wolfsonmicro.com or linux@wolfsonmicro.com
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
  *
  *  This program is free software; you can redistribute  it and/or modify it
  *  under  the terms of  the GNU General  Public License as published by the
index b0362df..dd3bb29 100644 (file)
@@ -175,9 +175,10 @@ static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct omap_runtime_data *prtd = runtime->private_data;
+       unsigned long flags;
        int ret = 0;
 
-       spin_lock_irq(&prtd->lock);
+       spin_lock_irqsave(&prtd->lock, flags);
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_RESUME:
@@ -195,7 +196,7 @@ static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
        default:
                ret = -EINVAL;
        }
-       spin_unlock_irq(&prtd->lock);
+       spin_unlock_irqrestore(&prtd->lock, flags);
 
        return ret;
 }
index c709b95..2ab8312 100644 (file)
@@ -2966,6 +2966,7 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
                return -EINVAL;
        }
        alts = &iface->altsetting[fp->altset_idx];
+       fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
        usb_set_interface(chip->dev, fp->iface, 0);
        init_usb_pitch(chip->dev, fp->iface, alts, fp);
        init_usb_sample_rate(chip->dev, fp->iface, alts, fp, fp->rate_max);