]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge commit 'v2.6.27-rc6' into sched/devel
authorIngo Molnar <mingo@elte.hu>
Thu, 11 Sep 2008 11:37:28 +0000 (13:37 +0200)
committerIngo Molnar <mingo@elte.hu>
Thu, 11 Sep 2008 11:37:28 +0000 (13:37 +0200)
113 files changed:
Documentation/filesystems/Locking
MAINTAINERS
Makefile
arch/arm/include/asm/io.h
arch/arm/include/asm/mach/map.h
arch/arm/mach-omap1/mcbsp.c
arch/arm/mach-omap2/mcbsp.c
arch/arm/mm/mmu.c
arch/arm/plat-mxc/clock.c
arch/arm/plat-omap/gpio.c
arch/arm/plat-omap/include/mach/mcbsp.h
arch/arm/plat-omap/mcbsp.c
arch/avr32/kernel/asm-offsets.c
arch/avr32/kernel/entry-avr32b.S
arch/avr32/mach-at32ap/pm-at32ap700x.S
arch/ia64/include/asm/sections.h
arch/ia64/kernel/module.c
arch/mips/Kconfig
arch/mips/kernel/setup.c
arch/mips/kernel/traps.c
arch/mips/mm/c-r3k.c
arch/mips/mm/c-r4k.c
arch/mips/mm/c-tx39.c
arch/mips/mm/cache.c
arch/mips/mm/tlbex.c
arch/mips/sgi-ip22/ip22-platform.c
arch/mips/txx9/generic/setup.c
arch/parisc/kernel/module.c
arch/powerpc/boot/Makefile
arch/powerpc/include/asm/sections.h
arch/powerpc/kernel/module_64.c
arch/powerpc/platforms/cell/spufs/sched.c
arch/s390/kernel/compat_ptrace.h
arch/s390/kernel/ptrace.c
arch/sparc64/kernel/irq.c
arch/sparc64/kernel/smp.c
arch/x86/Kconfig.cpu
arch/x86/boot/cpucheck.c
arch/x86/kernel/alternative.c
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/centaur.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpu/common_64.c
arch/x86/kernel/cpu/cyrix.c
arch/x86/kernel/cpu/feature_names.c
arch/x86/kernel/e820.c
arch/x86/kernel/hpet.c
arch/x86/xen/enlighten.c
crypto/camellia.c
drivers/ata/Kconfig
drivers/ata/ahci.c
drivers/ata/libata-sff.c
drivers/ata/pata_marvell.c
drivers/ata/pata_sil680.c
drivers/ata/sata_mv.c
drivers/ata/sata_nv.c
drivers/clocksource/acpi_pm.c
drivers/input/mouse/bcm5974.c
drivers/input/serio/i8042-x86ia64io.h
drivers/s390/cio/chp.c
drivers/s390/cio/cio.c
drivers/s390/cio/css.c
drivers/s390/cio/device_fsm.c
drivers/usb/host/ohci-omap.c
drivers/usb/serial/console.c
drivers/xen/balloon.c
fs/nfs/super.c
fs/ubifs/budget.c
fs/ubifs/dir.c
fs/ubifs/file.c
fs/ubifs/find.c
fs/ubifs/gc.c
fs/ubifs/misc.h
fs/ubifs/super.c
fs/ubifs/tnc.c
fs/ubifs/ubifs-media.h
fs/ubifs/ubifs.h
include/asm-generic/sections.h
include/asm-mips/cacheflush.h
include/asm-parisc/sections.h
include/asm-x86/cpufeature.h
include/asm-x86/required-features.h
include/linux/clockchips.h
include/linux/cpuset.h
include/net/bluetooth/hci_core.h
include/net/inet_timewait_sock.h
kernel/cpuset.c
kernel/sched.c
kernel/time/clockevents.c
kernel/time/ntp.c
kernel/time/tick-broadcast.c
kernel/time/tick-common.c
kernel/time/tick-internal.h
kernel/time/tick-oneshot.c
lib/vsprintf.c
net/bluetooth/af_bluetooth.c
net/bluetooth/hci_conn.c
net/bluetooth/hci_event.c
net/bluetooth/l2cap.c
net/bluetooth/sco.c
net/bridge/br_ioctl.c
net/bridge/br_sysfs_br.c
net/core/dev.c
net/ipv4/inet_timewait_sock.c
net/ipv4/tcp_ipv4.c
net/ipv6/ip6_output.c
net/ipv6/tcp_ipv6.c
net/netfilter/nf_conntrack_irc.c
net/netfilter/nf_conntrack_proto_gre.c
net/netfilter/nf_conntrack_sip.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_state.c
sound/Kconfig

index 680fb566b9286bcc71a527c5f75d4b94fc9ac215..8362860e21a7d6b4db3595e83905b32b25e55ecf 100644 (file)
@@ -144,8 +144,8 @@ prototypes:
        void (*kill_sb) (struct super_block *);
 locking rules:
                may block       BKL
-get_sb         yes             yes
-kill_sb                yes             yes
+get_sb         yes             no
+kill_sb                yes             no
 
 ->get_sb() returns error or 0 with locked superblock attached to the vfsmount
 (exclusive on ->s_umount).
@@ -409,12 +409,12 @@ ioctl:                    yes     (see below)
 unlocked_ioctl:                no      (see below)
 compat_ioctl:          no
 mmap:                  no
-open:                  maybe   (see below)
+open:                  no
 flush:                 no
 release:               no
 fsync:                 no      (see below)
 aio_fsync:             no
-fasync:                        yes     (see below)
+fasync:                        no
 lock:                  yes
 readv:                 no
 writev:                        no
@@ -431,13 +431,6 @@ For many filesystems, it is probably safe to acquire the inode
 semaphore.  Note some filesystems (i.e. remote ones) provide no
 protection for i_size so you will need to use the BKL.
 
-->open() locking is in-transit: big lock partially moved into the methods.
-The only exception is ->open() in the instances of file_operations that never
-end up in ->i_fop/->proc_fops, i.e. ones that belong to character devices
-(chrdev_open() takes lock before replacing ->f_op and calling the secondary
-method. As soon as we fix the handling of module reference counters all
-instances of ->open() will be called without the BKL.
-
 Note: ext2_release() was *the* source of contention on fs-intensive
 loads and dropping BKL on ->release() helps to get rid of that (we still
 grab BKL for cases when we close a file that had been opened r/w, but that
index af279458b6140f065bb89afb891747a70e098702..186be3ba50694c2c7a10f98cb9eaf2fd4c153b6f 100644 (file)
@@ -750,11 +750,13 @@ P:        Ville Syrjala
 M:     syrjala@sci.fi
 S:     Maintained
 
-ATL1 ETHERNET DRIVER
+ATLX ETHERNET DRIVERS
 P:     Jay Cliburn
 M:     jcliburn@gmail.com
 P:     Chris Snook
 M:     csnook@redhat.com
+P:     Jie Yang
+M:     jie.yang@atheros.com
 L:     atl1-devel@lists.sourceforge.net
 W:     http://sourceforge.net/projects/atl1
 W:     http://atl1.sourceforge.net
@@ -1593,7 +1595,7 @@ S:        Supported
 EMBEDDED LINUX
 P:     Paul Gortmaker
 M:     paul.gortmaker@windriver.com
-P      David Woodhouse
+P:     David Woodhouse
 M:     dwmw2@infradead.org
 L:     linux-embedded@vger.kernel.org
 S:     Maintained
index f448e0082ebf6726ba4a644164e5194edced6ff0..4ff83ea36c1920e585a63937e9887d703af04089 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 27
-EXTRAVERSION = -rc5
+EXTRAVERSION = -rc6
 NAME = Rotary Wombat
 
 # *DOCUMENTATION*
index 94a95d7fafd6cdaf887e26dcfad35dbe6590c39a..71934856fc22c38ede7ab9f4a6c1380d9e1dad5d 100644 (file)
@@ -61,8 +61,9 @@ extern void __raw_readsl(const void __iomem *addr, void *data, int longlen);
 #define MT_DEVICE_NONSHARED    1
 #define MT_DEVICE_CACHED       2
 #define MT_DEVICE_IXP2000      3
+#define MT_DEVICE_WC           4
 /*
- * types 4 onwards can be found in asm/mach/map.h and are undefined
+ * types 5 onwards can be found in asm/mach/map.h and are undefined
  * for ioremap
  */
 
@@ -215,11 +216,13 @@ extern void _memset_io(volatile void __iomem *, int, size_t);
 #define ioremap(cookie,size)           __arm_ioremap(cookie, size, MT_DEVICE)
 #define ioremap_nocache(cookie,size)   __arm_ioremap(cookie, size, MT_DEVICE)
 #define ioremap_cached(cookie,size)    __arm_ioremap(cookie, size, MT_DEVICE_CACHED)
+#define ioremap_wc(cookie,size)                __arm_ioremap(cookie, size, MT_DEVICE_WC)
 #define iounmap(cookie)                        __iounmap(cookie)
 #else
 #define ioremap(cookie,size)           __arch_ioremap((cookie), (size), MT_DEVICE)
 #define ioremap_nocache(cookie,size)   __arch_ioremap((cookie), (size), MT_DEVICE)
 #define ioremap_cached(cookie,size)    __arch_ioremap((cookie), (size), MT_DEVICE_CACHED)
+#define ioremap_wc(cookie,size)                __arch_ioremap((cookie), (size), MT_DEVICE_WC)
 #define iounmap(cookie)                        __arch_iounmap(cookie)
 #endif
 
index 06f583b13999c220ba835658c657460ccb1a5783..9eb936e49cc349564f651ea973f71e6cdd273ee9 100644 (file)
@@ -18,13 +18,13 @@ struct map_desc {
        unsigned int type;
 };
 
-/* types 0-3 are defined in asm/io.h */
-#define MT_CACHECLEAN          4
-#define MT_MINICLEAN           5
-#define MT_LOW_VECTORS         6
-#define MT_HIGH_VECTORS                7
-#define MT_MEMORY              8
-#define MT_ROM                 9
+/* types 0-4 are defined in asm/io.h */
+#define MT_CACHECLEAN          5
+#define MT_MINICLEAN           6
+#define MT_LOW_VECTORS         7
+#define MT_HIGH_VECTORS                8
+#define MT_MEMORY              9
+#define MT_ROM                 10
 
 #define MT_NONSHARED_DEVICE    MT_DEVICE_NONSHARED
 #define MT_IXP2000_DEVICE      MT_DEVICE_IXP2000
index 826010d5d014f26f96df045d7e195c6359b9c997..2baeaeb0c9004d2038a7c1fde8b398068de77810 100644 (file)
@@ -159,6 +159,7 @@ static struct omap_mcbsp_ops omap1_mcbsp_ops = {
 #ifdef CONFIG_ARCH_OMAP730
 static struct omap_mcbsp_platform_data omap730_mcbsp_pdata[] = {
        {
+               .phys_base      = OMAP730_MCBSP1_BASE,
                .virt_base      = io_p2v(OMAP730_MCBSP1_BASE),
                .dma_rx_sync    = OMAP_DMA_MCBSP1_RX,
                .dma_tx_sync    = OMAP_DMA_MCBSP1_TX,
@@ -167,6 +168,7 @@ static struct omap_mcbsp_platform_data omap730_mcbsp_pdata[] = {
                .ops            = &omap1_mcbsp_ops,
        },
        {
+               .phys_base      = OMAP730_MCBSP2_BASE,
                .virt_base      = io_p2v(OMAP730_MCBSP2_BASE),
                .dma_rx_sync    = OMAP_DMA_MCBSP3_RX,
                .dma_tx_sync    = OMAP_DMA_MCBSP3_TX,
@@ -184,6 +186,7 @@ static struct omap_mcbsp_platform_data omap730_mcbsp_pdata[] = {
 #ifdef CONFIG_ARCH_OMAP15XX
 static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
        {
+               .phys_base      = OMAP1510_MCBSP1_BASE,
                .virt_base      = OMAP1510_MCBSP1_BASE,
                .dma_rx_sync    = OMAP_DMA_MCBSP1_RX,
                .dma_tx_sync    = OMAP_DMA_MCBSP1_TX,
@@ -193,6 +196,7 @@ static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
                .clk_name       = "mcbsp_clk",
                },
        {
+               .phys_base      = OMAP1510_MCBSP2_BASE,
                .virt_base      = io_p2v(OMAP1510_MCBSP2_BASE),
                .dma_rx_sync    = OMAP_DMA_MCBSP2_RX,
                .dma_tx_sync    = OMAP_DMA_MCBSP2_TX,
@@ -201,6 +205,7 @@ static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
                .ops            = &omap1_mcbsp_ops,
        },
        {
+               .phys_base      = OMAP1510_MCBSP3_BASE,
                .virt_base      = OMAP1510_MCBSP3_BASE,
                .dma_rx_sync    = OMAP_DMA_MCBSP3_RX,
                .dma_tx_sync    = OMAP_DMA_MCBSP3_TX,
@@ -219,6 +224,7 @@ static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
 #ifdef CONFIG_ARCH_OMAP16XX
 static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
        {
+               .phys_base      = OMAP1610_MCBSP1_BASE,
                .virt_base      = OMAP1610_MCBSP1_BASE,
                .dma_rx_sync    = OMAP_DMA_MCBSP1_RX,
                .dma_tx_sync    = OMAP_DMA_MCBSP1_TX,
@@ -228,6 +234,7 @@ static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
                .clk_name       = "mcbsp_clk",
        },
        {
+               .phys_base      = OMAP1610_MCBSP2_BASE,
                .virt_base      = io_p2v(OMAP1610_MCBSP2_BASE),
                .dma_rx_sync    = OMAP_DMA_MCBSP2_RX,
                .dma_tx_sync    = OMAP_DMA_MCBSP2_TX,
@@ -236,6 +243,7 @@ static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
                .ops            = &omap1_mcbsp_ops,
        },
        {
+               .phys_base      = OMAP1610_MCBSP3_BASE,
                .virt_base      = OMAP1610_MCBSP3_BASE,
                .dma_rx_sync    = OMAP_DMA_MCBSP3_RX,
                .dma_tx_sync    = OMAP_DMA_MCBSP3_TX,
index 27eb6e3ca92622d98111b2d9bb030837541e1b30..b261f1f80b5e0fd7131a5586ca04bb6d9796a3ea 100644 (file)
@@ -134,6 +134,7 @@ static struct omap_mcbsp_ops omap2_mcbsp_ops = {
 #ifdef CONFIG_ARCH_OMAP24XX
 static struct omap_mcbsp_platform_data omap24xx_mcbsp_pdata[] = {
        {
+               .phys_base      = OMAP24XX_MCBSP1_BASE,
                .virt_base      = IO_ADDRESS(OMAP24XX_MCBSP1_BASE),
                .dma_rx_sync    = OMAP24XX_DMA_MCBSP1_RX,
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP1_TX,
@@ -143,6 +144,7 @@ static struct omap_mcbsp_platform_data omap24xx_mcbsp_pdata[] = {
                .clk_name       = "mcbsp_clk",
        },
        {
+               .phys_base      = OMAP24XX_MCBSP2_BASE,
                .virt_base      = IO_ADDRESS(OMAP24XX_MCBSP2_BASE),
                .dma_rx_sync    = OMAP24XX_DMA_MCBSP2_RX,
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP2_TX,
@@ -161,6 +163,7 @@ static struct omap_mcbsp_platform_data omap24xx_mcbsp_pdata[] = {
 #ifdef CONFIG_ARCH_OMAP34XX
 static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
        {
+               .phys_base      = OMAP34XX_MCBSP1_BASE,
                .virt_base      = IO_ADDRESS(OMAP34XX_MCBSP1_BASE),
                .dma_rx_sync    = OMAP24XX_DMA_MCBSP1_RX,
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP1_TX,
@@ -170,6 +173,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
                .clk_name       = "mcbsp_clk",
        },
        {
+               .phys_base      = OMAP34XX_MCBSP2_BASE,
                .virt_base      = IO_ADDRESS(OMAP34XX_MCBSP2_BASE),
                .dma_rx_sync    = OMAP24XX_DMA_MCBSP2_RX,
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP2_TX,
index 25d9a11eb61750ade3ba77abd7771068ebe668ee..a713e40e1f1a718549f333327c0f1a234e38a12c 100644 (file)
@@ -211,6 +211,12 @@ static struct mem_type mem_types[] = {
                                  PMD_SECT_TEX(1),
                .domain         = DOMAIN_IO,
        },
+       [MT_DEVICE_WC] = {      /* ioremap_wc */
+               .prot_pte       = PROT_PTE_DEVICE,
+               .prot_l1        = PMD_TYPE_TABLE,
+               .prot_sect      = PROT_SECT_DEVICE,
+               .domain         = DOMAIN_IO,
+       },
        [MT_CACHECLEAN] = {
                .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN,
                .domain    = DOMAIN_KERNEL,
@@ -272,6 +278,20 @@ static void __init build_mem_type_table(void)
                ecc_mask = 0;
        }
 
+       /*
+        * On non-Xscale3 ARMv5-and-older systems, use CB=01
+        * (Uncached/Buffered) for ioremap_wc() mappings.  On XScale3
+        * and ARMv6+, use TEXCB=00100 mappings (Inner/Outer Uncacheable
+        * in xsc3 parlance, Uncached Normal in ARMv6 parlance).
+        */
+       if (cpu_is_xsc3() || cpu_arch >= CPU_ARCH_ARMv6) {
+               mem_types[MT_DEVICE_WC].prot_pte_ext |= PTE_EXT_TEX(1);
+               mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_TEX(1);
+       } else {
+               mem_types[MT_DEVICE_WC].prot_pte |= L_PTE_BUFFERABLE;
+               mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_BUFFERABLE;
+       }
+
        /*
         * ARMv5 and lower, bit 4 must be set for page tables.
         * (was: cache "update-able on write" bit on ARM610)
index 2f8627218839130ccdba3c23c5f1d6b968b190f6..0a38f0b396eb997ce558584676ff3d1b2e8c49bc 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/proc_fs.h>
 #include <linux/semaphore.h>
 #include <linux/string.h>
-#include <linux/version.h>
 
 #include <mach/clock.h>
 
index 3e76ee2bc731dfd91d7e6fb00461a9a43e9b6c55..9e1341ebc14e8842646ae8a53fb2aa9307031b69 100644 (file)
@@ -1488,7 +1488,7 @@ static int __init _omap_gpio_init(void)
                bank->chip.set = gpio_set;
                if (bank_is_mpuio(bank)) {
                        bank->chip.label = "mpuio";
-#ifdef CONFIG_ARCH_OMAP1
+#ifdef CONFIG_ARCH_OMAP16XX
                        bank->chip.dev = &omap_mpuio_device.dev;
 #endif
                        bank->chip.base = OMAP_MPUIO(0);
index 6eb44a92871db97961644ef2d147f30b5f1632cd..8fdb95e26fcd86775fe4fd494139e381b17f76e5 100644 (file)
@@ -315,6 +315,7 @@ struct omap_mcbsp_ops {
 };
 
 struct omap_mcbsp_platform_data {
+       unsigned long phys_base;
        u32 virt_base;
        u8 dma_rx_sync, dma_tx_sync;
        u16 rx_irq, tx_irq;
@@ -324,6 +325,7 @@ struct omap_mcbsp_platform_data {
 
 struct omap_mcbsp {
        struct device *dev;
+       unsigned long phys_base;
        u32 io_base;
        u8 id;
        u8 free;
index d0844050f2d2da0febf9e95e287f032ed95f3ef7..014d26574bb61cd52267db7edfff9ad439e0c4bd 100644 (file)
@@ -651,7 +651,7 @@ int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer,
        omap_set_dma_dest_params(mcbsp[id].dma_tx_lch,
                                 src_port,
                                 OMAP_DMA_AMODE_CONSTANT,
-                                mcbsp[id].io_base + OMAP_MCBSP_REG_DXR1,
+                                mcbsp[id].phys_base + OMAP_MCBSP_REG_DXR1,
                                 0, 0);
 
        omap_set_dma_src_params(mcbsp[id].dma_tx_lch,
@@ -712,7 +712,7 @@ int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer,
        omap_set_dma_src_params(mcbsp[id].dma_rx_lch,
                                src_port,
                                OMAP_DMA_AMODE_CONSTANT,
-                               mcbsp[id].io_base + OMAP_MCBSP_REG_DRR1,
+                               mcbsp[id].phys_base + OMAP_MCBSP_REG_DRR1,
                                0, 0);
 
        omap_set_dma_dest_params(mcbsp[id].dma_rx_lch,
@@ -830,6 +830,7 @@ static int __init omap_mcbsp_probe(struct platform_device *pdev)
        mcbsp[id].dma_tx_lch = -1;
        mcbsp[id].dma_rx_lch = -1;
 
+       mcbsp[id].phys_base = pdata->phys_base;
        mcbsp[id].io_base = pdata->virt_base;
        /* Default I/O is IRQ based */
        mcbsp[id].io_type = OMAP_MCBSP_IRQ_IO;
index e4796c67a831aa930208c736de6722b1a460891b..d6a8193a1d2f09c8d9356212db5bd6ae44efeda4 100644 (file)
@@ -4,6 +4,8 @@
  * to extract and format the required data.
  */
 
+#include <linux/mm.h>
+#include <linux/sched.h>
 #include <linux/thread_info.h>
 #include <linux/kbuild.h>
 
@@ -17,4 +19,8 @@ void foo(void)
        OFFSET(TI_rar_saved, thread_info, rar_saved);
        OFFSET(TI_rsr_saved, thread_info, rsr_saved);
        OFFSET(TI_restart_block, thread_info, restart_block);
+       BLANK();
+       OFFSET(TSK_active_mm, task_struct, active_mm);
+       BLANK();
+       OFFSET(MM_pgd, mm_struct, pgd);
 }
index 2b398cae110c839fc5b3c3be3d9d7a48fcf3a2ec..33d49377b8beda6ae217cf40928d304d5eabfa6d 100644 (file)
@@ -334,9 +334,64 @@ save_full_context_ex:
 
        /* Low-level exception handlers */
 handle_critical:
+       /*
+        * AT32AP700x errata:
+        *
+        * After a Java stack overflow or underflow trap, any CPU
+        * memory access may cause erratic behavior. This will happen
+        * when the four least significant bits of the JOSP system
+        * register contains any value between 9 and 15 (inclusive).
+        *
+        * Possible workarounds:
+        *   - Don't use the Java Extension Module
+        *   - Ensure that the stack overflow and underflow trap
+        *     handlers do not do any memory access or trigger any
+        *     exceptions before the overflow/underflow condition is
+        *     cleared (by incrementing or decrementing the JOSP)
+        *   - Make sure that JOSP does not contain any problematic
+        *     value before doing any exception or interrupt
+        *     processing.
+        *   - Set up a critical exception handler which writes a
+        *     known-to-be-safe value, e.g. 4, to JOSP before doing
+        *     any further processing.
+        *
+        * We'll use the last workaround for now since we cannot
+        * guarantee that user space processes don't use Java mode.
+        * Non-well-behaving userland will be terminated with extreme
+        * prejudice.
+        */
+#ifdef CONFIG_CPU_AT32AP700X
+       /*
+        * There's a chance we can't touch memory, so temporarily
+        * borrow PTBR to save the stack pointer while we fix things
+        * up...
+        */
+       mtsr    SYSREG_PTBR, sp
+       mov     sp, 4
+       mtsr    SYSREG_JOSP, sp
+       mfsr    sp, SYSREG_PTBR
+       sub     pc, -2
+
+       /* Push most of pt_regs on stack. We'll do the rest later */
        sub     sp, 4
-       stmts   --sp, r0-lr
-       rcall   save_full_context_ex
+       pushm   r0-r12
+
+       /* PTBR mirrors current_thread_info()->task->active_mm->pgd */
+       get_thread_info r0
+       ld.w    r1, r0[TI_task]
+       ld.w    r2, r1[TSK_active_mm]
+       ld.w    r3, r2[MM_pgd]
+       mtsr    SYSREG_PTBR, r3
+#else
+       sub     sp, 4
+       pushm   r0-r12
+#endif
+       sub     r0, sp, -(14 * 4)
+       mov     r1, lr
+       mfsr    r2, SYSREG_RAR_EX
+       mfsr    r3, SYSREG_RSR_EX
+       pushm   r0-r3
+
        mfsr    r12, SYSREG_ECR
        mov     r11, sp
        rcall   do_critical_exception
index 5be4de65b209661edbaab3851f7283149c96dba0..17503b0ed6c9b3f5865406fb0d5f44241ce6bab7 100644 (file)
@@ -134,7 +134,7 @@ pm_standby:
        mov     r11, SDRAMC_LPR_LPCB_SELF_RFR
        bfins   r10, r11, 0, 2          /* LPCB <- self Refresh */
        sync    0                       /* flush write buffer */
-       st.w    r12[SDRAMC_LPR], r11    /* put SDRAM in self-refresh mode */
+       st.w    r12[SDRAMC_LPR], r10    /* put SDRAM in self-refresh mode */
        ld.w    r11, r12[SDRAMC_LPR]
        unmask_interrupts
        sleep   CPU_SLEEP_FROZEN
index 7286e4a9fe8449e1b02e5e762eb9dc7e1aeb53ce..a7acad2bc2f0b0f14f6b608bf43224b4411ce9d5 100644 (file)
@@ -21,5 +21,8 @@ extern char __start_gate_brl_fsys_bubble_down_patchlist[], __end_gate_brl_fsys_b
 extern char __start_unwind[], __end_unwind[];
 extern char __start_ivt_text[], __end_ivt_text[];
 
+#undef dereference_function_descriptor
+void *dereference_function_descriptor(void *);
+
 #endif /* _ASM_IA64_SECTIONS_H */
 
index 29aad349e0c4fafd49eb6b8c07bce2f3db3a24d6..545626f66a4c571c65bcd8a5ae3a8e855db48012 100644 (file)
 #include <linux/elf.h>
 #include <linux/moduleloader.h>
 #include <linux/string.h>
+#include <linux/uaccess.h>
 #include <linux/vmalloc.h>
 
 #include <asm/patch.h>
+#include <asm/sections.h>
 #include <asm/unaligned.h>
 
 #define ARCH_MODULE_DEBUG 0
@@ -941,3 +943,13 @@ module_arch_cleanup (struct module *mod)
        if (mod->arch.core_unw_table)
                unw_remove_unwind_table(mod->arch.core_unw_table);
 }
+
+void *dereference_function_descriptor(void *ptr)
+{
+       struct fdesc *desc = ptr;
+       void *p;
+
+       if (!probe_kernel_address(&desc->ip, p))
+               ptr = p;
+       return ptr;
+}
index 4da736e25333abc8ce46440dcb8b97c4c9f2be9d..49896a2a1d722e0760a866487f8b80b7d8af8fb0 100644 (file)
@@ -1886,6 +1886,15 @@ config STACKTRACE_SUPPORT
 
 source "init/Kconfig"
 
+config PROBE_INITRD_HEADER
+       bool "Probe initrd header created by addinitrd"
+       depends on BLK_DEV_INITRD
+       help
+         Probe initrd header at the last page of kernel image.
+         Say Y here if you are using arch/mips/boot/addinitrd.c to
+         add initrd or initramfs image to the kernel image.
+         Otherwise, say N.
+
 menu "Bus options (PCI, PCMCIA, EISA, ISA, TC)"
 
 config HW_HAS_EISA
index 2aae76bce29355183f9697cb314dec3306d89af5..16f8edfe5cdce81a63d850980cb0dda08e94049f 100644 (file)
@@ -160,30 +160,33 @@ early_param("rd_size", rd_size_early);
 static unsigned long __init init_initrd(void)
 {
        unsigned long end;
-       u32 *initrd_header;
 
        /*
         * Board specific code or command line parser should have
         * already set up initrd_start and initrd_end. In these cases
         * perfom sanity checks and use them if all looks good.
         */
-       if (initrd_start && initrd_end > initrd_start)
-               goto sanitize;
+       if (!initrd_start || initrd_end <= initrd_start) {
+#ifdef CONFIG_PROBE_INITRD_HEADER
+               u32 *initrd_header;
 
-       /*
-        * See if initrd has been added to the kernel image by
-        * arch/mips/boot/addinitrd.c. In that case a header is
-        * prepended to initrd and is made up by 8 bytes. The fisrt
-        * word is a magic number and the second one is the size of
-        * initrd.  Initrd start must be page aligned in any cases.
-        */
-       initrd_header = __va(PAGE_ALIGN(__pa_symbol(&_end) + 8)) - 8;
-       if (initrd_header[0] != 0x494E5244)
+               /*
+                * See if initrd has been added to the kernel image by
+                * arch/mips/boot/addinitrd.c. In that case a header is
+                * prepended to initrd and is made up by 8 bytes. The first
+                * word is a magic number and the second one is the size of
+                * initrd.  Initrd start must be page aligned in any cases.
+                */
+               initrd_header = __va(PAGE_ALIGN(__pa_symbol(&_end) + 8)) - 8;
+               if (initrd_header[0] != 0x494E5244)
+                       goto disable;
+               initrd_start = (unsigned long)(initrd_header + 2);
+               initrd_end = initrd_start + initrd_header[1];
+#else
                goto disable;
-       initrd_start = (unsigned long)(initrd_header + 2);
-       initrd_end = initrd_start + initrd_header[1];
+#endif
+       }
 
-sanitize:
        if (initrd_start & ~PAGE_MASK) {
                pr_err("initrd start must be page aligned\n");
                goto disable;
index 426cced1e9dce3e4d6e560fad38d26136a8c02e9..6bee29097a565e71459f80ee75c3affd3d0ed25b 100644 (file)
@@ -373,8 +373,8 @@ void __noreturn die(const char * str, const struct pt_regs * regs)
        do_exit(SIGSEGV);
 }
 
-extern const struct exception_table_entry __start___dbe_table[];
-extern const struct exception_table_entry __stop___dbe_table[];
+extern struct exception_table_entry __start___dbe_table[];
+extern struct exception_table_entry __stop___dbe_table[];
 
 __asm__(
 "      .section        __dbe_table, \"a\"\n"
@@ -1200,7 +1200,7 @@ void *set_except_vector(int n, void *addr)
        if (n == 0 && cpu_has_divec) {
                *(u32 *)(ebase + 0x200) = 0x08000000 |
                                          (0x03ffffff & (handler >> 2));
-               flush_icache_range(ebase + 0x200, ebase + 0x204);
+               local_flush_icache_range(ebase + 0x200, ebase + 0x204);
        }
        return (void *)old_handler;
 }
@@ -1283,7 +1283,8 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
                *w = (*w & 0xffff0000) | (((u32)handler >> 16) & 0xffff);
                w = (u32 *)(b + ori_offset);
                *w = (*w & 0xffff0000) | ((u32)handler & 0xffff);
-               flush_icache_range((unsigned long)b, (unsigned long)(b+handler_len));
+               local_flush_icache_range((unsigned long)b,
+                                        (unsigned long)(b+handler_len));
        }
        else {
                /*
@@ -1295,7 +1296,8 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
                w = (u32 *)b;
                *w++ = 0x08000000 | (((u32)handler >> 2) & 0x03fffff); /* j handler */
                *w = 0;
-               flush_icache_range((unsigned long)b, (unsigned long)(b+8));
+               local_flush_icache_range((unsigned long)b,
+                                        (unsigned long)(b+8));
        }
 
        return (void *)old_handler;
@@ -1515,7 +1517,7 @@ void __cpuinit per_cpu_trap_init(void)
 void __init set_handler(unsigned long offset, void *addr, unsigned long size)
 {
        memcpy((void *)(ebase + offset), addr, size);
-       flush_icache_range(ebase + offset, ebase + offset + size);
+       local_flush_icache_range(ebase + offset, ebase + offset + size);
 }
 
 static char panic_null_cerr[] __cpuinitdata =
@@ -1680,6 +1682,8 @@ void __init trap_init(void)
        signal32_init();
 #endif
 
-       flush_icache_range(ebase, ebase + 0x400);
+       local_flush_icache_range(ebase, ebase + 0x400);
        flush_tlb_handlers();
+
+       sort_extable(__start___dbe_table, __stop___dbe_table);
 }
index 27a5b466c85ce0ef4f859ea47402dfd2d77f112c..5500c20c79aeafc491c3b9b43cbe8f5e816e084c 100644 (file)
@@ -320,6 +320,7 @@ void __cpuinit r3k_cache_init(void)
        flush_cache_range = r3k_flush_cache_range;
        flush_cache_page = r3k_flush_cache_page;
        flush_icache_range = r3k_flush_icache_range;
+       local_flush_icache_range = r3k_flush_icache_range;
 
        flush_cache_sigtramp = r3k_flush_cache_sigtramp;
        local_flush_data_cache_page = local_r3k_flush_data_cache_page;
index 71df3390c07bf76608ee9c25f3896f9d93eda94c..6e99665ae860e540cafee642d5d3daf0c1537738 100644 (file)
@@ -543,12 +543,8 @@ struct flush_icache_range_args {
        unsigned long end;
 };
 
-static inline void local_r4k_flush_icache_range(void *args)
+static inline void local_r4k_flush_icache_range(unsigned long start, unsigned long end)
 {
-       struct flush_icache_range_args *fir_args = args;
-       unsigned long start = fir_args->start;
-       unsigned long end = fir_args->end;
-
        if (!cpu_has_ic_fills_f_dc) {
                if (end - start >= dcache_size) {
                        r4k_blast_dcache();
@@ -564,6 +560,15 @@ static inline void local_r4k_flush_icache_range(void *args)
                protected_blast_icache_range(start, end);
 }
 
+static inline void local_r4k_flush_icache_range_ipi(void *args)
+{
+       struct flush_icache_range_args *fir_args = args;
+       unsigned long start = fir_args->start;
+       unsigned long end = fir_args->end;
+
+       local_r4k_flush_icache_range(start, end);
+}
+
 static void r4k_flush_icache_range(unsigned long start, unsigned long end)
 {
        struct flush_icache_range_args args;
@@ -571,7 +576,7 @@ static void r4k_flush_icache_range(unsigned long start, unsigned long end)
        args.start = start;
        args.end = end;
 
-       r4k_on_each_cpu(local_r4k_flush_icache_range, &args, 1);
+       r4k_on_each_cpu(local_r4k_flush_icache_range_ipi, &args, 1);
        instruction_hazard();
 }
 
@@ -1375,6 +1380,7 @@ void __cpuinit r4k_cache_init(void)
        local_flush_data_cache_page     = local_r4k_flush_data_cache_page;
        flush_data_cache_page   = r4k_flush_data_cache_page;
        flush_icache_range      = r4k_flush_icache_range;
+       local_flush_icache_range        = local_r4k_flush_icache_range;
 
 #if defined(CONFIG_DMA_NONCOHERENT)
        if (coherentio) {
index a9f7f1f5e9b4ae90a50993bd06335b77ac8f47f5..f7c8f9ce39c1b1e983d54b6414c3a4bd1a2b8010 100644 (file)
@@ -362,6 +362,7 @@ void __cpuinit tx39_cache_init(void)
                flush_cache_range       = (void *) tx39h_flush_icache_all;
                flush_cache_page        = (void *) tx39h_flush_icache_all;
                flush_icache_range      = (void *) tx39h_flush_icache_all;
+               local_flush_icache_range = (void *) tx39h_flush_icache_all;
 
                flush_cache_sigtramp    = (void *) tx39h_flush_icache_all;
                local_flush_data_cache_page     = (void *) tx39h_flush_icache_all;
@@ -390,6 +391,7 @@ void __cpuinit tx39_cache_init(void)
                flush_cache_range = tx39_flush_cache_range;
                flush_cache_page = tx39_flush_cache_page;
                flush_icache_range = tx39_flush_icache_range;
+               local_flush_icache_range = tx39_flush_icache_range;
 
                flush_cache_sigtramp = tx39_flush_cache_sigtramp;
                local_flush_data_cache_page = local_tx39_flush_data_cache_page;
index 034e8506f6ea712a9554d9f13de28f622d8db1d4..1eb7c71e3d6adfe25916070e180ae87e0b3eedbf 100644 (file)
@@ -29,6 +29,7 @@ void (*flush_cache_range)(struct vm_area_struct *vma, unsigned long start,
 void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page,
        unsigned long pfn);
 void (*flush_icache_range)(unsigned long start, unsigned long end);
+void (*local_flush_icache_range)(unsigned long start, unsigned long end);
 
 void (*__flush_cache_vmap)(void);
 void (*__flush_cache_vunmap)(void);
index 76da73a5ab3caff4fcf43921ed8a132a8a739897..979cf9197282ca1f315a0ca8430da4d527332cd8 100644 (file)
@@ -1273,10 +1273,10 @@ void __cpuinit build_tlb_refill_handler(void)
 
 void __cpuinit flush_tlb_handlers(void)
 {
-       flush_icache_range((unsigned long)handle_tlbl,
+       local_flush_icache_range((unsigned long)handle_tlbl,
                           (unsigned long)handle_tlbl + sizeof(handle_tlbl));
-       flush_icache_range((unsigned long)handle_tlbs,
+       local_flush_icache_range((unsigned long)handle_tlbs,
                           (unsigned long)handle_tlbs + sizeof(handle_tlbs));
-       flush_icache_range((unsigned long)handle_tlbm,
+       local_flush_icache_range((unsigned long)handle_tlbm,
                           (unsigned long)handle_tlbm + sizeof(handle_tlbm));
 }
index 60141235ec40a956162f6343b27d55d567f0d386..52486c4d2b019739be2db360e3cbc8b7dd1fd847 100644 (file)
@@ -150,7 +150,7 @@ static int __init sgiseeq_devinit(void)
                return res;
 
        /* Second HPC is missing? */
-       if (!ip22_is_fullhouse() ||
+       if (ip22_is_fullhouse() ||
            get_dbe(tmp, (unsigned int *)&hpc3c1->pbdma[1]))
                return 0;
 
index 0afe94c48fb65e82ee283f5fbd2fbce6362dcdb9..fe6bee09cecea23e640a40861a9dcbc4e4adfe94 100644 (file)
@@ -53,6 +53,7 @@ txx9_reg_res_init(unsigned int pcode, unsigned long base, unsigned long size)
                txx9_ce_res[i].name = txx9_ce_res_name[i];
        }
 
+       txx9_pcode = pcode;
        sprintf(txx9_pcode_str, "TX%x", pcode);
        if (base) {
                txx9_reg_res.start = base & 0xfffffffffULL;
index fdacdd4341c9f3ccf3189afe683b7179ead823d4..44138c3e6ea74e3042b2ddb66058714eb74bc27f 100644 (file)
@@ -47,7 +47,9 @@
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/bug.h>
+#include <linux/uaccess.h>
 
+#include <asm/sections.h>
 #include <asm/unwind.h>
 
 #if 0
@@ -860,3 +862,15 @@ void module_arch_cleanup(struct module *mod)
        deregister_unwind_table(mod);
        module_bug_cleanup(mod);
 }
+
+#ifdef CONFIG_64BIT
+void *dereference_function_descriptor(void *ptr)
+{
+       Elf64_Fdesc *desc = ptr;
+       void *p;
+
+       if (!probe_kernel_address(&desc->addr, p))
+               ptr = p;
+       return ptr;
+}
+#endif
index 14174aa240744783d6c0d77748a9b714d6cebea0..717a3bc1352e542d410e3713e2222e7ea2745516 100644 (file)
@@ -49,7 +49,7 @@ zlib       := inffast.c inflate.c inftrees.c
 zlibheader := inffast.h inffixed.h inflate.h inftrees.h infutil.h
 zliblinuxheader := zlib.h zconf.h zutil.h
 
-$(addprefix $(obj)/,$(zlib) gunzip_util.o main.o): \
+$(addprefix $(obj)/,$(zlib) cuboot-c2k.o gunzip_util.o main.o prpmc2800.o): \
        $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader))
 
 src-libfdt := fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
index 916018e425c4dc7112f6c0c1f49f884118d4bd0b..7710e9e6660fc52ef703c540a95b16a892ba3fca 100644 (file)
@@ -16,6 +16,9 @@ static inline int in_kernel_text(unsigned long addr)
        return 0;
 }
 
+#undef dereference_function_descriptor
+void *dereference_function_descriptor(void *);
+
 #endif
 
 #endif /* __KERNEL__ */
index ee6a2982d567351eb88ace12c2109918af6af59e..ad79de272ff3ec7f7ee14062f48eed082511e2e0 100644 (file)
@@ -21,8 +21,9 @@
 #include <linux/err.h>
 #include <linux/vmalloc.h>
 #include <linux/bug.h>
+#include <linux/uaccess.h>
 #include <asm/module.h>
-#include <asm/uaccess.h>
+#include <asm/sections.h>
 #include <asm/firmware.h>
 #include <asm/code-patching.h>
 #include <linux/sort.h>
@@ -451,3 +452,13 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
 
        return 0;
 }
+
+void *dereference_function_descriptor(void *ptr)
+{
+       struct ppc64_opd_entry *desc = ptr;
+       void *p;
+
+       if (!probe_kernel_address(&desc->funcaddr, p))
+               ptr = p;
+       return ptr;
+}
index 1c1b627ee8436dc8e2fce9098d274183b8f18011..67595bc380dc154465682f9be7f9c203d283bfe5 100644 (file)
@@ -643,9 +643,10 @@ static struct spu *find_victim(struct spu_context *ctx)
                            !(tmp->flags & SPU_CREATE_NOSCHED) &&
                            (!victim || tmp->prio > victim->prio)) {
                                victim = spu->ctx;
-                               get_spu_context(victim);
                        }
                }
+               if (victim)
+                       get_spu_context(victim);
                mutex_unlock(&cbe_spu_info[node].list_mutex);
 
                if (victim) {
@@ -727,17 +728,33 @@ static void spu_schedule(struct spu *spu, struct spu_context *ctx)
        /* not a candidate for interruptible because it's called either
           from the scheduler thread or from spu_deactivate */
        mutex_lock(&ctx->state_mutex);
-       __spu_schedule(spu, ctx);
+       if (ctx->state == SPU_STATE_SAVED)
+               __spu_schedule(spu, ctx);
        spu_release(ctx);
 }
 
-static void spu_unschedule(struct spu *spu, struct spu_context *ctx)
+/**
+ * spu_unschedule - remove a context from a spu, and possibly release it.
+ * @spu:       The SPU to unschedule from
+ * @ctx:       The context currently scheduled on the SPU
+ * @free_spu   Whether to free the SPU for other contexts
+ *
+ * Unbinds the context @ctx from the SPU @spu. If @free_spu is non-zero, the
+ * SPU is made available for other contexts (ie, may be returned by
+ * spu_get_idle). If this is zero, the caller is expected to schedule another
+ * context to this spu.
+ *
+ * Should be called with ctx->state_mutex held.
+ */
+static void spu_unschedule(struct spu *spu, struct spu_context *ctx,
+               int free_spu)
 {
        int node = spu->node;
 
        mutex_lock(&cbe_spu_info[node].list_mutex);
        cbe_spu_info[node].nr_active--;
-       spu->alloc_state = SPU_FREE;
+       if (free_spu)
+               spu->alloc_state = SPU_FREE;
        spu_unbind_context(spu, ctx);
        ctx->stats.invol_ctx_switch++;
        spu->stats.invol_ctx_switch++;
@@ -837,7 +854,7 @@ static int __spu_deactivate(struct spu_context *ctx, int force, int max_prio)
        if (spu) {
                new = grab_runnable_context(max_prio, spu->node);
                if (new || force) {
-                       spu_unschedule(spu, ctx);
+                       spu_unschedule(spu, ctx, new == NULL);
                        if (new) {
                                if (new->flags & SPU_CREATE_NOSCHED)
                                        wake_up(&new->stop_wq);
@@ -910,7 +927,7 @@ static noinline void spusched_tick(struct spu_context *ctx)
 
        new = grab_runnable_context(ctx->prio + 1, spu->node);
        if (new) {
-               spu_unschedule(spu, ctx);
+               spu_unschedule(spu, ctx, 0);
                if (test_bit(SPU_SCHED_SPU_RUN, &ctx->sched_flags))
                        spu_add_to_rq(ctx);
        } else {
index cde81fa64f89bf17bc586dce3f973e77f55985e8..a2be3a978d5c43281e3cf3115e2dfb19d473307f 100644 (file)
@@ -42,6 +42,7 @@ struct user_regs_struct32
        u32 gprs[NUM_GPRS];
        u32 acrs[NUM_ACRS];
        u32 orig_gpr2;
+       /* nb: there's a 4-byte hole here */
        s390_fp_regs fp_regs;
        /*
         * These per registers are in here so that gdb can modify them
index 2815bfe348a6f92e67b64e04e0b70cbecde6bc58..c8b08289eb87e1d78c9c92996fe7bbfe30c16645 100644 (file)
@@ -170,6 +170,13 @@ static unsigned long __peek_user(struct task_struct *child, addr_t addr)
                 */
                tmp = (addr_t) task_pt_regs(child)->orig_gpr2;
 
+       } else if (addr < (addr_t) &dummy->regs.fp_regs) {
+               /*
+                * prevent reads of padding hole between
+                * orig_gpr2 and fp_regs on s390.
+                */
+               tmp = 0;
+
        } else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) {
                /* 
                 * floating point regs. are stored in the thread structure
@@ -270,6 +277,13 @@ static int __poke_user(struct task_struct *child, addr_t addr, addr_t data)
                 */
                task_pt_regs(child)->orig_gpr2 = data;
 
+       } else if (addr < (addr_t) &dummy->regs.fp_regs) {
+               /*
+                * prevent writes of padding hole between
+                * orig_gpr2 and fp_regs on s390.
+                */
+               return 0;
+
        } else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) {
                /*
                 * floating point regs. are stored in the thread structure
@@ -428,6 +442,13 @@ static u32 __peek_user_compat(struct task_struct *child, addr_t addr)
                 */
                tmp = *(__u32*)((addr_t) &task_pt_regs(child)->orig_gpr2 + 4);
 
+       } else if (addr < (addr_t) &dummy32->regs.fp_regs) {
+               /*
+                * prevent reads of padding hole between
+                * orig_gpr2 and fp_regs on s390.
+                */
+               tmp = 0;
+
        } else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) {
                /*
                 * floating point regs. are stored in the thread structure 
@@ -514,6 +535,13 @@ static int __poke_user_compat(struct task_struct *child,
                 */
                *(__u32*)((addr_t) &task_pt_regs(child)->orig_gpr2 + 4) = tmp;
 
+       } else if (addr < (addr_t) &dummy32->regs.fp_regs) {
+               /*
+                * prevent writess of padding hole between
+                * orig_gpr2 and fp_regs on s390.
+                */
+               return 0;
+
        } else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) {
                /*
                 * floating point regs. are stored in the thread structure 
index 9b6689d9d57097239641d51653dc921e2607b997..23963882bc18f203cd27850300cbb80755df025e 100644 (file)
@@ -792,6 +792,8 @@ void fixup_irqs(void)
                }
                spin_unlock_irqrestore(&irq_desc[irq].lock, flags);
        }
+
+       tick_ops->disable_irq();
 }
 #endif
 
index 743ccad61c60921b36c9bf42a556dac79ac4e23c..2be166c544ca42a27222325cc61001b5190e368c 100644 (file)
@@ -80,8 +80,6 @@ void smp_bogo(struct seq_file *m)
                           i, cpu_data(i).clock_tick);
 }
 
-static __cacheline_aligned_in_smp DEFINE_SPINLOCK(call_lock);
-
 extern void setup_sparc64_timer(void);
 
 static volatile unsigned long callin_flag = 0;
@@ -120,9 +118,9 @@ void __cpuinit smp_callin(void)
        while (!cpu_isset(cpuid, smp_commenced_mask))
                rmb();
 
-       spin_lock(&call_lock);
+       ipi_call_lock();
        cpu_set(cpuid, cpu_online_map);
-       spin_unlock(&call_lock);
+       ipi_call_unlock();
 
        /* idle thread is expected to have preempt disabled */
        preempt_disable();
@@ -1305,10 +1303,6 @@ int __cpu_disable(void)
        c->core_id = 0;
        c->proc_id = -1;
 
-       spin_lock(&call_lock);
-       cpu_clear(cpu, cpu_online_map);
-       spin_unlock(&call_lock);
-
        smp_wmb();
 
        /* Make sure no interrupts point to this cpu.  */
@@ -1318,6 +1312,10 @@ int __cpu_disable(void)
        mdelay(1);
        local_irq_disable();
 
+       ipi_call_lock();
+       cpu_clear(cpu, cpu_online_map);
+       ipi_call_unlock();
+
        return 0;
 }
 
index 2c518fbc52ece13221e587ee71f11c81a4d5cec7..b225219c448ca4cc44c7de2402b8c894e8b5da3e 100644 (file)
@@ -382,14 +382,17 @@ config X86_OOSTORE
 # P6_NOPs are a relatively minor optimization that require a family >=
 # 6 processor, except that it is broken on certain VIA chips.
 # Furthermore, AMD chips prefer a totally different sequence of NOPs
-# (which work on all CPUs).  As a result, disallow these if we're
-# compiling X86_GENERIC but not X86_64 (these NOPs do work on all
-# x86-64 capable chips); the list of processors in the right-hand clause
-# are the cores that benefit from this optimization.
+# (which work on all CPUs).  In addition, it looks like Virtual PC
+# does not understand them.
+#
+# As a result, disallow these if we're not compiling for X86_64 (these
+# NOPs do work on all x86-64 capable chips); the list of processors in
+# the right-hand clause are the cores that benefit from this optimization.
 #
 config X86_P6_NOP
        def_bool y
-       depends on (X86_64 || !X86_GENERIC) && (M686 || MPENTIUMII || MPENTIUMIII || MPENTIUMM || MCORE2 || MPENTIUM4 || MPSC)
+       depends on X86_64
+       depends on (MCORE2 || MPENTIUM4 || MPSC)
 
 config X86_TSC
        def_bool y
index 4b9ae7c567480658ff1e83333a2f8137c887579b..4d3ff037201ffbee0bb468e04d069b02909d094d 100644 (file)
@@ -38,12 +38,12 @@ static const u32 req_flags[NCAPINTS] =
 {
        REQUIRED_MASK0,
        REQUIRED_MASK1,
-       REQUIRED_MASK2,
-       REQUIRED_MASK3,
+       0, /* REQUIRED_MASK2 not implemented in this file */
+       0, /* REQUIRED_MASK3 not implemented in this file */
        REQUIRED_MASK4,
-       REQUIRED_MASK5,
+       0, /* REQUIRED_MASK5 not implemented in this file */
        REQUIRED_MASK6,
-       REQUIRED_MASK7,
+       0, /* REQUIRED_MASK7 not implemented in this file */
 };
 
 #define A32(a, b, c, d) (((d) << 24)+((c) << 16)+((b) << 8)+(a))
index 2763cb37b553e5780c9dc080311022e3b4339092..65a0c1b4869636122fc22dec84de26788662a2d4 100644 (file)
@@ -145,35 +145,25 @@ static const unsigned char *const p6_nops[ASM_NOP_MAX+1] = {
 extern char __vsyscall_0;
 const unsigned char *const *find_nop_table(void)
 {
-       return boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
-              boot_cpu_data.x86 < 6 ? k8_nops : p6_nops;
+       if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
+           boot_cpu_has(X86_FEATURE_NOPL))
+               return p6_nops;
+       else
+               return k8_nops;
 }
 
 #else /* CONFIG_X86_64 */
 
-static const struct nop {
-       int cpuid;
-       const unsigned char *const *noptable;
-} noptypes[] = {
-       { X86_FEATURE_K8, k8_nops },
-       { X86_FEATURE_K7, k7_nops },
-       { X86_FEATURE_P4, p6_nops },
-       { X86_FEATURE_P3, p6_nops },
-       { -1, NULL }
-};
-
 const unsigned char *const *find_nop_table(void)
 {
-       const unsigned char *const *noptable = intel_nops;
-       int i;
-
-       for (i = 0; noptypes[i].cpuid >= 0; i++) {
-               if (boot_cpu_has(noptypes[i].cpuid)) {
-                       noptable = noptypes[i].noptable;
-                       break;
-               }
-       }
-       return noptable;
+       if (boot_cpu_has(X86_FEATURE_K8))
+               return k8_nops;
+       else if (boot_cpu_has(X86_FEATURE_K7))
+               return k7_nops;
+       else if (boot_cpu_has(X86_FEATURE_NOPL))
+               return p6_nops;
+       else
+               return intel_nops;
 }
 
 #endif /* CONFIG_X86_64 */
index cae9cabc3031f1e3a2a3d6f8085d20b557026ac3..18514ed261047b057104b6bc4384d0ab18908cfd 100644 (file)
@@ -31,6 +31,11 @@ static void __cpuinit early_init_amd(struct cpuinfo_x86 *c)
                if (c->x86_power & (1<<8))
                        set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
        }
+
+       /*  Set MTRR capability flag if appropriate */
+       if (c->x86_model == 13 || c->x86_model == 9 ||
+          (c->x86_model == 8 && c->x86_mask >= 8))
+               set_cpu_cap(c, X86_FEATURE_K6_MTRR);
 }
 
 static void __cpuinit init_amd(struct cpuinfo_x86 *c)
@@ -166,10 +171,6 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
                                                mbytes);
                                }
 
-                               /*  Set MTRR capability flag if appropriate */
-                               if (c->x86_model == 13 || c->x86_model == 9 ||
-                                  (c->x86_model == 8 && c->x86_mask >= 8))
-                                       set_cpu_cap(c, X86_FEATURE_K6_MTRR);
                                break;
                        }
 
index e0f45edd6a5591498aca154243bd234e11973609..a0534c04d38a5d385072b869903eea4339553293 100644 (file)
@@ -314,6 +314,16 @@ enum {
                EAMD3D          = 1<<20,
 };
 
+static void __cpuinit early_init_centaur(struct cpuinfo_x86 *c)
+{
+       switch (c->x86) {
+       case 5:
+               /* Emulate MTRRs using Centaur's MCR. */
+               set_cpu_cap(c, X86_FEATURE_CENTAUR_MCR);
+               break;
+       }
+}
+
 static void __cpuinit init_centaur(struct cpuinfo_x86 *c)
 {
 
@@ -462,6 +472,7 @@ centaur_size_cache(struct cpuinfo_x86 *c, unsigned int size)
 static struct cpu_dev centaur_cpu_dev __cpuinitdata = {
        .c_vendor       = "Centaur",
        .c_ident        = { "CentaurHauls" },
+       .c_early_init   = early_init_centaur,
        .c_init         = init_centaur,
        .c_size_cache   = centaur_size_cache,
 };
index 80ab20d4fa39913ce2a7b4ea5676883bb6f9d96f..8aab8517642e7ba34c3c91da7403c4892b01b53d 100644 (file)
@@ -13,6 +13,7 @@
 #include <asm/mtrr.h>
 #include <asm/mce.h>
 #include <asm/pat.h>
+#include <asm/asm.h>
 #ifdef CONFIG_X86_LOCAL_APIC
 #include <asm/mpspec.h>
 #include <asm/apic.h>
@@ -334,11 +335,40 @@ static void __init early_cpu_detect(void)
 
        get_cpu_vendor(c, 1);
 
+       early_get_cap(c);
+
        if (c->x86_vendor != X86_VENDOR_UNKNOWN &&
            cpu_devs[c->x86_vendor]->c_early_init)
                cpu_devs[c->x86_vendor]->c_early_init(c);
+}
 
-       early_get_cap(c);
+/*
+ * The NOPL instruction is supposed to exist on all CPUs with
+ * family >= 6, unfortunately, that's not true in practice because
+ * of early VIA chips and (more importantly) broken virtualizers that
+ * are not easy to detect.  Hence, probe for it based on first
+ * principles.
+ */
+static void __cpuinit detect_nopl(struct cpuinfo_x86 *c)
+{
+       const u32 nopl_signature = 0x888c53b1; /* Random number */
+       u32 has_nopl = nopl_signature;
+
+       clear_cpu_cap(c, X86_FEATURE_NOPL);
+       if (c->x86 >= 6) {
+               asm volatile("\n"
+                            "1:      .byte 0x0f,0x1f,0xc0\n" /* nopl %eax */
+                            "2:\n"
+                            "        .section .fixup,\"ax\"\n"
+                            "3:      xor %0,%0\n"
+                            "        jmp 2b\n"
+                            "        .previous\n"
+                            _ASM_EXTABLE(1b,3b)
+                            : "+a" (has_nopl));
+
+               if (has_nopl == nopl_signature)
+                       set_cpu_cap(c, X86_FEATURE_NOPL);
+       }
 }
 
 static void __cpuinit generic_identify(struct cpuinfo_x86 *c)
@@ -395,8 +425,8 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 *c)
                }
 
                init_scattered_cpuid_features(c);
+               detect_nopl(c);
        }
-
 }
 
 static void __cpuinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
index dd6e3f15017eb87b04885fd5164681bbdd9a3073..a11f5d4477cd797432d8a54df202dd558bdec5d5 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/mtrr.h>
 #include <asm/mce.h>
 #include <asm/pat.h>
+#include <asm/asm.h>
 #include <asm/numa.h>
 #ifdef CONFIG_X86_LOCAL_APIC
 #include <asm/mpspec.h>
@@ -215,6 +216,39 @@ static void __init early_cpu_support_print(void)
        }
 }
 
+/*
+ * The NOPL instruction is supposed to exist on all CPUs with
+ * family >= 6, unfortunately, that's not true in practice because
+ * of early VIA chips and (more importantly) broken virtualizers that
+ * are not easy to detect.  Hence, probe for it based on first
+ * principles.
+ *
+ * Note: no 64-bit chip is known to lack these, but put the code here
+ * for consistency with 32 bits, and to make it utterly trivial to
+ * diagnose the problem should it ever surface.
+ */
+static void __cpuinit detect_nopl(struct cpuinfo_x86 *c)
+{
+       const u32 nopl_signature = 0x888c53b1; /* Random number */
+       u32 has_nopl = nopl_signature;
+
+       clear_cpu_cap(c, X86_FEATURE_NOPL);
+       if (c->x86 >= 6) {
+               asm volatile("\n"
+                            "1:      .byte 0x0f,0x1f,0xc0\n" /* nopl %eax */
+                            "2:\n"
+                            "        .section .fixup,\"ax\"\n"
+                            "3:      xor %0,%0\n"
+                            "        jmp 2b\n"
+                            "        .previous\n"
+                            _ASM_EXTABLE(1b,3b)
+                            : "+a" (has_nopl));
+
+               if (has_nopl == nopl_signature)
+                       set_cpu_cap(c, X86_FEATURE_NOPL);
+       }
+}
+
 static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c);
 
 void __init early_cpu_init(void)
@@ -313,6 +347,8 @@ static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c)
                c->x86_phys_bits = eax & 0xff;
        }
 
+       detect_nopl(c);
+
        if (c->x86_vendor != X86_VENDOR_UNKNOWN &&
            cpu_devs[c->x86_vendor]->c_early_init)
                cpu_devs[c->x86_vendor]->c_early_init(c);
@@ -493,17 +529,20 @@ void pda_init(int cpu)
                /* others are initialized in smpboot.c */
                pda->pcurrent = &init_task;
                pda->irqstackptr = boot_cpu_stack;
+               pda->irqstackptr += IRQSTACKSIZE - 64;
        } else {
-               pda->irqstackptr = (char *)
-                       __get_free_pages(GFP_ATOMIC, IRQSTACK_ORDER);
-               if (!pda->irqstackptr)
-                       panic("cannot allocate irqstack for cpu %d", cpu);
+               if (!pda->irqstackptr) {
+                       pda->irqstackptr = (char *)
+                               __get_free_pages(GFP_ATOMIC, IRQSTACK_ORDER);
+                       if (!pda->irqstackptr)
+                               panic("cannot allocate irqstack for cpu %d",
+                                     cpu);
+                       pda->irqstackptr += IRQSTACKSIZE - 64;
+               }
 
                if (pda->nodenumber == 0 && cpu_to_node(cpu) != NUMA_NO_NODE)
                        pda->nodenumber = cpu_to_node(cpu);
        }
-
-       pda->irqstackptr += IRQSTACKSIZE-64;
 }
 
 char boot_exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ +
@@ -601,19 +640,22 @@ void __cpuinit cpu_init(void)
        /*
         * set up and load the per-CPU TSS
         */
-       for (v = 0; v < N_EXCEPTION_STACKS; v++) {
+       if (!orig_ist->ist[0]) {
                static const unsigned int order[N_EXCEPTION_STACKS] = {
-                       [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER,
-                       [DEBUG_STACK - 1] = DEBUG_STACK_ORDER
+                 [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER,
+                 [DEBUG_STACK - 1] = DEBUG_STACK_ORDER
                };
-               if (cpu) {
-                       estacks = (char *)__get_free_pages(GFP_ATOMIC, order[v]);
-                       if (!estacks)
-                               panic("Cannot allocate exception stack %ld %d\n",
-                                     v, cpu);
+               for (v = 0; v < N_EXCEPTION_STACKS; v++) {
+                       if (cpu) {
+                               estacks = (char *)__get_free_pages(GFP_ATOMIC, order[v]);
+                               if (!estacks)
+                                       panic("Cannot allocate exception "
+                                             "stack %ld %d\n", v, cpu);
+                       }
+                       estacks += PAGE_SIZE << order[v];
+                       orig_ist->ist[v] = t->x86_tss.ist[v] =
+                                       (unsigned long)estacks;
                }
-               estacks += PAGE_SIZE << order[v];
-               orig_ist->ist[v] = t->x86_tss.ist[v] = (unsigned long)estacks;
        }
 
        t->x86_tss.io_bitmap_base = offsetof(struct tss_struct, io_bitmap);
index e710a21bb6e8dc0dd9d83a7bd49df69135cbcf7b..898a5a2002ed64e391d45a24d5e6a7103d6397a9 100644 (file)
 /*
  * Read NSC/Cyrix DEVID registers (DIR) to get more detailed info. about the CPU
  */
-static void __cpuinit do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
+static void __cpuinit __do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
 {
        unsigned char ccr2, ccr3;
-       unsigned long flags;
 
        /* we test for DEVID by checking whether CCR3 is writable */
-       local_irq_save(flags);
        ccr3 = getCx86(CX86_CCR3);
        setCx86(CX86_CCR3, ccr3 ^ 0x80);
        getCx86(0xc0);   /* dummy to change bus */
@@ -44,9 +42,16 @@ static void __cpuinit do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
                *dir0 = getCx86(CX86_DIR0);
                *dir1 = getCx86(CX86_DIR1);
        }
-       local_irq_restore(flags);
 }
 
+static void __cpuinit do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       __do_cyrix_devid(dir0, dir1);
+       local_irq_restore(flags);
+}
 /*
  * Cx86_dir0_msb is a HACK needed by check_cx686_cpuid/slop in bugs.h in
  * order to identify the Cyrix CPU model after we're out of setup.c
@@ -161,6 +166,24 @@ static void __cpuinit geode_configure(void)
        local_irq_restore(flags);
 }
 
+static void __cpuinit early_init_cyrix(struct cpuinfo_x86 *c)
+{
+       unsigned char dir0, dir0_msn, dir1 = 0;
+
+       __do_cyrix_devid(&dir0, &dir1);
+       dir0_msn = dir0 >> 4; /* identifies CPU "family"   */
+
+       switch (dir0_msn) {
+       case 3: /* 6x86/6x86L */
+               /* Emulate MTRRs using Cyrix's ARRs. */
+               set_cpu_cap(c, X86_FEATURE_CYRIX_ARR);
+               break;
+       case 5: /* 6x86MX/M II */
+               /* Emulate MTRRs using Cyrix's ARRs. */
+               set_cpu_cap(c, X86_FEATURE_CYRIX_ARR);
+               break;
+       }
+}
 
 static void __cpuinit init_cyrix(struct cpuinfo_x86 *c)
 {
@@ -416,6 +439,7 @@ static void __cpuinit cyrix_identify(struct cpuinfo_x86 *c)
 static struct cpu_dev cyrix_cpu_dev __cpuinitdata = {
        .c_vendor       = "Cyrix",
        .c_ident        = { "CyrixInstead" },
+       .c_early_init   = early_init_cyrix,
        .c_init         = init_cyrix,
        .c_identify     = cyrix_identify,
 };
index e43ad4ad4cbae8b75561f67ec1da51628c568491..c9017799497c5f99db3df1ce96d010b6ea5e3230 100644 (file)
@@ -39,7 +39,8 @@ const char * const x86_cap_flags[NCAPINTS*32] = {
        NULL, NULL, NULL, NULL,
        "constant_tsc", "up", NULL, "arch_perfmon",
        "pebs", "bts", NULL, NULL,
-       "rep_good", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       "rep_good", NULL, NULL, NULL,
+       "nopl", NULL, NULL, NULL,
        NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
        /* Intel-defined (#2) */
index 9af89078f7bb0cb2b6ce7ed958c9483b24d4402e..66e48aa2dd1b4dae8739f69841337386cc670889 100644 (file)
@@ -1203,7 +1203,7 @@ static int __init parse_memmap_opt(char *p)
        if (!p)
                return -EINVAL;
 
-       if (!strcmp(p, "exactmap")) {
+       if (!strncmp(p, "exactmap", 8)) {
 #ifdef CONFIG_CRASH_DUMP
                /*
                 * If we are doing a crash dump, we still need to know
index 59fd3b6b13036e1e279e54d0e1e3d3f5ebb55166..73deaffadd036a578984bb8ad6e0455f1044558a 100644 (file)
@@ -210,8 +210,8 @@ static void hpet_legacy_clockevent_register(void)
        /* Calculate the min / max delta */
        hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF,
                                                           &hpet_clockevent);
-       hpet_clockevent.min_delta_ns = clockevent_delta2ns(0x30,
-                                                          &hpet_clockevent);
+       /* 5 usec minimum reprogramming delta. */
+       hpet_clockevent.min_delta_ns = 5000;
 
        /*
         * Start hpet with the boot cpu mask and make it
@@ -270,15 +270,22 @@ static void hpet_legacy_set_mode(enum clock_event_mode mode,
 }
 
 static int hpet_legacy_next_event(unsigned long delta,
-                          struct clock_event_device *evt)
+                                 struct clock_event_device *evt)
 {
-       unsigned long cnt;
+       u32 cnt;
 
        cnt = hpet_readl(HPET_COUNTER);
-       cnt += delta;
+       cnt += (u32) delta;
        hpet_writel(cnt, HPET_T0_CMP);
 
-       return ((long)(hpet_readl(HPET_COUNTER) - cnt ) > 0) ? -ETIME : 0;
+       /*
+        * We need to read back the CMP register to make sure that
+        * what we wrote hit the chip before we compare it to the
+        * counter.
+        */
+       WARN_ON((u32)hpet_readl(HPET_T0_CMP) != cnt);
+
+       return (s32)((u32)hpet_readl(HPET_COUNTER) - cnt) >= 0 ? -ETIME : 0;
 }
 
 /*
index 9ff6e3cbf08feaf41c36d9a48c46ae45a105174e..a4e201b47f64ec1fbaf5075da3254c6b72f109b1 100644 (file)
@@ -1324,7 +1324,7 @@ static const struct pv_mmu_ops xen_mmu_ops __initdata = {
        .ptep_modify_prot_commit = __ptep_modify_prot_commit,
 
        .pte_val = xen_pte_val,
-       .pte_flags = native_pte_val,
+       .pte_flags = native_pte_flags,
        .pgd_val = xen_pgd_val,
 
        .make_pte = xen_make_pte,
index b1cc4de6493cfa7604187e4f05429d84f6ad2e58..493fee7e0a8b46bbd9933d92681e0a7c16d0ab81 100644 (file)
@@ -35,8 +35,6 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/bitops.h>
-#include <asm/unaligned.h>
 
 static const u32 camellia_sp1110[256] = {
        0x70707000,0x82828200,0x2c2c2c00,0xececec00,
@@ -337,6 +335,20 @@ static const u32 camellia_sp4404[256] = {
 /*
  *  macros
  */
+#define GETU32(v, pt) \
+    do { \
+       /* latest breed of gcc is clever enough to use move */ \
+       memcpy(&(v), (pt), 4); \
+       (v) = be32_to_cpu(v); \
+    } while(0)
+
+/* rotation right shift 1byte */
+#define ROR8(x) (((x) >> 8) + ((x) << 24))
+/* rotation left shift 1bit */
+#define ROL1(x) (((x) << 1) + ((x) >> 31))
+/* rotation left shift 1byte */
+#define ROL8(x) (((x) << 8) + ((x) >> 24))
+
 #define ROLDQ(ll, lr, rl, rr, w0, w1, bits)            \
     do {                                               \
        w0 = ll;                                        \
@@ -371,7 +383,7 @@ static const u32 camellia_sp4404[256] = {
           ^ camellia_sp3033[(u8)(il >> 8)]                     \
           ^ camellia_sp4404[(u8)(il     )];                    \
        yl ^= yr;                                               \
-       yr = ror32(yr, 8);                                      \
+       yr = ROR8(yr);                                          \
        yr ^= yl;                                               \
     } while(0)
 
@@ -393,7 +405,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
        subL[7] ^= subL[1]; subR[7] ^= subR[1];
        subL[1] ^= subR[1] & ~subR[9];
        dw = subL[1] & subL[9],
-               subR[1] ^= rol32(dw, 1); /* modified for FLinv(kl2) */
+               subR[1] ^= ROL1(dw); /* modified for FLinv(kl2) */
        /* round 8 */
        subL[11] ^= subL[1]; subR[11] ^= subR[1];
        /* round 10 */
@@ -402,7 +414,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
        subL[15] ^= subL[1]; subR[15] ^= subR[1];
        subL[1] ^= subR[1] & ~subR[17];
        dw = subL[1] & subL[17],
-               subR[1] ^= rol32(dw, 1); /* modified for FLinv(kl4) */
+               subR[1] ^= ROL1(dw); /* modified for FLinv(kl4) */
        /* round 14 */
        subL[19] ^= subL[1]; subR[19] ^= subR[1];
        /* round 16 */
@@ -418,7 +430,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
        } else {
                subL[1] ^= subR[1] & ~subR[25];
                dw = subL[1] & subL[25],
-                       subR[1] ^= rol32(dw, 1); /* modified for FLinv(kl6) */
+                       subR[1] ^= ROL1(dw); /* modified for FLinv(kl6) */
                /* round 20 */
                subL[27] ^= subL[1]; subR[27] ^= subR[1];
                /* round 22 */
@@ -438,7 +450,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
                subL[26] ^= kw4l; subR[26] ^= kw4r;
                kw4l ^= kw4r & ~subR[24];
                dw = kw4l & subL[24],
-                       kw4r ^= rol32(dw, 1); /* modified for FL(kl5) */
+                       kw4r ^= ROL1(dw); /* modified for FL(kl5) */
        }
        /* round 17 */
        subL[22] ^= kw4l; subR[22] ^= kw4r;
@@ -448,7 +460,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
        subL[18] ^= kw4l; subR[18] ^= kw4r;
        kw4l ^= kw4r & ~subR[16];
        dw = kw4l & subL[16],
-               kw4r ^= rol32(dw, 1); /* modified for FL(kl3) */
+               kw4r ^= ROL1(dw); /* modified for FL(kl3) */
        /* round 11 */
        subL[14] ^= kw4l; subR[14] ^= kw4r;
        /* round 9 */
@@ -457,7 +469,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
        subL[10] ^= kw4l; subR[10] ^= kw4r;
        kw4l ^= kw4r & ~subR[8];
        dw = kw4l & subL[8],
-               kw4r ^= rol32(dw, 1); /* modified for FL(kl1) */
+               kw4r ^= ROL1(dw); /* modified for FL(kl1) */
        /* round 5 */
        subL[6] ^= kw4l; subR[6] ^= kw4r;
        /* round 3 */
@@ -482,7 +494,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
        SUBKEY_R(6) = subR[5] ^ subR[7];
        tl = subL[10] ^ (subR[10] & ~subR[8]);
        dw = tl & subL[8],  /* FL(kl1) */
-               tr = subR[10] ^ rol32(dw, 1);
+               tr = subR[10] ^ ROL1(dw);
        SUBKEY_L(7) = subL[6] ^ tl; /* round 6 */
        SUBKEY_R(7) = subR[6] ^ tr;
        SUBKEY_L(8) = subL[8];       /* FL(kl1) */
@@ -491,7 +503,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
        SUBKEY_R(9) = subR[9];
        tl = subL[7] ^ (subR[7] & ~subR[9]);
        dw = tl & subL[9],  /* FLinv(kl2) */
-               tr = subR[7] ^ rol32(dw, 1);
+               tr = subR[7] ^ ROL1(dw);
        SUBKEY_L(10) = tl ^ subL[11]; /* round 7 */
        SUBKEY_R(10) = tr ^ subR[11];
        SUBKEY_L(11) = subL[10] ^ subL[12]; /* round 8 */
@@ -504,7 +516,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
        SUBKEY_R(14) = subR[13] ^ subR[15];
        tl = subL[18] ^ (subR[18] & ~subR[16]);
        dw = tl & subL[16], /* FL(kl3) */
-               tr = subR[18] ^ rol32(dw, 1);
+               tr = subR[18] ^ ROL1(dw);
        SUBKEY_L(15) = subL[14] ^ tl; /* round 12 */
        SUBKEY_R(15) = subR[14] ^ tr;
        SUBKEY_L(16) = subL[16];     /* FL(kl3) */
@@ -513,7 +525,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
        SUBKEY_R(17) = subR[17];
        tl = subL[15] ^ (subR[15] & ~subR[17]);
        dw = tl & subL[17], /* FLinv(kl4) */
-               tr = subR[15] ^ rol32(dw, 1);
+               tr = subR[15] ^ ROL1(dw);
        SUBKEY_L(18) = tl ^ subL[19]; /* round 13 */
        SUBKEY_R(18) = tr ^ subR[19];
        SUBKEY_L(19) = subL[18] ^ subL[20]; /* round 14 */
@@ -532,7 +544,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
        } else {
                tl = subL[26] ^ (subR[26] & ~subR[24]);
                dw = tl & subL[24], /* FL(kl5) */
-                       tr = subR[26] ^ rol32(dw, 1);
+                       tr = subR[26] ^ ROL1(dw);
                SUBKEY_L(23) = subL[22] ^ tl; /* round 18 */
                SUBKEY_R(23) = subR[22] ^ tr;
                SUBKEY_L(24) = subL[24];     /* FL(kl5) */
@@ -541,7 +553,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
                SUBKEY_R(25) = subR[25];
                tl = subL[23] ^ (subR[23] & ~subR[25]);
                dw = tl & subL[25], /* FLinv(kl6) */
-                       tr = subR[23] ^ rol32(dw, 1);
+                       tr = subR[23] ^ ROL1(dw);
                SUBKEY_L(26) = tl ^ subL[27]; /* round 19 */
                SUBKEY_R(26) = tr ^ subR[27];
                SUBKEY_L(27) = subL[26] ^ subL[28]; /* round 20 */
@@ -561,17 +573,17 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
        /* apply the inverse of the last half of P-function */
        i = 2;
        do {
-               dw = SUBKEY_L(i + 0) ^ SUBKEY_R(i + 0); dw = rol32(dw, 8);/* round 1 */
+               dw = SUBKEY_L(i + 0) ^ SUBKEY_R(i + 0); dw = ROL8(dw);/* round 1 */
                SUBKEY_R(i + 0) = SUBKEY_L(i + 0) ^ dw; SUBKEY_L(i + 0) = dw;
-               dw = SUBKEY_L(i + 1) ^ SUBKEY_R(i + 1); dw = rol32(dw, 8);/* round 2 */
+               dw = SUBKEY_L(i + 1) ^ SUBKEY_R(i + 1); dw = ROL8(dw);/* round 2 */
                SUBKEY_R(i + 1) = SUBKEY_L(i + 1) ^ dw; SUBKEY_L(i + 1) = dw;
-               dw = SUBKEY_L(i + 2) ^ SUBKEY_R(i + 2); dw = rol32(dw, 8);/* round 3 */
+               dw = SUBKEY_L(i + 2) ^ SUBKEY_R(i + 2); dw = ROL8(dw);/* round 3 */
                SUBKEY_R(i + 2) = SUBKEY_L(i + 2) ^ dw; SUBKEY_L(i + 2) = dw;
-               dw = SUBKEY_L(i + 3) ^ SUBKEY_R(i + 3); dw = rol32(dw, 8);/* round 4 */
+               dw = SUBKEY_L(i + 3) ^ SUBKEY_R(i + 3); dw = ROL8(dw);/* round 4 */
                SUBKEY_R(i + 3) = SUBKEY_L(i + 3) ^ dw; SUBKEY_L(i + 3) = dw;
-               dw = SUBKEY_L(i + 4) ^ SUBKEY_R(i + 4); dw = rol32(dw, 9);/* round 5 */
+               dw = SUBKEY_L(i + 4) ^ SUBKEY_R(i + 4); dw = ROL8(dw);/* round 5 */
                SUBKEY_R(i + 4) = SUBKEY_L(i + 4) ^ dw; SUBKEY_L(i + 4) = dw;
-               dw = SUBKEY_L(i + 5) ^ SUBKEY_R(i + 5); dw = rol32(dw, 8);/* round 6 */
+               dw = SUBKEY_L(i + 5) ^ SUBKEY_R(i + 5); dw = ROL8(dw);/* round 6 */
                SUBKEY_R(i + 5) = SUBKEY_L(i + 5) ^ dw; SUBKEY_L(i + 5) = dw;
                i += 8;
        } while (i < max);
@@ -587,10 +599,10 @@ static void camellia_setup128(const unsigned char *key, u32 *subkey)
        /**
         *  k == kll || klr || krl || krr (|| is concatenation)
         */
-       kll = get_unaligned_be32(key);
-       klr = get_unaligned_be32(key + 4);
-       krl = get_unaligned_be32(key + 8);
-       krr = get_unaligned_be32(key + 12);
+       GETU32(kll, key     );
+       GETU32(klr, key +  4);
+       GETU32(krl, key +  8);
+       GETU32(krr, key + 12);
 
        /* generate KL dependent subkeys */
        /* kw1 */
@@ -695,14 +707,14 @@ static void camellia_setup256(const unsigned char *key, u32 *subkey)
         *  key = (kll || klr || krl || krr || krll || krlr || krrl || krrr)
         *  (|| is concatenation)
         */
-       kll = get_unaligned_be32(key);
-       klr = get_unaligned_be32(key + 4);
-       krl = get_unaligned_be32(key + 8);
-       krr = get_unaligned_be32(key + 12);
-       krll = get_unaligned_be32(key + 16);
-       krlr = get_unaligned_be32(key + 20);
-       krrl = get_unaligned_be32(key + 24);
-       krrr = get_unaligned_be32(key + 28);
+       GETU32(kll,  key     );
+       GETU32(klr,  key +  4);
+       GETU32(krl,  key +  8);
+       GETU32(krr,  key + 12);
+       GETU32(krll, key + 16);
+       GETU32(krlr, key + 20);
+       GETU32(krrl, key + 24);
+       GETU32(krrr, key + 28);
 
        /* generate KL dependent subkeys */
        /* kw1 */
@@ -858,13 +870,13 @@ static void camellia_setup192(const unsigned char *key, u32 *subkey)
        t0 &= ll;                                                       \
        t2 |= rr;                                                       \
        rl ^= t2;                                                       \
-       lr ^= rol32(t0, 1);                                             \
+       lr ^= ROL1(t0);                                                 \
        t3 = krl;                                                       \
        t1 = klr;                                                       \
        t3 &= rl;                                                       \
        t1 |= lr;                                                       \
        ll ^= t1;                                                       \
-       rr ^= rol32(t3, 1);                                             \
+       rr ^= ROL1(t3);                                                 \
     } while(0)
 
 #define CAMELLIA_ROUNDSM(xl, xr, kl, kr, yl, yr, il, ir)               \
@@ -880,7 +892,7 @@ static void camellia_setup192(const unsigned char *key, u32 *subkey)
        il ^= kl;                                                       \
        ir ^= il ^ kr;                                                  \
        yl ^= ir;                                                       \
-       yr ^= ror32(il, 8) ^ ir;                                                \
+       yr ^= ROR8(il) ^ ir;                                            \
     } while(0)
 
 /* max = 24: 128bit encrypt, max = 32: 256bit encrypt */
index ae8494944c45dd54eb92f57f9651b86b6679f361..11c8c19f0fb7107acfd0c9189c70aeffc5dfba06 100644 (file)
@@ -448,8 +448,10 @@ config PATA_MARVELL
        tristate "Marvell PATA support via legacy mode"
        depends on PCI
        help
-         This option enables limited support for the Marvell 88SE6145 ATA
-         controller.
+         This option enables limited support for the Marvell 88SE61xx ATA
+         controllers. If you wish to use only the SATA ports then select
+         the AHCI driver alone. If you wish to the use the PATA port or
+         both SATA and PATA include this driver.
 
          If unsure, say N.
 
index c729e6988bbb17db928de1cd903682cfc3dc2802..2e1a7cb2ed5f91553ef9d2a39326233197eae7bd 100644 (file)
@@ -420,7 +420,7 @@ static const struct ata_port_info ahci_port_info[] = {
        /* board_ahci_mv */
        {
                AHCI_HFLAGS     (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI |
-                                AHCI_HFLAG_MV_PATA),
+                                AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP),
                .flags          = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
                                  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA,
                .pio_mask       = 0x1f, /* pio0-4 */
@@ -487,7 +487,9 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */
        { PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */
        { PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */
+       { PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */
        { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
+       { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */
 
        /* JMicron 360/1/3/5/6, match class to avoid IDE function */
        { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
@@ -610,6 +612,15 @@ module_param(ahci_em_messages, int, 0444);
 MODULE_PARM_DESC(ahci_em_messages,
        "Set AHCI Enclosure Management Message type (0 = disabled, 1 = LED");
 
+#if defined(CONFIG_PATA_MARVELL) || defined(CONFIG_PATA_MARVELL_MODULE)
+static int marvell_enable;
+#else
+static int marvell_enable = 1;
+#endif
+module_param(marvell_enable, int, 0644);
+MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)");
+
+
 static inline int ahci_nr_ports(u32 cap)
 {
        return (cap & 0x1f) + 1;
@@ -732,6 +743,8 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
                           "MV_AHCI HACK: port_map %x -> %x\n",
                           port_map,
                           port_map & mv);
+               dev_printk(KERN_ERR, &pdev->dev,
+                         "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n");
 
                port_map &= mv;
        }
@@ -2533,6 +2546,12 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (!printed_version++)
                dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
+       /* The AHCI driver can only drive the SATA ports, the PATA driver
+          can drive them all so if both drivers are selected make sure
+          AHCI stays out of the way */
+       if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable)
+               return -ENODEV;
+
        /* acquire resources */
        rc = pcim_enable_device(pdev);
        if (rc)
index 304fdc6f1dc2c8bce53e7e4e1fca18d982762f31..2a4c516894f0018c7c370168b4ae004f25598546 100644 (file)
@@ -1315,11 +1315,6 @@ fsm_start:
                break;
 
        case HSM_ST_ERR:
-               /* make sure qc->err_mask is available to
-                * know what's wrong and recover
-                */
-               WARN_ON(!(qc->err_mask & (AC_ERR_DEV | AC_ERR_HSM)));
-
                ap->hsm_task_state = HSM_ST_IDLE;
 
                /* complete taskfile transaction */
index 24a011b25024abf4f0da6c8032262934d76db81e..0d87eec849665fe3fac8b276ba6b40009cd129e7 100644 (file)
 #include <linux/ata.h>
 
 #define DRV_NAME       "pata_marvell"
-#define DRV_VERSION    "0.1.4"
+#define DRV_VERSION    "0.1.6"
 
 /**
- *     marvell_pre_reset       -       check for 40/80 pin
- *     @link: link
- *     @deadline: deadline jiffies for the operation
+ *     marvell_pata_active     -       check if PATA is active
+ *     @pdev: PCI device
  *
- *     Perform the PATA port setup we need.
+ *     Returns 1 if the PATA port may be active. We know how to check this
+ *     for the 6145 but not the other devices
  */
 
-static int marvell_pre_reset(struct ata_link *link, unsigned long deadline)
+static int marvell_pata_active(struct pci_dev *pdev)
 {
-       struct ata_port *ap = link->ap;
-       struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+       int i;
        u32 devices;
        void __iomem *barp;
-       int i;
 
-       /* Check if our port is enabled */
+       /* We don't yet know how to do this for other devices */
+       if (pdev->device != 0x6145)
+               return 1;       
 
        barp = pci_iomap(pdev, 5, 0x10);
        if (barp == NULL)
                return -ENOMEM;
+
        printk("BAR5:");
        for(i = 0; i <= 0x0F; i++)
                printk("%02X:%02X ", i, ioread8(barp + i));
@@ -51,9 +52,27 @@ static int marvell_pre_reset(struct ata_link *link, unsigned long deadline)
        devices = ioread32(barp + 0x0C);
        pci_iounmap(pdev, barp);
 
-       if ((pdev->device == 0x6145) && (ap->port_no == 0) &&
-           (!(devices & 0x10)))        /* PATA enable ? */
-               return -ENOENT;
+       if (devices & 0x10)
+               return 1;
+       return 0;
+}
+
+/**
+ *     marvell_pre_reset       -       check for 40/80 pin
+ *     @link: link
+ *     @deadline: deadline jiffies for the operation
+ *
+ *     Perform the PATA port setup we need.
+ */
+
+static int marvell_pre_reset(struct ata_link *link, unsigned long deadline)
+{
+       struct ata_port *ap = link->ap;
+       struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+
+       if (pdev->device == 0x6145 && ap->port_no == 0 &&
+               !marvell_pata_active(pdev))     /* PATA enable ? */
+                       return -ENOENT;
 
        return ata_sff_prereset(link, deadline);
 }
@@ -128,6 +147,12 @@ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *i
        if (pdev->device == 0x6101)
                ppi[1] = &ata_dummy_port_info;
 
+#if defined(CONFIG_AHCI) || defined(CONFIG_AHCI_MODULE)
+       if (!marvell_pata_active(pdev)) {
+               printk(KERN_INFO DRV_NAME ": PATA port not active, deferring to AHCI driver.\n");
+               return -ENODEV;
+       }
+#endif
        return ata_pci_sff_init_one(pdev, ppi, &marvell_sht, NULL);
 }
 
index 720b8645f58a3121d96112f60e03625fd12de8bc..e970b227fbce39037b4f14879eb4152056df59a5 100644 (file)
@@ -322,9 +322,6 @@ static int __devinit sil680_init_one(struct pci_dev *pdev,
        /* Try to acquire MMIO resources and fallback to PIO if
         * that fails
         */
-       rc = pcim_enable_device(pdev);
-       if (rc)
-               return rc;
        rc = pcim_iomap_regions(pdev, 1 << SIL680_MMIO_BAR, DRV_NAME);
        if (rc)
                goto use_ioports;
index 13c1d2af18ac3e0ff02ef35b926df40955ac3006..c815f8ecf6e64c758eb2a43deebc5c20f259ab03 100644 (file)
@@ -667,7 +667,8 @@ static const struct pci_device_id mv_pci_tbl[] = {
        { PCI_VDEVICE(MARVELL, 0x5041), chip_504x },
        { PCI_VDEVICE(MARVELL, 0x5080), chip_5080 },
        { PCI_VDEVICE(MARVELL, 0x5081), chip_508x },
-       /* RocketRAID 1740/174x have different identifiers */
+       /* RocketRAID 1720/174x have different identifiers */
+       { PCI_VDEVICE(TTI, 0x1720), chip_6042 },
        { PCI_VDEVICE(TTI, 0x1740), chip_508x },
        { PCI_VDEVICE(TTI, 0x1742), chip_508x },
 
index 858f70610edaa8370a6b79b2367147cf3d69dba9..1e1f3f3757ae7bf98fd7ce2d39cfafdc644095f0 100644 (file)
@@ -309,8 +309,6 @@ static void nv_nf2_freeze(struct ata_port *ap);
 static void nv_nf2_thaw(struct ata_port *ap);
 static void nv_ck804_freeze(struct ata_port *ap);
 static void nv_ck804_thaw(struct ata_port *ap);
-static int nv_hardreset(struct ata_link *link, unsigned int *class,
-                       unsigned long deadline);
 static int nv_adma_slave_config(struct scsi_device *sdev);
 static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc);
 static void nv_adma_qc_prep(struct ata_queued_cmd *qc);
@@ -407,7 +405,7 @@ static struct scsi_host_template nv_swncq_sht = {
 
 static struct ata_port_operations nv_generic_ops = {
        .inherits               = &ata_bmdma_port_ops,
-       .hardreset              = nv_hardreset,
+       .hardreset              = ATA_OP_NULL,
        .scr_read               = nv_scr_read,
        .scr_write              = nv_scr_write,
 };
@@ -1588,21 +1586,6 @@ static void nv_mcp55_thaw(struct ata_port *ap)
        ata_sff_thaw(ap);
 }
 
-static int nv_hardreset(struct ata_link *link, unsigned int *class,
-                       unsigned long deadline)
-{
-       int rc;
-
-       /* SATA hardreset fails to retrieve proper device signature on
-        * some controllers.  Request follow up SRST.  For more info,
-        * see http://bugzilla.kernel.org/show_bug.cgi?id=3352
-        */
-       rc = sata_sff_hardreset(link, class, deadline);
-       if (rc)
-               return rc;
-       return -EAGAIN;
-}
-
 static void nv_adma_error_handler(struct ata_port *ap)
 {
        struct nv_adma_port_priv *pp = ap->private_data;
index 5ca1d80de182bfa3bb333f0aeca907f7929ed26c..4eee533f3f4af7e8f5c9d811c7ac671d95d05083 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <linux/delay.h>
 #include <asm/io.h>
 
 /*
@@ -151,13 +152,13 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_LE,
  */
 static int verify_pmtmr_rate(void)
 {
-       u32 value1, value2;
+       cycle_t value1, value2;
        unsigned long count, delta;
 
        mach_prepare_counter();
-       value1 = read_pmtmr();
+       value1 = clocksource_acpi_pm.read();
        mach_countup(&count);
-       value2 = read_pmtmr();
+       value2 = clocksource_acpi_pm.read();
        delta = (value2 - value1) & ACPI_PM_MASK;
 
        /* Check that the PMTMR delta is within 5% of what we expect */
@@ -175,10 +176,13 @@ static int verify_pmtmr_rate(void)
 #define verify_pmtmr_rate() (0)
 #endif
 
+/* Number of monotonicity checks to perform during initialization */
+#define ACPI_PM_MONOTONICITY_CHECKS 10
+
 static int __init init_acpi_pm_clocksource(void)
 {
-       u32 value1, value2;
-       unsigned int i;
+       cycle_t value1, value2;
+       unsigned int i, j, good = 0;
 
        if (!pmtmr_ioport)
                return -ENODEV;
@@ -187,24 +191,32 @@ static int __init init_acpi_pm_clocksource(void)
                                                clocksource_acpi_pm.shift);
 
        /* "verify" this timing source: */
-       value1 = read_pmtmr();
-       for (i = 0; i < 10000; i++) {
-               value2 = read_pmtmr();
-               if (value2 == value1)
-                       continue;
-               if (value2 > value1)
-                       goto pm_good;
-               if ((value2 < value1) && ((value2) < 0xFFF))
-                       goto pm_good;
-               printk(KERN_INFO "PM-Timer had inconsistent results:"
-                       " 0x%#x, 0x%#x - aborting.\n", value1, value2);
-               return -EINVAL;
+       for (j = 0; j < ACPI_PM_MONOTONICITY_CHECKS; j++) {
+               value1 = clocksource_acpi_pm.read();
+               for (i = 0; i < 10000; i++) {
+                       value2 = clocksource_acpi_pm.read();
+                       if (value2 == value1)
+                               continue;
+                       if (value2 > value1)
+                               good++;
+                               break;
+                       if ((value2 < value1) && ((value2) < 0xFFF))
+                               good++;
+                               break;
+                       printk(KERN_INFO "PM-Timer had inconsistent results:"
+                              " 0x%#llx, 0x%#llx - aborting.\n",
+                              value1, value2);
+                       return -EINVAL;
+               }
+               udelay(300 * i);
+       }
+
+       if (good != ACPI_PM_MONOTONICITY_CHECKS) {
+               printk(KERN_INFO "PM-Timer failed consistency check "
+                      " (0x%#llx) - aborting.\n", value1);
+               return -ENODEV;
        }
-       printk(KERN_INFO "PM-Timer had no reasonable result:"
-                       " 0x%#x - aborting.\n", value1);
-       return -ENODEV;
 
-pm_good:
        if (verify_pmtmr_rate() != 0)
                return -ENODEV;
 
index 2ec921bf3c6016b6dc19e5999e3ccf6682e209bf..18f4d7f6ce6d0d3b983d34fffc7b6da437679cc7 100644 (file)
@@ -63,7 +63,7 @@
 }
 
 /* table of devices that work with this driver */
-static const struct usb_device_id bcm5974_table [] = {
+static const struct usb_device_id bcm5974_table[] = {
        /* MacbookAir1.1 */
        BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING_ANSI),
        BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING_ISO),
@@ -105,7 +105,7 @@ struct tp_header {
 
 /* trackpad finger structure */
 struct tp_finger {
-       __le16 origin;          /* left/right origin? */
+       __le16 origin;          /* zero when switching track finger */
        __le16 abs_x;           /* absolute x coodinate */
        __le16 abs_y;           /* absolute y coodinate */
        __le16 rel_x;           /* relative x coodinate */
@@ -159,6 +159,7 @@ struct bcm5974 {
        struct bt_data *bt_data;        /* button transferred data */
        struct urb *tp_urb;             /* trackpad usb request block */
        struct tp_data *tp_data;        /* trackpad transferred data */
+       int fingers;                    /* number of fingers on trackpad */
 };
 
 /* logical dimensions */
@@ -172,6 +173,10 @@ struct bcm5974 {
 #define SN_WIDTH       100             /* width signal-to-noise ratio */
 #define SN_COORD       250             /* coordinate signal-to-noise ratio */
 
+/* pressure thresholds */
+#define PRESSURE_LOW   (2 * DIM_PRESSURE / SN_PRESSURE)
+#define PRESSURE_HIGH  (3 * PRESSURE_LOW)
+
 /* device constants */
 static const struct bcm5974_config bcm5974_config_table[] = {
        {
@@ -248,6 +253,7 @@ static void setup_events_to_report(struct input_dev *input_dev,
                                0, cfg->y.dim, cfg->y.fuzz, 0);
 
        __set_bit(EV_KEY, input_dev->evbit);
+       __set_bit(BTN_TOUCH, input_dev->keybit);
        __set_bit(BTN_TOOL_FINGER, input_dev->keybit);
        __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
        __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
@@ -273,32 +279,66 @@ static int report_tp_state(struct bcm5974 *dev, int size)
        const struct tp_finger *f = dev->tp_data->finger;
        struct input_dev *input = dev->input;
        const int fingers = (size - 26) / 28;
-       int p = 0, w, x, y, n = 0;
+       int raw_p, raw_w, raw_x, raw_y;
+       int ptest = 0, origin = 0, nmin = 0, nmax = 0;
+       int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0;
 
        if (size < 26 || (size - 26) % 28 != 0)
                return -EIO;
 
+       /* always track the first finger; when detached, start over */
        if (fingers) {
-               p = raw2int(f->force_major);
-               w = raw2int(f->size_major);
-               x = raw2int(f->abs_x);
-               y = raw2int(f->abs_y);
-               n = p > 0 ? fingers : 0;
+               raw_p = raw2int(f->force_major);
+               raw_w = raw2int(f->size_major);
+               raw_x = raw2int(f->abs_x);
+               raw_y = raw2int(f->abs_y);
 
                dprintk(9,
-                       "bcm5974: p: %+05d w: %+05d x: %+05d y: %+05d n: %d\n",
-                       p, w, x, y, n);
+                       "bcm5974: raw: p: %+05d w: %+05d x: %+05d y: %+05d\n",
+                       raw_p, raw_w, raw_x, raw_y);
+
+               ptest = int2bound(&c->p, raw_p);
+               origin = raw2int(f->origin);
+       }
 
-               input_report_abs(input, ABS_TOOL_WIDTH, int2bound(&c->w, w));
-               input_report_abs(input, ABS_X, int2bound(&c->x, x - c->x.devmin));
-               input_report_abs(input, ABS_Y, int2bound(&c->y, c->y.devmax - y));
+       /* while tracking finger still valid, count all fingers */
+       if (ptest > PRESSURE_LOW && origin) {
+               abs_p = ptest;
+               abs_w = int2bound(&c->w, raw_w);
+               abs_x = int2bound(&c->x, raw_x - c->x.devmin);
+               abs_y = int2bound(&c->y, c->y.devmax - raw_y);
+               for (; f != dev->tp_data->finger + fingers; f++) {
+                       ptest = int2bound(&c->p, raw2int(f->force_major));
+                       if (ptest > PRESSURE_LOW)
+                               nmax++;
+                       if (ptest > PRESSURE_HIGH)
+                               nmin++;
+               }
        }
 
-       input_report_abs(input, ABS_PRESSURE, int2bound(&c->p, p));
+       if (dev->fingers < nmin)
+               dev->fingers = nmin;
+       if (dev->fingers > nmax)
+               dev->fingers = nmax;
+
+       input_report_key(input, BTN_TOUCH, dev->fingers > 0);
+       input_report_key(input, BTN_TOOL_FINGER, dev->fingers == 1);
+       input_report_key(input, BTN_TOOL_DOUBLETAP, dev->fingers == 2);
+       input_report_key(input, BTN_TOOL_TRIPLETAP, dev->fingers > 2);
 
-       input_report_key(input, BTN_TOOL_FINGER, n == 1);
-       input_report_key(input, BTN_TOOL_DOUBLETAP, n == 2);
-       input_report_key(input, BTN_TOOL_TRIPLETAP, n > 2);
+       input_report_abs(input, ABS_PRESSURE, abs_p);
+       input_report_abs(input, ABS_TOOL_WIDTH, abs_w);
+
+       if (abs_p) {
+               input_report_abs(input, ABS_X, abs_x);
+               input_report_abs(input, ABS_Y, abs_y);
+
+               dprintk(8,
+                       "bcm5974: abs: p: %+05d w: %+05d x: %+05d y: %+05d "
+                       "nmin: %d nmax: %d n: %d\n",
+                       abs_p, abs_w, abs_x, abs_y, nmin, nmax, dev->fingers);
+
+       }
 
        input_sync(input);
 
index 3282b741e2460ed20d30ef4fd3a5f655fc228f5c..5aafe24984c598236efdd54dde31e8db9ec6cc60 100644 (file)
@@ -305,7 +305,7 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
                .ident = "Lenovo 3000 n100",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-                       DMI_MATCH(DMI_PRODUCT_VERSION, "3000 N100"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "076804U"),
                },
        },
        {
index db00b05917331b5901091f7697fa1fa2f2de8d96..f1216cf6fa8fdd098cc3bc9c145d352fb907059d 100644 (file)
@@ -423,7 +423,7 @@ int chp_new(struct chp_id chpid)
        ret = sysfs_create_group(&chp->dev.kobj, &chp_attr_group);
        if (ret) {
                device_unregister(&chp->dev);
-               goto out_free;
+               goto out;
        }
        mutex_lock(&channel_subsystems[chpid.cssid]->mutex);
        if (channel_subsystems[chpid.cssid]->cm_enabled) {
@@ -432,14 +432,15 @@ int chp_new(struct chp_id chpid)
                        sysfs_remove_group(&chp->dev.kobj, &chp_attr_group);
                        device_unregister(&chp->dev);
                        mutex_unlock(&channel_subsystems[chpid.cssid]->mutex);
-                       goto out_free;
+                       goto out;
                }
        }
        channel_subsystems[chpid.cssid]->chps[chpid.id] = chp;
        mutex_unlock(&channel_subsystems[chpid.cssid]->mutex);
-       return ret;
+       goto out;
 out_free:
        kfree(chp);
+out:
        return ret;
 }
 
index 33bff8fec7d10b0a5b02cb0ed0824cdd210b2256..5954b905e3cab9723116646069356ad7928c31d8 100644 (file)
@@ -208,8 +208,10 @@ cio_start_key (struct subchannel *sch,     /* subchannel structure */
        case 1:         /* status pending */
        case 2:         /* busy */
                return -EBUSY;
-       default:                /* device/path not operational */
+       case 3:         /* device/path not operational */
                return cio_start_handle_notoper(sch, lpm);
+       default:
+               return ccode;
        }
 }
 
index 51489eff6b0b4484ad234e6b7b7a0819a6d1ddd6..1261e1a9e8cd518f78aa44754a00318182de2ad8 100644 (file)
@@ -633,6 +633,11 @@ channel_subsystem_release(struct device *dev)
 
        css = to_css(dev);
        mutex_destroy(&css->mutex);
+       if (css->pseudo_subchannel) {
+               /* Implies that it has been generated but never registered. */
+               css_subchannel_release(&css->pseudo_subchannel->dev);
+               css->pseudo_subchannel = NULL;
+       }
        kfree(css);
 }
 
@@ -785,11 +790,15 @@ init_channel_subsystem (void)
                }
                channel_subsystems[i] = css;
                ret = setup_css(i);
-               if (ret)
-                       goto out_free;
+               if (ret) {
+                       kfree(channel_subsystems[i]);
+                       goto out_unregister;
+               }
                ret = device_register(&css->device);
-               if (ret)
-                       goto out_free_all;
+               if (ret) {
+                       put_device(&css->device);
+                       goto out_unregister;
+               }
                if (css_chsc_characteristics.secm) {
                        ret = device_create_file(&css->device,
                                                 &dev_attr_cm_enable);
@@ -802,7 +811,7 @@ init_channel_subsystem (void)
        }
        ret = register_reboot_notifier(&css_reboot_notifier);
        if (ret)
-               goto out_pseudo;
+               goto out_unregister;
        css_init_done = 1;
 
        /* Enable default isc for I/O subchannels. */
@@ -810,18 +819,12 @@ init_channel_subsystem (void)
 
        for_each_subchannel(__init_channel_subsystem, NULL);
        return 0;
-out_pseudo:
-       device_unregister(&channel_subsystems[i]->pseudo_subchannel->dev);
 out_file:
-       device_remove_file(&channel_subsystems[i]->device,
-                          &dev_attr_cm_enable);
+       if (css_chsc_characteristics.secm)
+               device_remove_file(&channel_subsystems[i]->device,
+                                  &dev_attr_cm_enable);
 out_device:
        device_unregister(&channel_subsystems[i]->device);
-out_free_all:
-       kfree(channel_subsystems[i]->pseudo_subchannel->lock);
-       kfree(channel_subsystems[i]->pseudo_subchannel);
-out_free:
-       kfree(channel_subsystems[i]);
 out_unregister:
        while (i > 0) {
                struct channel_subsystem *css;
@@ -829,6 +832,7 @@ out_unregister:
                i--;
                css = channel_subsystems[i];
                device_unregister(&css->pseudo_subchannel->dev);
+               css->pseudo_subchannel = NULL;
                if (css_chsc_characteristics.secm)
                        device_remove_file(&css->device,
                                           &dev_attr_cm_enable);
index 550508df952b89693f5b13e4de5e5bec2a976ac3..84cc9ea346dbc264639d892a19e591ef7535ef8f 100644 (file)
@@ -658,6 +658,13 @@ ccw_device_offline(struct ccw_device *cdev)
 {
        struct subchannel *sch;
 
+       /* Allow ccw_device_offline while disconnected. */
+       if (cdev->private->state == DEV_STATE_DISCONNECTED ||
+           cdev->private->state == DEV_STATE_NOT_OPER) {
+               cdev->private->flags.donotify = 0;
+               ccw_device_done(cdev, DEV_STATE_NOT_OPER);
+               return 0;
+       }
        if (ccw_device_is_orphan(cdev)) {
                ccw_device_done(cdev, DEV_STATE_OFFLINE);
                return 0;
index 1eb64d08b60a9591bd994f757c0372602b7c7ef4..95b3ec89c126cdd0609306c034ae348a1324a184 100644 (file)
@@ -208,7 +208,7 @@ static int ohci_omap_init(struct usb_hcd *hcd)
        if (cpu_is_omap16xx())
                ocpi_enable();
 
-#ifdef CONFIG_ARCH_OMAP_OTG
+#ifdef CONFIG_USB_OTG
        if (need_transceiver) {
                ohci->transceiver = otg_get_transceiver();
                if (ohci->transceiver) {
index 7b74238ad1c7a2ab1aed27bc219b94f23b997c9e..e980766bb84bed3fc05abb203dc3c3bc02b7daff 100644 (file)
@@ -161,7 +161,7 @@ static int usb_console_setup(struct console *co, char *options)
                if (serial->type->set_termios) {
                        termios->c_cflag = cflag;
                        tty_termios_encode_baud_rate(termios, baud, baud);
-                       serial->type->set_termios(NULL, port, &dummy);
+                       serial->type->set_termios(tty, port, &dummy);
 
                        port->port.tty = NULL;
                        kfree(termios);
index d4427cb869791cd0f1b910f5371f78aefe42c626..2e15da5459cf6bd5b0e144a0fef70cccfa6549c3 100644 (file)
@@ -60,7 +60,7 @@
 
 #define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10))
 
-#define BALLOON_CLASS_NAME "memory"
+#define BALLOON_CLASS_NAME "xen_memory"
 
 struct balloon_stats {
        /* We aim for 'current allocation' == 'target allocation'. */
index 9abcd2b329f7357b0af65065613e996b643e1747..e9b20173fef33835e9d87be1a9b67e718b8dfe0a 100644 (file)
@@ -1279,6 +1279,12 @@ static int nfs_parse_mount_options(char *raw,
                }
        }
 
+       if (errors > 0) {
+               dfprintk(MOUNT, "NFS: parsing encountered %d error%s\n",
+                               errors, (errors == 1 ? "" : "s"));
+               if (!sloppy)
+                       return 0;
+       }
        return 1;
 
 out_nomem:
index 1540981574738e45b4585c27d9cf5a8f43df21c9..73db464cd08b7a213365c0331824ce478a69e4d1 100644 (file)
@@ -302,18 +302,6 @@ long long ubifs_calc_available(const struct ubifs_info *c, int min_idx_lebs)
        int subtract_lebs;
        long long available;
 
-       /*
-        * Force the amount available to the total size reported if the used
-        * space is zero.
-        */
-       if (c->lst.total_used <= UBIFS_INO_NODE_SZ &&
-           c->budg_data_growth + c->budg_dd_growth == 0) {
-               /* Do the same calculation as for c->block_cnt */
-               available = c->main_lebs - 2;
-               available *= c->leb_size - c->dark_wm;
-               return available;
-       }
-
        available = c->main_bytes - c->lst.total_used;
 
        /*
@@ -714,34 +702,106 @@ void ubifs_release_dirty_inode_budget(struct ubifs_info *c,
 }
 
 /**
- * ubifs_budg_get_free_space - return amount of free space.
+ * ubifs_reported_space - calculate reported free space.
+ * @c: the UBIFS file-system description object
+ * @free: amount of free space
+ *
+ * This function calculates amount of free space which will be reported to
+ * user-space. User-space application tend to expect that if the file-system
+ * (e.g., via the 'statfs()' call) reports that it has N bytes available, they
+ * are able to write a file of size N. UBIFS attaches node headers to each data
+ * node and it has to write indexind nodes as well. This introduces additional
+ * overhead, and UBIFS it has to report sligtly less free space to meet the
+ * above expectetion.
+ *
+ * This function assumes free space is made up of uncompressed data nodes and
+ * full index nodes (one per data node, tripled because we always allow enough
+ * space to write the index thrice).
+ *
+ * Note, the calculation is pessimistic, which means that most of the time
+ * UBIFS reports less space than it actually has.
+ */
+long long ubifs_reported_space(const struct ubifs_info *c, uint64_t free)
+{
+       int divisor, factor, f;
+
+       /*
+        * Reported space size is @free * X, where X is UBIFS block size
+        * divided by UBIFS block size + all overhead one data block
+        * introduces. The overhead is the node header + indexing overhead.
+        *
+        * Indexing overhead calculations are based on the following formula:
+        * I = N/(f - 1) + 1, where I - number of indexing nodes, N - number
+        * of data nodes, f - fanout. Because effective UBIFS fanout is twice
+        * as less than maximum fanout, we assume that each data node
+        * introduces 3 * @c->max_idx_node_sz / (@c->fanout/2 - 1) bytes.
+        * Note, the multiplier 3 is because UBIFS reseves thrice as more space
+        * for the index.
+        */
+       f = c->fanout > 3 ? c->fanout >> 1 : 2;
+       factor = UBIFS_BLOCK_SIZE;
+       divisor = UBIFS_MAX_DATA_NODE_SZ;
+       divisor += (c->max_idx_node_sz * 3) / (f - 1);
+       free *= factor;
+       do_div(free, divisor);
+       return free;
+}
+
+/**
+ * ubifs_get_free_space - return amount of free space.
  * @c: UBIFS file-system description object
  *
- * This function returns amount of free space on the file-system.
+ * This function calculates amount of free space to report to user-space.
+ *
+ * Because UBIFS may introduce substantial overhead (the index, node headers,
+ * alighment, wastage at the end of eraseblocks, etc), it cannot report real
+ * amount of free flash space it has (well, because not all dirty space is
+ * reclamable, UBIFS does not actually know the real amount). If UBIFS did so,
+ * it would bread user expectetion about what free space is. Users seem to
+ * accustomed to assume that if the file-system reports N bytes of free space,
+ * they would be able to fit a file of N bytes to the FS. This almost works for
+ * 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_budg_get_free_space(struct ubifs_info *c)
+long long ubifs_get_free_space(struct ubifs_info *c)
 {
-       int min_idx_lebs, rsvd_idx_lebs;
+       int min_idx_lebs, rsvd_idx_lebs, lebs;
        long long available, outstanding, free;
 
-       /* Do exactly the same calculations as in 'do_budget_space()' */
        spin_lock(&c->space_lock);
        min_idx_lebs = ubifs_calc_min_idx_lebs(c);
+       outstanding = c->budg_data_growth + c->budg_dd_growth;
 
-       if (min_idx_lebs > c->lst.idx_lebs)
-               rsvd_idx_lebs = min_idx_lebs - c->lst.idx_lebs;
-       else
-               rsvd_idx_lebs = 0;
-
-       if (rsvd_idx_lebs > c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt
-                               - c->lst.taken_empty_lebs) {
+       /*
+        * Force the amount available to the total size reported if the used
+        * space is zero.
+        */
+       if (c->lst.total_used <= UBIFS_INO_NODE_SZ && !outstanding) {
                spin_unlock(&c->space_lock);
-               return 0;
+               return (long long)c->block_cnt << UBIFS_BLOCK_SHIFT;
        }
 
        available = ubifs_calc_available(c, min_idx_lebs);
-       outstanding = c->budg_data_growth + c->budg_dd_growth;
-       c->min_idx_lebs = min_idx_lebs;
+
+       /*
+        * When reporting free space to user-space, UBIFS guarantees that it is
+        * possible to write a file of free space size. This means that for
+        * empty LEBs we may use more precise calculations than
+        * 'ubifs_calc_available()' is using. Namely, we know that in empty
+        * LEBs we would waste only @c->leb_overhead bytes, not @c->dark_wm.
+        * Thus, amend the available space.
+        *
+        * 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;
+       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)
index 5c96f1fb70166dbd75217692722d9e727be1d031..2b267c9a18065030ff8caff09fc6b2d5cc08b558 100644 (file)
@@ -587,7 +587,6 @@ static int ubifs_unlink(struct inode *dir, struct dentry *dentry)
        if (err) {
                if (err != -ENOSPC)
                        return err;
-               err = 0;
                budgeted = 0;
        }
 
index 4071d1cae29f7cb0b65221ecd541b3832b37be31..3d698e2022b1ee7b2c8250fc75c89fff79785097 100644 (file)
@@ -793,7 +793,7 @@ static int do_truncation(struct ubifs_info *c, struct inode *inode,
        int err;
        struct ubifs_budget_req req;
        loff_t old_size = inode->i_size, new_size = attr->ia_size;
-       int offset = new_size & (UBIFS_BLOCK_SIZE - 1);
+       int offset = new_size & (UBIFS_BLOCK_SIZE - 1), budgeted = 1;
        struct ubifs_inode *ui = ubifs_inode(inode);
 
        dbg_gen("ino %lu, size %lld -> %lld", inode->i_ino, old_size, new_size);
@@ -811,8 +811,15 @@ static int do_truncation(struct ubifs_info *c, struct inode *inode,
        /* A funny way to budget for truncation node */
        req.dirtied_ino_d = UBIFS_TRUN_NODE_SZ;
        err = ubifs_budget_space(c, &req);
-       if (err)
-               return err;
+       if (err) {
+               /*
+                * Treat truncations to zero as deletion and always allow them,
+                * just like we do for '->unlink()'.
+                */
+               if (new_size || err != -ENOSPC)
+                       return err;
+               budgeted = 0;
+       }
 
        err = vmtruncate(inode, new_size);
        if (err)
@@ -869,7 +876,12 @@ static int do_truncation(struct ubifs_info *c, struct inode *inode,
        err = ubifs_jnl_truncate(c, inode, old_size, new_size);
        mutex_unlock(&ui->ui_mutex);
 out_budg:
-       ubifs_release_budget(c, &req);
+       if (budgeted)
+               ubifs_release_budget(c, &req);
+       else {
+               c->nospace = c->nospace_rp = 0;
+               smp_wmb();
+       }
        return err;
 }
 
index adee7b5ddeabb6cb63769f1cfcd4b68ba959e40c..e045c8b55423e9adc7c312efbd8164f7e3584bc5 100644 (file)
@@ -211,14 +211,8 @@ static const struct ubifs_lprops *scan_for_dirty(struct ubifs_info *c,
  * dirty index heap, and it falls-back to LPT scanning if the heaps are empty
  * or do not have an LEB which satisfies the @min_space criteria.
  *
- * Note:
- *   o LEBs which have less than dead watermark of dirty space are never picked
- *   by this function;
- *
- * Returns zero and the LEB properties of
- * found dirty LEB in case of success, %-ENOSPC if no dirty LEB was found and a
- * negative error code in case of other failures. The returned LEB is marked as
- * "taken".
+ * Note, LEBs which have less than dead watermark of free + dirty space are
+ * never picked by this function.
  *
  * The additional @pick_free argument controls if this function has to return a
  * free or freeable LEB if one is present. For example, GC must to set it to %1,
@@ -231,6 +225,10 @@ static const struct ubifs_lprops *scan_for_dirty(struct ubifs_info *c,
  *
  * In addition @pick_free is set to %2 by the recovery process in order to
  * recover gc_lnum in which case an index LEB must not be returned.
+ *
+ * This function returns zero and the LEB properties of found dirty LEB in case
+ * of success, %-ENOSPC if no dirty LEB was found and a negative error code in
+ * case of other failures. The returned LEB is marked as "taken".
  */
 int ubifs_find_dirty_leb(struct ubifs_info *c, struct ubifs_lprops *ret_lp,
                         int min_space, int pick_free)
@@ -245,7 +243,7 @@ int ubifs_find_dirty_leb(struct ubifs_info *c, struct ubifs_lprops *ret_lp,
                int lebs, rsvd_idx_lebs = 0;
 
                spin_lock(&c->space_lock);
-               lebs = c->lst.empty_lebs;
+               lebs = c->lst.empty_lebs + c->idx_gc_cnt;
                lebs += c->freeable_cnt - c->lst.taken_empty_lebs;
 
                /*
@@ -317,7 +315,7 @@ int ubifs_find_dirty_leb(struct ubifs_info *c, struct ubifs_lprops *ret_lp,
                lp = idx_lp;
 
        if (lp) {
-               ubifs_assert(lp->dirty >= c->dead_wm);
+               ubifs_assert(lp->free + lp->dirty >= c->dead_wm);
                goto found;
        }
 
index d0f3dac2908133f1ea7398d8bac29ffbd5eaa8a8..13f1019c859f254bed9ee9512007b50ee79274da 100644 (file)
@@ -344,6 +344,12 @@ int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp)
                if (err)
                        goto out;
 
+               /* Allow for races with TNC */
+               c->gced_lnum = lnum;
+               smp_wmb();
+               c->gc_seq += 1;
+               smp_wmb();
+
                if (c->gc_lnum == -1) {
                        c->gc_lnum = lnum;
                        err = LEB_RETAINED;
index 87dabf9fe742ea05674ec8cb2bf78f5fe98f510d..4c12a9215d7f24571d13603a382179bb223a1b40 100644 (file)
@@ -283,38 +283,6 @@ static inline void *ubifs_idx_key(const struct ubifs_info *c,
        return (void *)((struct ubifs_branch *)idx->branches)->key;
 }
 
-/**
- * ubifs_reported_space - calculate reported free space.
- * @c: the UBIFS file-system description object
- * @free: amount of free space
- *
- * This function calculates amount of free space which will be reported to
- * user-space. User-space application tend to expect that if the file-system
- * (e.g., via the 'statfs()' call) reports that it has N bytes available, they
- * are able to write a file of size N. UBIFS attaches node headers to each data
- * node and it has to write indexind nodes as well. This introduces additional
- * overhead, and UBIFS it has to report sligtly less free space to meet the
- * above expectetion.
- *
- * This function assumes free space is made up of uncompressed data nodes and
- * full index nodes (one per data node, doubled because we always allow enough
- * space to write the index twice).
- *
- * Note, the calculation is pessimistic, which means that most of the time
- * UBIFS reports less space than it actually has.
- */
-static inline long long ubifs_reported_space(const struct ubifs_info *c,
-                                            uint64_t free)
-{
-       int divisor, factor;
-
-       divisor = UBIFS_MAX_DATA_NODE_SZ + (c->max_idx_node_sz * 3);
-       factor = UBIFS_MAX_DATA_NODE_SZ - UBIFS_DATA_NODE_SZ;
-       do_div(free, divisor);
-
-       return free * factor;
-}
-
 /**
  * ubifs_current_time - round current time to time granularity.
  * @inode: inode
@@ -325,4 +293,21 @@ static inline struct timespec ubifs_current_time(struct inode *inode)
                current_fs_time(inode->i_sb) : CURRENT_TIME_SEC;
 }
 
+/**
+ * ubifs_tnc_lookup - look up a file-system node.
+ * @c: UBIFS file-system description object
+ * @key: node key to lookup
+ * @node: the node is returned here
+ *
+ * This function look up and reads node with key @key. The caller has to make
+ * sure the @node buffer is large enough to fit the node. Returns zero in case
+ * of success, %-ENOENT if the node was not found, and a negative error code in
+ * case of failure.
+ */
+static inline int ubifs_tnc_lookup(struct ubifs_info *c,
+                                  const union ubifs_key *key, void *node)
+{
+       return ubifs_tnc_locate(c, key, node, NULL, NULL);
+}
+
 #endif /* __UBIFS_MISC_H__ */
index f71e6b8822c4fac6dbaab1913098e7a61c81dcfa..7562464ac83fba3c19101afea8cf9495bf6cd692 100644 (file)
@@ -370,8 +370,9 @@ static int ubifs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
        struct ubifs_info *c = dentry->d_sb->s_fs_info;
        unsigned long long free;
+       __le32 *uuid = (__le32 *)c->uuid;
 
-       free = ubifs_budg_get_free_space(c);
+       free = ubifs_get_free_space(c);
        dbg_gen("free space %lld bytes (%lld blocks)",
                free, free >> UBIFS_BLOCK_SHIFT);
 
@@ -386,7 +387,8 @@ static int ubifs_statfs(struct dentry *dentry, struct kstatfs *buf)
        buf->f_files = 0;
        buf->f_ffree = 0;
        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]);
        return 0;
 }
 
@@ -530,6 +532,12 @@ static int init_constants_early(struct ubifs_info *c)
        c->dead_wm = ALIGN(MIN_WRITE_SZ, c->min_io_size);
        c->dark_wm = ALIGN(UBIFS_MAX_NODE_SZ, c->min_io_size);
 
+       /*
+        * Calculate how many bytes would be wasted at the end of LEB if it was
+        * fully filled with data nodes of maximum size. This is used in
+        * calculations when reporting free space.
+        */
+       c->leb_overhead = c->leb_size % UBIFS_MAX_DATA_NODE_SZ;
        return 0;
 }
 
@@ -647,13 +655,11 @@ static int init_constants_late(struct ubifs_info *c)
         * internally because it does not make much sense for UBIFS, but it is
         * necessary to report something for the 'statfs()' call.
         *
-        * Subtract the LEB reserved for GC and the LEB which is reserved for
-        * deletions.
-        *
-        * Review 'ubifs_calc_available()' if changing this calculation.
+        * Subtract the LEB reserved for GC, the LEB which is reserved for
+        * deletions, and assume only one journal head is available.
         */
-       tmp64 = c->main_lebs - 2;
-       tmp64 *= (uint64_t)c->leb_size - c->dark_wm;
+       tmp64 = c->main_lebs - 2 - c->jhead_cnt + 1;
+       tmp64 *= (uint64_t)c->leb_size - c->leb_overhead;
        tmp64 = ubifs_reported_space(c, tmp64);
        c->block_cnt = tmp64 >> UBIFS_BLOCK_SHIFT;
 
index e909f4a96443a65de717771b3004344f02263332..7da209ab93788f8cafb30d6532b946897d9ae384 100644 (file)
@@ -506,7 +506,7 @@ static int fallible_read_node(struct ubifs_info *c, const union ubifs_key *key,
                if (keys_cmp(c, key, &node_key) != 0)
                        ret = 0;
        }
-       if (ret == 0)
+       if (ret == 0 && c->replaying)
                dbg_mnt("dangling branch LEB %d:%d len %d, key %s",
                        zbr->lnum, zbr->offs, zbr->len, DBGKEY(key));
        return ret;
@@ -1382,50 +1382,39 @@ static int lookup_level0_dirty(struct ubifs_info *c, const union ubifs_key *key,
 }
 
 /**
- * ubifs_tnc_lookup - look up a file-system node.
+ * maybe_leb_gced - determine if a LEB may have been garbage collected.
  * @c: UBIFS file-system description object
- * @key: node key to lookup
- * @node: the node is returned here
+ * @lnum: LEB number
+ * @gc_seq1: garbage collection sequence number
  *
- * This function look up and reads node with key @key. The caller has to make
- * sure the @node buffer is large enough to fit the node. Returns zero in case
- * of success, %-ENOENT if the node was not found, and a negative error code in
- * case of failure.
+ * This function determines if @lnum may have been garbage collected since
+ * sequence number @gc_seq1. If it may have been then %1 is returned, otherwise
+ * %0 is returned.
  */
-int ubifs_tnc_lookup(struct ubifs_info *c, const union ubifs_key *key,
-                    void *node)
+static int maybe_leb_gced(struct ubifs_info *c, int lnum, int gc_seq1)
 {
-       int found, n, err;
-       struct ubifs_znode *znode;
-       struct ubifs_zbranch zbr, *zt;
+       int gc_seq2, gced_lnum;
 
-       mutex_lock(&c->tnc_mutex);
-       found = ubifs_lookup_level0(c, key, &znode, &n);
-       if (!found) {
-               err = -ENOENT;
-               goto out;
-       } else if (found < 0) {
-               err = found;
-               goto out;
-       }
-       zt = &znode->zbranch[n];
-       if (is_hash_key(c, key)) {
-               /*
-                * In this case the leaf node cache gets used, so we pass the
-                * address of the zbranch and keep the mutex locked
-                */
-               err = tnc_read_node_nm(c, zt, node);
-               goto out;
-       }
-       zbr = znode->zbranch[n];
-       mutex_unlock(&c->tnc_mutex);
-
-       err = ubifs_tnc_read_node(c, &zbr, node);
-       return err;
-
-out:
-       mutex_unlock(&c->tnc_mutex);
-       return err;
+       gced_lnum = c->gced_lnum;
+       smp_rmb();
+       gc_seq2 = c->gc_seq;
+       /* Same seq means no GC */
+       if (gc_seq1 == gc_seq2)
+               return 0;
+       /* Different by more than 1 means we don't know */
+       if (gc_seq1 + 1 != gc_seq2)
+               return 1;
+       /*
+        * We have seen the sequence number has increased by 1. Now we need to
+        * be sure we read the right LEB number, so read it again.
+        */
+       smp_rmb();
+       if (gced_lnum != c->gced_lnum)
+               return 1;
+       /* Finally we can check lnum */
+       if (gced_lnum == lnum)
+               return 1;
+       return 0;
 }
 
 /**
@@ -1436,16 +1425,19 @@ out:
  * @lnum: LEB number is returned here
  * @offs: offset is returned here
  *
- * This function is the same as 'ubifs_tnc_lookup()' but it returns the node
- * location also. See 'ubifs_tnc_lookup()'.
+ * This function look up and reads node with key @key. The caller has to make
+ * sure the @node buffer is large enough to fit the node. Returns zero in case
+ * of success, %-ENOENT if the node was not found, and a negative error code in
+ * case of failure. The node location can be returned in @lnum and @offs.
  */
 int ubifs_tnc_locate(struct ubifs_info *c, const union ubifs_key *key,
                     void *node, int *lnum, int *offs)
 {
-       int found, n, err;
+       int found, n, err, safely = 0, gc_seq1;
        struct ubifs_znode *znode;
        struct ubifs_zbranch zbr, *zt;
 
+again:
        mutex_lock(&c->tnc_mutex);
        found = ubifs_lookup_level0(c, key, &znode, &n);
        if (!found) {
@@ -1456,24 +1448,43 @@ int ubifs_tnc_locate(struct ubifs_info *c, const union ubifs_key *key,
                goto out;
        }
        zt = &znode->zbranch[n];
+       if (lnum) {
+               *lnum = zt->lnum;
+               *offs = zt->offs;
+       }
        if (is_hash_key(c, key)) {
                /*
                 * In this case the leaf node cache gets used, so we pass the
                 * address of the zbranch and keep the mutex locked
                 */
-               *lnum = zt->lnum;
-               *offs = zt->offs;
                err = tnc_read_node_nm(c, zt, node);
                goto out;
        }
+       if (safely) {
+               err = ubifs_tnc_read_node(c, zt, node);
+               goto out;
+       }
+       /* Drop the TNC mutex prematurely and race with garbage collection */
        zbr = znode->zbranch[n];
+       gc_seq1 = c->gc_seq;
        mutex_unlock(&c->tnc_mutex);
 
-       *lnum = zbr.lnum;
-       *offs = zbr.offs;
+       if (ubifs_get_wbuf(c, zbr.lnum)) {
+               /* We do not GC journal heads */
+               err = ubifs_tnc_read_node(c, &zbr, node);
+               return err;
+       }
 
-       err = ubifs_tnc_read_node(c, &zbr, node);
-       return err;
+       err = fallible_read_node(c, key, &zbr, node);
+       if (maybe_leb_gced(c, zbr.lnum, gc_seq1)) {
+               /*
+                * The node may have been GC'ed out from under us so try again
+                * while keeping the TNC mutex locked.
+                */
+               safely = 1;
+               goto again;
+       }
+       return 0;
 
 out:
        mutex_unlock(&c->tnc_mutex);
@@ -1498,7 +1509,6 @@ static int do_lookup_nm(struct ubifs_info *c, const union ubifs_key *key,
 {
        int found, n, err;
        struct ubifs_znode *znode;
-       struct ubifs_zbranch zbr;
 
        dbg_tnc("name '%.*s' key %s", nm->len, nm->name, DBGKEY(key));
        mutex_lock(&c->tnc_mutex);
@@ -1522,11 +1532,7 @@ static int do_lookup_nm(struct ubifs_info *c, const union ubifs_key *key,
                goto out_unlock;
        }
 
-       zbr = znode->zbranch[n];
-       mutex_unlock(&c->tnc_mutex);
-
-       err = tnc_read_node_nm(c, &zbr, node);
-       return err;
+       err = tnc_read_node_nm(c, &znode->zbranch[n], node);
 
 out_unlock:
        mutex_unlock(&c->tnc_mutex);
index bd2121f3426eb5cacee42602dca1dcacb0150acd..a9ecbd9af20dbeb9a0ddefccd21f8b7393ba1d0a 100644 (file)
@@ -87,7 +87,7 @@
 #define UBIFS_SK_LEN 8
 
 /* Minimum index tree fanout */
-#define UBIFS_MIN_FANOUT 2
+#define UBIFS_MIN_FANOUT 3
 
 /* Maximum number of levels in UBIFS indexing B-tree */
 #define UBIFS_MAX_LEVELS 512
index d7f706f7a3024ab18200c382e790202273adc1e4..17c620b93eec324ced7165b4b2de16482e1b8fda 100644 (file)
@@ -995,6 +995,9 @@ struct ubifs_mount_opts {
  * @max_idx_node_sz: maximum indexing node aligned on 8-bytes boundary
  * @max_inode_sz: maximum possible inode size in bytes
  * @max_znode_sz: size of znode in bytes
+ *
+ * @leb_overhead: how many bytes are wasted in an LEB when it is filled with
+ *                data nodes of maximum size - used in free space reporting
  * @dead_wm: LEB dead space watermark
  * @dark_wm: LEB dark space watermark
  * @block_cnt: count of 4KiB blocks on the FS
@@ -1028,6 +1031,8 @@ struct ubifs_mount_opts {
  * @sbuf: a buffer of LEB size used by GC and replay for scanning
  * @idx_gc: list of index LEBs that have been garbage collected
  * @idx_gc_cnt: number of elements on the idx_gc list
+ * @gc_seq: incremented for every non-index LEB garbage collected
+ * @gced_lnum: last non-index LEB that was garbage collected
  *
  * @infos_list: links all 'ubifs_info' objects
  * @umount_mutex: serializes shrinker and un-mount
@@ -1224,6 +1229,8 @@ struct ubifs_info {
        int max_idx_node_sz;
        long long max_inode_sz;
        int max_znode_sz;
+
+       int leb_overhead;
        int dead_wm;
        int dark_wm;
        int block_cnt;
@@ -1257,6 +1264,8 @@ struct ubifs_info {
        void *sbuf;
        struct list_head idx_gc;
        int idx_gc_cnt;
+       volatile int gc_seq;
+       volatile int gced_lnum;
 
        struct list_head infos_list;
        struct mutex umount_mutex;
@@ -1434,9 +1443,10 @@ void ubifs_release_ino_dirty(struct ubifs_info *c, struct inode *inode,
                                struct ubifs_budget_req *req);
 void ubifs_cancel_ino_op(struct ubifs_info *c, struct inode *inode,
                         struct ubifs_budget_req *req);
-long long ubifs_budg_get_free_space(struct ubifs_info *c);
+long long ubifs_get_free_space(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, uint64_t free);
 long long ubifs_calc_available(const struct ubifs_info *c, int min_idx_lebs);
 
 /* find.c */
@@ -1451,8 +1461,6 @@ int ubifs_save_dirty_idx_lnums(struct ubifs_info *c);
 /* tnc.c */
 int ubifs_lookup_level0(struct ubifs_info *c, const union ubifs_key *key,
                        struct ubifs_znode **zn, int *n);
-int ubifs_tnc_lookup(struct ubifs_info *c, const union ubifs_key *key,
-                    void *node);
 int ubifs_tnc_lookup_nm(struct ubifs_info *c, const union ubifs_key *key,
                        void *node, const struct qstr *nm);
 int ubifs_tnc_locate(struct ubifs_info *c, const union ubifs_key *key,
index 8feeae1f2369b64cdf1be263880200503c5c3a41..79a7ff925bf8ea24f0d2fa83a02115113d772a34 100644 (file)
@@ -14,4 +14,10 @@ extern char __kprobes_text_start[], __kprobes_text_end[];
 extern char __initdata_begin[], __initdata_end[];
 extern char __start_rodata[], __end_rodata[];
 
+/* function descriptor handling (if any).  Override
+ * in asm/sections.h */
+#ifndef dereference_function_descriptor
+#define dereference_function_descriptor(p) (p)
+#endif
+
 #endif /* _ASM_GENERIC_SECTIONS_H_ */
index d5c0f2fda51bb0fc8cace8174d2865a3e0a27c98..03b1d69b142fcf4650b1dc16cb0fb1683fe94b88 100644 (file)
@@ -63,6 +63,7 @@ static inline void flush_icache_page(struct vm_area_struct *vma,
 }
 
 extern void (*flush_icache_range)(unsigned long start, unsigned long end);
+extern void (*local_flush_icache_range)(unsigned long start, unsigned long end);
 
 extern void (*__flush_cache_vmap)(void);
 
index fdd43ec42ec56fb5e4ca7552458f81dc35066e53..9d13c3507ad612f95fcc77085cc26e3a2d31192f 100644 (file)
@@ -4,4 +4,9 @@
 /* nothing to see, move along */
 #include <asm-generic/sections.h>
 
+#ifdef CONFIG_64BIT
+#undef dereference_function_descriptor
+void *dereference_function_descriptor(void *);
+#endif
+
 #endif
index 762f6a6bc707cedfcabc15db59a2977a54decab2..9489283a4bcfbc6bbb4f9e8fd5c25dbb8ed547f8 100644 (file)
 #define X86_FEATURE_UP         (3*32+ 9) /* smp kernel running on up */
 #define X86_FEATURE_FXSAVE_LEAK (3*32+10) /* FXSAVE leaks FOP/FIP/FOP */
 #define X86_FEATURE_ARCH_PERFMON (3*32+11) /* Intel Architectural PerfMon */
-#define X86_FEATURE_PEBS       (3*32+12)  /* Precise-Event Based Sampling */
-#define X86_FEATURE_BTS                (3*32+13)  /* Branch Trace Store */
-#define X86_FEATURE_SYSCALL32  (3*32+14)  /* syscall in ia32 userspace */
-#define X86_FEATURE_SYSENTER32 (3*32+15)  /* sysenter in ia32 userspace */
+#define X86_FEATURE_PEBS       (3*32+12) /* Precise-Event Based Sampling */
+#define X86_FEATURE_BTS                (3*32+13) /* Branch Trace Store */
+#define X86_FEATURE_SYSCALL32  (3*32+14) /* syscall in ia32 userspace */
+#define X86_FEATURE_SYSENTER32 (3*32+15) /* sysenter in ia32 userspace */
 #define X86_FEATURE_REP_GOOD   (3*32+16) /* rep microcode works well on this CPU */
 #define X86_FEATURE_MFENCE_RDTSC (3*32+17) /* Mfence synchronizes RDTSC */
 #define X86_FEATURE_LFENCE_RDTSC (3*32+18) /* Lfence synchronizes RDTSC */
-#define X86_FEATURE_11AP       (3*32+19)  /* Bad local APIC aka 11AP */
+#define X86_FEATURE_11AP       (3*32+19) /* Bad local APIC aka 11AP */
+#define X86_FEATURE_NOPL       (3*32+20) /* The NOPL (0F 1F) instructions */
 
 /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
 #define X86_FEATURE_XMM3       (4*32+ 0) /* Streaming SIMD Extensions-3 */
index adec887dd7cd5f07c1148f8c233e033e05160e40..5c2ff4bc2980b0c21d4973f52c123ab1cca45e7f 100644 (file)
 # define NEED_3DNOW    0
 #endif
 
+#if defined(CONFIG_X86_P6_NOP) || defined(CONFIG_X86_64)
+# define NEED_NOPL     (1<<(X86_FEATURE_NOPL & 31))
+#else
+# define NEED_NOPL     0
+#endif
+
 #ifdef CONFIG_X86_64
 #define NEED_PSE       0
 #define NEED_MSR       (1<<(X86_FEATURE_MSR & 31))
@@ -67,7 +73,7 @@
 #define REQUIRED_MASK1 (NEED_LM|NEED_3DNOW)
 
 #define REQUIRED_MASK2 0
-#define REQUIRED_MASK3 0
+#define REQUIRED_MASK3 (NEED_NOPL)
 #define REQUIRED_MASK4 0
 #define REQUIRED_MASK5 0
 #define REQUIRED_MASK6 0
index c33b0dc28e4db5de75df8a2419c128d22c8e29d9..ed3a5d473e52b2282c0d09c2c25d406400dc7522 100644 (file)
@@ -127,6 +127,8 @@ extern int clockevents_register_notifier(struct notifier_block *nb);
 extern int clockevents_program_event(struct clock_event_device *dev,
                                     ktime_t expires, ktime_t now);
 
+extern void clockevents_handle_noop(struct clock_event_device *dev);
+
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
 extern void clockevents_notify(unsigned long reason, void *arg);
 #else
index e8f450c499b0ac42302fe6c0cf91ecb4115973f2..2691926fb50641305219b74db1a96f94a143c4f7 100644 (file)
@@ -160,7 +160,7 @@ static inline int current_cpuset_is_being_rebound(void)
 
 static inline void rebuild_sched_domains(void)
 {
-       partition_sched_domains(0, NULL, NULL);
+       partition_sched_domains(1, NULL, NULL);
 }
 
 #endif /* !CONFIG_CPUSETS */
index cbf751094688cfb024d7931c4ca755a70a33ab42..46a43b721dd6a104ed3252f211d9dfaa2b3d36e9 100644 (file)
@@ -325,7 +325,8 @@ int hci_conn_del(struct hci_conn *conn);
 void hci_conn_hash_flush(struct hci_dev *hdev);
 void hci_conn_check_pending(struct hci_dev *hdev);
 
-struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *src);
+struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 auth_type);
+int hci_conn_check_link_mode(struct hci_conn *conn);
 int hci_conn_auth(struct hci_conn *conn);
 int hci_conn_encrypt(struct hci_conn *conn);
 int hci_conn_change_link_key(struct hci_conn *conn);
index 95c660c9719ba957c3a57f9957e75528d98083ae..91324908fccd367953bcce47aeb537afbd242f2e 100644 (file)
@@ -208,6 +208,9 @@ extern void inet_twsk_schedule(struct inet_timewait_sock *tw,
 extern void inet_twsk_deschedule(struct inet_timewait_sock *tw,
                                 struct inet_timewait_death_row *twdr);
 
+extern void inet_twsk_purge(struct net *net, struct inet_hashinfo *hashinfo,
+                           struct inet_timewait_death_row *twdr, int family);
+
 static inline
 struct net *twsk_net(const struct inet_timewait_sock *twsk)
 {
index d5ab79cf516d7edf77f8e45afe15c04cdae2cda4..f227bc1726906a52a803907299230f62b39edd84 100644 (file)
@@ -14,6 +14,8 @@
  *  2003-10-22 Updates by Stephen Hemminger.
  *  2004 May-July Rework by Paul Jackson.
  *  2006 Rework by Paul Menage to use generic cgroups
+ *  2008 Rework of the scheduler domains and CPU hotplug handling
+ *       by Max Krasnyansky
  *
  *  This file is subject to the terms and conditions of the GNU General Public
  *  License.  See the file COPYING in the main directory of the Linux
@@ -236,9 +238,11 @@ static struct cpuset top_cpuset = {
 
 static DEFINE_MUTEX(callback_mutex);
 
-/* This is ugly, but preserves the userspace API for existing cpuset
+/*
+ * This is ugly, but preserves the userspace API for existing cpuset
  * users. If someone tries to mount the "cpuset" filesystem, we
- * silently switch it to mount "cgroup" instead */
+ * silently switch it to mount "cgroup" instead
+ */
 static int cpuset_get_sb(struct file_system_type *fs_type,
                         int flags, const char *unused_dev_name,
                         void *data, struct vfsmount *mnt)
@@ -473,10 +477,9 @@ static int validate_change(const struct cpuset *cur, const struct cpuset *trial)
 }
 
 /*
- * Helper routine for rebuild_sched_domains().
+ * Helper routine for generate_sched_domains().
  * Do cpusets a, b have overlapping cpus_allowed masks?
  */
-
 static int cpusets_overlap(struct cpuset *a, struct cpuset *b)
 {
        return cpus_intersects(a->cpus_allowed, b->cpus_allowed);
@@ -518,26 +521,15 @@ update_domain_attr_tree(struct sched_domain_attr *dattr, struct cpuset *c)
 }
 
 /*
- * rebuild_sched_domains()
- *
- * This routine will be called to rebuild the scheduler's dynamic
- * sched domains:
- * - if the flag 'sched_load_balance' of any cpuset with non-empty
- *   'cpus' changes,
- * - or if the 'cpus' allowed changes in any cpuset which has that
- *   flag enabled,
- * - or if the 'sched_relax_domain_level' of any cpuset which has
- *   that flag enabled and with non-empty 'cpus' changes,
- * - or if any cpuset with non-empty 'cpus' is removed,
- * - or if a cpu gets offlined.
- *
- * This routine builds a partial partition of the systems CPUs
- * (the set of non-overlappping cpumask_t's in the array 'part'
- * below), and passes that partial partition to the kernel/sched.c
- * partition_sched_domains() routine, which will rebuild the
- * schedulers load balancing domains (sched domains) as specified
- * by that partial partition.  A 'partial partition' is a set of
- * non-overlapping subsets whose union is a subset of that set.
+ * generate_sched_domains()
+ *
+ * This function builds a partial partition of the systems CPUs
+ * A 'partial partition' is a set of non-overlapping subsets whose
+ * union is a subset of that set.
+ * The output of this function needs to be passed to kernel/sched.c
+ * partition_sched_domains() routine, which will rebuild the scheduler's
+ * load balancing domains (sched domains) as specified by that partial
+ * partition.
  *
  * See "What is sched_load_balance" in Documentation/cpusets.txt
  * for a background explanation of this.
@@ -547,13 +539,7 @@ update_domain_attr_tree(struct sched_domain_attr *dattr, struct cpuset *c)
  * domains when operating in the severe memory shortage situations
  * that could cause allocation failures below.
  *
- * Call with cgroup_mutex held.  May take callback_mutex during
- * call due to the kfifo_alloc() and kmalloc() calls.  May nest
- * a call to the get_online_cpus()/put_online_cpus() pair.
- * Must not be called holding callback_mutex, because we must not
- * call get_online_cpus() while holding callback_mutex.  Elsewhere
- * the kernel nests callback_mutex inside get_online_cpus() calls.
- * So the reverse nesting would risk an ABBA deadlock.
+ * Must be called with cgroup_lock held.
  *
  * The three key local variables below are:
  *    q  - a linked-list queue of cpuset pointers, used to implement a
@@ -588,10 +574,10 @@ update_domain_attr_tree(struct sched_domain_attr *dattr, struct cpuset *c)
  *     element of the partition (one sched domain) to be passed to
  *     partition_sched_domains().
  */
-
-void rebuild_sched_domains(void)
+static int generate_sched_domains(cpumask_t **domains,
+                       struct sched_domain_attr **attributes)
 {
-       LIST_HEAD(q);           /* queue of cpusets to be scanned*/
+       LIST_HEAD(q);           /* queue of cpusets to be scanned */
        struct cpuset *cp;      /* scans q */
        struct cpuset **csa;    /* array of all cpuset ptrs */
        int csn;                /* how many cpuset ptrs in csa so far */
@@ -601,23 +587,26 @@ void rebuild_sched_domains(void)
        int ndoms;              /* number of sched domains in result */
        int nslot;              /* next empty doms[] cpumask_t slot */
 
-       csa = NULL;
+       ndoms = 0;
        doms = NULL;
        dattr = NULL;
+       csa = NULL;
 
        /* Special case for the 99% of systems with one, full, sched domain */
        if (is_sched_load_balance(&top_cpuset)) {
-               ndoms = 1;
                doms = kmalloc(sizeof(cpumask_t), GFP_KERNEL);
                if (!doms)
-                       goto rebuild;
+                       goto done;
+
                dattr = kmalloc(sizeof(struct sched_domain_attr), GFP_KERNEL);
                if (dattr) {
                        *dattr = SD_ATTR_INIT;
                        update_domain_attr_tree(dattr, &top_cpuset);
                }
                *doms = top_cpuset.cpus_allowed;
-               goto rebuild;
+
+               ndoms = 1;
+               goto done;
        }
 
        csa = kmalloc(number_of_cpusets * sizeof(cp), GFP_KERNEL);
@@ -680,61 +669,141 @@ restart:
                }
        }
 
-       /* Convert <csn, csa> to <ndoms, doms> */
+       /*
+        * Now we know how many domains to create.
+        * Convert <csn, csa> to <ndoms, doms> and populate cpu masks.
+        */
        doms = kmalloc(ndoms * sizeof(cpumask_t), GFP_KERNEL);
-       if (!doms)
-               goto rebuild;
+       if (!doms) {
+               ndoms = 0;
+               goto done;
+       }
+
+       /*
+        * The rest of the code, including the scheduler, can deal with
+        * dattr==NULL case. No need to abort if alloc fails.
+        */
        dattr = kmalloc(ndoms * sizeof(struct sched_domain_attr), GFP_KERNEL);
 
        for (nslot = 0, i = 0; i < csn; i++) {
                struct cpuset *a = csa[i];
+               cpumask_t *dp;
                int apn = a->pn;
 
-               if (apn >= 0) {
-                       cpumask_t *dp = doms + nslot;
-
-                       if (nslot == ndoms) {
-                               static int warnings = 10;
-                               if (warnings) {
-                                       printk(KERN_WARNING
-                                        "rebuild_sched_domains confused:"
-                                         " nslot %d, ndoms %d, csn %d, i %d,"
-                                         " apn %d\n",
-                                         nslot, ndoms, csn, i, apn);
-                                       warnings--;
-                               }
-                               continue;
+               if (apn < 0) {
+                       /* Skip completed partitions */
+                       continue;
+               }
+
+               dp = doms + nslot;
+
+               if (nslot == ndoms) {
+                       static int warnings = 10;
+                       if (warnings) {
+                               printk(KERN_WARNING
+                                "rebuild_sched_domains confused:"
+                                 " nslot %d, ndoms %d, csn %d, i %d,"
+                                 " apn %d\n",
+                                 nslot, ndoms, csn, i, apn);
+                               warnings--;
                        }
+                       continue;
+               }
 
-                       cpus_clear(*dp);
-                       if (dattr)
-                               *(dattr + nslot) = SD_ATTR_INIT;
-                       for (j = i; j < csn; j++) {
-                               struct cpuset *b = csa[j];
-
-                               if (apn == b->pn) {
-                                       cpus_or(*dp, *dp, b->cpus_allowed);
-                                       b->pn = -1;
-                                       if (dattr)
-                                               update_domain_attr_tree(dattr
-                                                                  + nslot, b);
-                               }
+               cpus_clear(*dp);
+               if (dattr)
+                       *(dattr + nslot) = SD_ATTR_INIT;
+               for (j = i; j < csn; j++) {
+                       struct cpuset *b = csa[j];
+
+                       if (apn == b->pn) {
+                               cpus_or(*dp, *dp, b->cpus_allowed);
+                               if (dattr)
+                                       update_domain_attr_tree(dattr + nslot, b);
+
+                               /* Done with this partition */
+                               b->pn = -1;
                        }
-                       nslot++;
                }
+               nslot++;
        }
        BUG_ON(nslot != ndoms);
 
-rebuild:
-       /* Have scheduler rebuild sched domains */
+done:
+       kfree(csa);
+
+       *domains    = doms;
+       *attributes = dattr;
+       return ndoms;
+}
+
+/*
+ * Rebuild scheduler domains.
+ *
+ * Call with neither cgroup_mutex held nor within get_online_cpus().
+ * Takes both cgroup_mutex and get_online_cpus().
+ *
+ * Cannot be directly called from cpuset code handling changes
+ * to the cpuset pseudo-filesystem, because it cannot be called
+ * from code that already holds cgroup_mutex.
+ */
+static void do_rebuild_sched_domains(struct work_struct *unused)
+{
+       struct sched_domain_attr *attr;
+       cpumask_t *doms;
+       int ndoms;
+
        get_online_cpus();
-       partition_sched_domains(ndoms, doms, dattr);
+
+       /* Generate domain masks and attrs */
+       cgroup_lock();
+       ndoms = generate_sched_domains(&doms, &attr);
+       cgroup_unlock();
+
+       /* Have scheduler rebuild the domains */
+       partition_sched_domains(ndoms, doms, attr);
+
        put_online_cpus();
+}
 
-done:
-       kfree(csa);
-       /* Don't kfree(doms) -- partition_sched_domains() does that. */
-       /* Don't kfree(dattr) -- partition_sched_domains() does that. */
+static DECLARE_WORK(rebuild_sched_domains_work, do_rebuild_sched_domains);
+
+/*
+ * Rebuild scheduler domains, asynchronously via workqueue.
+ *
+ * If the flag 'sched_load_balance' of any cpuset with non-empty
+ * 'cpus' changes, or if the 'cpus' allowed changes in any cpuset
+ * which has that flag enabled, or if any cpuset with a non-empty
+ * 'cpus' is removed, then call this routine to rebuild the
+ * scheduler's dynamic sched domains.
+ *
+ * The rebuild_sched_domains() and partition_sched_domains()
+ * routines must nest cgroup_lock() inside get_online_cpus(),
+ * but such cpuset changes as these must nest that locking the
+ * other way, holding cgroup_lock() for much of the code.
+ *
+ * So in order to avoid an ABBA deadlock, the cpuset code handling
+ * these user changes delegates the actual sched domain rebuilding
+ * to a separate workqueue thread, which ends up processing the
+ * above do_rebuild_sched_domains() function.
+ */
+static void async_rebuild_sched_domains(void)
+{
+       schedule_work(&rebuild_sched_domains_work);
+}
+
+/*
+ * Accomplishes the same scheduler domain rebuild as the above
+ * async_rebuild_sched_domains(), however it directly calls the
+ * rebuild routine synchronously rather than calling it via an
+ * asynchronous work thread.
+ *
+ * This can only be called from code that is not holding
+ * cgroup_mutex (not nested in a cgroup_lock() call.)
+ */
+void rebuild_sched_domains(void)
+{
+       do_rebuild_sched_domains(NULL);
 }
 
 /**
@@ -863,7 +932,7 @@ static int update_cpumask(struct cpuset *cs, const char *buf)
                return retval;
 
        if (is_load_balanced)
-               rebuild_sched_domains();
+               async_rebuild_sched_domains();
        return 0;
 }
 
@@ -1090,7 +1159,7 @@ static int update_relax_domain_level(struct cpuset *cs, s64 val)
        if (val != cs->relax_domain_level) {
                cs->relax_domain_level = val;
                if (!cpus_empty(cs->cpus_allowed) && is_sched_load_balance(cs))
-                       rebuild_sched_domains();
+                       async_rebuild_sched_domains();
        }
 
        return 0;
@@ -1131,7 +1200,7 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs,
        mutex_unlock(&callback_mutex);
 
        if (cpus_nonempty && balance_flag_changed)
-               rebuild_sched_domains();
+               async_rebuild_sched_domains();
 
        return 0;
 }
@@ -1492,6 +1561,9 @@ static u64 cpuset_read_u64(struct cgroup *cont, struct cftype *cft)
        default:
                BUG();
        }
+
+       /* Unreachable but makes gcc happy */
+       return 0;
 }
 
 static s64 cpuset_read_s64(struct cgroup *cont, struct cftype *cft)
@@ -1504,6 +1576,9 @@ static s64 cpuset_read_s64(struct cgroup *cont, struct cftype *cft)
        default:
                BUG();
        }
+
+       /* Unrechable but makes gcc happy */
+       return 0;
 }
 
 
@@ -1692,15 +1767,9 @@ static struct cgroup_subsys_state *cpuset_create(
 }
 
 /*
- * Locking note on the strange update_flag() call below:
- *
  * If the cpuset being removed has its flag 'sched_load_balance'
  * enabled, then simulate turning sched_load_balance off, which
- * will call rebuild_sched_domains().  The get_online_cpus()
- * call in rebuild_sched_domains() must not be made while holding
- * callback_mutex.  Elsewhere the kernel nests callback_mutex inside
- * get_online_cpus() calls.  So the reverse nesting would risk an
- * ABBA deadlock.
+ * will call async_rebuild_sched_domains().
  */
 
 static void cpuset_destroy(struct cgroup_subsys *ss, struct cgroup *cont)
@@ -1719,7 +1788,7 @@ static void cpuset_destroy(struct cgroup_subsys *ss, struct cgroup *cont)
 struct cgroup_subsys cpuset_subsys = {
        .name = "cpuset",
        .create = cpuset_create,
-       .destroy  = cpuset_destroy,
+       .destroy = cpuset_destroy,
        .can_attach = cpuset_can_attach,
        .attach = cpuset_attach,
        .populate = cpuset_populate,
@@ -1811,7 +1880,7 @@ static void move_member_tasks_to_cpuset(struct cpuset *from, struct cpuset *to)
 }
 
 /*
- * If common_cpu_mem_hotplug_unplug(), below, unplugs any CPUs
+ * If CPU and/or memory hotplug handlers, below, unplug any CPUs
  * or memory nodes, we need to walk over the cpuset hierarchy,
  * removing that CPU or node from all cpusets.  If this removes the
  * last CPU or node from a cpuset, then move the tasks in the empty
@@ -1902,35 +1971,6 @@ static void scan_for_empty_cpusets(const struct cpuset *root)
        }
 }
 
-/*
- * The cpus_allowed and mems_allowed nodemasks in the top_cpuset track
- * cpu_online_map and node_states[N_HIGH_MEMORY].  Force the top cpuset to
- * track what's online after any CPU or memory node hotplug or unplug event.
- *
- * Since there are two callers of this routine, one for CPU hotplug
- * events and one for memory node hotplug events, we could have coded
- * two separate routines here.  We code it as a single common routine
- * in order to minimize text size.
- */
-
-static void common_cpu_mem_hotplug_unplug(int rebuild_sd)
-{
-       cgroup_lock();
-
-       top_cpuset.cpus_allowed = cpu_online_map;
-       top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY];
-       scan_for_empty_cpusets(&top_cpuset);
-
-       /*
-        * Scheduler destroys domains on hotplug events.
-        * Rebuild them based on the current settings.
-        */
-       if (rebuild_sd)
-               rebuild_sched_domains();
-
-       cgroup_unlock();
-}
-
 /*
  * The top_cpuset tracks what CPUs and Memory Nodes are online,
  * period.  This is necessary in order to make cpusets transparent
@@ -1939,40 +1979,52 @@ static void common_cpu_mem_hotplug_unplug(int rebuild_sd)
  *
  * This routine ensures that top_cpuset.cpus_allowed tracks
  * cpu_online_map on each CPU hotplug (cpuhp) event.
+ *
+ * Called within get_online_cpus().  Needs to call cgroup_lock()
+ * before calling generate_sched_domains().
  */
-
-static int cpuset_handle_cpuhp(struct notifier_block *unused_nb,
+static int cpuset_track_online_cpus(struct notifier_block *unused_nb,
                                unsigned long phase, void *unused_cpu)
 {
+       struct sched_domain_attr *attr;
+       cpumask_t *doms;
+       int ndoms;
+
        switch (phase) {
-       case CPU_UP_CANCELED:
-       case CPU_UP_CANCELED_FROZEN:
-       case CPU_DOWN_FAILED:
-       case CPU_DOWN_FAILED_FROZEN:
        case CPU_ONLINE:
        case CPU_ONLINE_FROZEN:
        case CPU_DEAD:
        case CPU_DEAD_FROZEN:
-               common_cpu_mem_hotplug_unplug(1);
                break;
+
        default:
                return NOTIFY_DONE;
        }
 
+       cgroup_lock();
+       top_cpuset.cpus_allowed = cpu_online_map;
+       scan_for_empty_cpusets(&top_cpuset);
+       ndoms = generate_sched_domains(&doms, &attr);
+       cgroup_unlock();
+
+       /* Have scheduler rebuild the domains */
+       partition_sched_domains(ndoms, doms, attr);
+
        return NOTIFY_OK;
 }
 
 #ifdef CONFIG_MEMORY_HOTPLUG
 /*
  * Keep top_cpuset.mems_allowed tracking node_states[N_HIGH_MEMORY].
- * Call this routine anytime after you change
- * node_states[N_HIGH_MEMORY].
- * See also the previous routine cpuset_handle_cpuhp().
+ * Call this routine anytime after node_states[N_HIGH_MEMORY] changes.
+ * See also the previous routine cpuset_track_online_cpus().
  */
-
 void cpuset_track_online_nodes(void)
 {
-       common_cpu_mem_hotplug_unplug(0);
+       cgroup_lock();
+       top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY];
+       scan_for_empty_cpusets(&top_cpuset);
+       cgroup_unlock();
 }
 #endif
 
@@ -1987,7 +2039,7 @@ void __init cpuset_init_smp(void)
        top_cpuset.cpus_allowed = cpu_online_map;
        top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY];
 
-       hotcpu_notifier(cpuset_handle_cpuhp, 0);
+       hotcpu_notifier(cpuset_track_online_cpus, 0);
 }
 
 /**
index 8626ae50ce0826229ee272af55c97622cfb2927e..0d8905a1b8ca9fab76ae92e2b1b952b990d83b02 100644 (file)
@@ -7746,24 +7746,27 @@ static int dattrs_equal(struct sched_domain_attr *cur, int idx_cur,
  * and partition_sched_domains() will fallback to the single partition
  * 'fallback_doms', it also forces the domains to be rebuilt.
  *
+ * If doms_new==NULL it will be replaced with cpu_online_map.
+ * ndoms_new==0 is a special case for destroying existing domains.
+ * It will not create the default domain.
+ *
  * Call with hotplug lock held
  */
 void partition_sched_domains(int ndoms_new, cpumask_t *doms_new,
                             struct sched_domain_attr *dattr_new)
 {
-       int i, j;
+       int i, j, n;
 
        mutex_lock(&sched_domains_mutex);
 
        /* always unregister in case we don't destroy any domains */
        unregister_sched_domain_sysctl();
 
-       if (doms_new == NULL)
-               ndoms_new = 0;
+       n = doms_new ? ndoms_new : 0;
 
        /* Destroy deleted domains */
        for (i = 0; i < ndoms_cur; i++) {
-               for (j = 0; j < ndoms_new; j++) {
+               for (j = 0; j < n; j++) {
                        if (cpus_equal(doms_cur[i], doms_new[j])
                            && dattrs_equal(dattr_cur, i, dattr_new, j))
                                goto match1;
@@ -7776,7 +7779,6 @@ match1:
 
        if (doms_new == NULL) {
                ndoms_cur = 0;
-               ndoms_new = 1;
                doms_new = &fallback_doms;
                cpus_andnot(doms_new[0], cpu_online_map, cpu_isolated_map);
                dattr_new = NULL;
@@ -7813,8 +7815,13 @@ match2:
 int arch_reinit_sched_domains(void)
 {
        get_online_cpus();
+
+       /* Destroy domains first to force the rebuild */
+       partition_sched_domains(0, NULL, NULL);
+
        rebuild_sched_domains();
        put_online_cpus();
+
        return 0;
 }
 
@@ -7898,7 +7905,7 @@ static int update_sched_domains(struct notifier_block *nfb,
        case CPU_ONLINE_FROZEN:
        case CPU_DEAD:
        case CPU_DEAD_FROZEN:
-               partition_sched_domains(0, NULL, NULL);
+               partition_sched_domains(1, NULL, NULL);
                return NOTIFY_OK;
 
        default:
index 3d1e3e1a19716e94cdad4116b1ca73242ac45f1e..1876b526c7783db17d4dd5050a899e640670ef59 100644 (file)
@@ -177,7 +177,7 @@ void clockevents_register_device(struct clock_event_device *dev)
 /*
  * Noop handler when we shut down an event device
  */
-static void clockevents_handle_noop(struct clock_event_device *dev)
+void clockevents_handle_noop(struct clock_event_device *dev)
 {
 }
 
@@ -199,7 +199,6 @@ void clockevents_exchange_device(struct clock_event_device *old,
         * released list and do a notify add later.
         */
        if (old) {
-               old->event_handler = clockevents_handle_noop;
                clockevents_set_mode(old, CLOCK_EVT_MODE_UNUSED);
                list_del(&old->list);
                list_add(&old->list, &clockevents_released);
index 5125ddd8196ba3cffb2fd683c2fd3abdac0a695b..1ad46f3df6e76cd8994403b1c1ca72c14ec3553b 100644 (file)
@@ -245,7 +245,7 @@ static void sync_cmos_clock(unsigned long dummy)
        if (abs(now.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec / 2)
                fail = update_persistent_clock(now);
 
-       next.tv_nsec = (NSEC_PER_SEC / 2) - now.tv_nsec;
+       next.tv_nsec = (NSEC_PER_SEC / 2) - now.tv_nsec - (TICK_NSEC / 2);
        if (next.tv_nsec <= 0)
                next.tv_nsec += NSEC_PER_SEC;
 
index 31463d370b944ff37919d184a125e7efc1bf563a..2f5a38294bf9ffc8639a5e623760c5242e96629b 100644 (file)
@@ -175,6 +175,8 @@ static void tick_do_periodic_broadcast(void)
  */
 static void tick_handle_periodic_broadcast(struct clock_event_device *dev)
 {
+       ktime_t next;
+
        tick_do_periodic_broadcast();
 
        /*
@@ -185,10 +187,13 @@ static void tick_handle_periodic_broadcast(struct clock_event_device *dev)
 
        /*
         * Setup the next period for devices, which do not have
-        * periodic mode:
+        * periodic mode. We read dev->next_event first and add to it
+        * when the event alrady expired. clockevents_program_event()
+        * sets dev->next_event only when the event is really
+        * programmed to the device.
         */
-       for (;;) {
-               ktime_t next = ktime_add(dev->next_event, tick_period);
+       for (next = dev->next_event; ;) {
+               next = ktime_add(next, tick_period);
 
                if (!clockevents_program_event(dev, next, ktime_get()))
                        return;
@@ -205,7 +210,7 @@ static void tick_do_broadcast_on_off(void *why)
        struct clock_event_device *bc, *dev;
        struct tick_device *td;
        unsigned long flags, *reason = why;
-       int cpu;
+       int cpu, bc_stopped;
 
        spin_lock_irqsave(&tick_broadcast_lock, flags);
 
@@ -223,6 +228,8 @@ static void tick_do_broadcast_on_off(void *why)
        if (!tick_device_is_functional(dev))
                goto out;
 
+       bc_stopped = cpus_empty(tick_broadcast_mask);
+
        switch (*reason) {
        case CLOCK_EVT_NOTIFY_BROADCAST_ON:
        case CLOCK_EVT_NOTIFY_BROADCAST_FORCE:
@@ -245,9 +252,10 @@ static void tick_do_broadcast_on_off(void *why)
                break;
        }
 
-       if (cpus_empty(tick_broadcast_mask))
-               clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN);
-       else {
+       if (cpus_empty(tick_broadcast_mask)) {
+               if (!bc_stopped)
+                       clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN);
+       } else if (bc_stopped) {
                if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC)
                        tick_broadcast_start_periodic(bc);
                else
@@ -364,16 +372,8 @@ cpumask_t *tick_get_broadcast_oneshot_mask(void)
 static int tick_broadcast_set_event(ktime_t expires, int force)
 {
        struct clock_event_device *bc = tick_broadcast_device.evtdev;
-       ktime_t now = ktime_get();
-       int res;
-
-       for(;;) {
-               res = clockevents_program_event(bc, expires, now);
-               if (!res || !force)
-                       return res;
-               now = ktime_get();
-               expires = ktime_add(now, ktime_set(0, bc->min_delta_ns));
-       }
+
+       return tick_dev_program_event(bc, expires, force);
 }
 
 int tick_resume_broadcast_oneshot(struct clock_event_device *bc)
@@ -491,14 +491,52 @@ static void tick_broadcast_clear_oneshot(int cpu)
        cpu_clear(cpu, tick_broadcast_oneshot_mask);
 }
 
+static void tick_broadcast_init_next_event(cpumask_t *mask, ktime_t expires)
+{
+       struct tick_device *td;
+       int cpu;
+
+       for_each_cpu_mask_nr(cpu, *mask) {
+               td = &per_cpu(tick_cpu_device, cpu);
+               if (td->evtdev)
+                       td->evtdev->next_event = expires;
+       }
+}
+
 /**
  * tick_broadcast_setup_oneshot - setup the broadcast device
  */
 void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
 {
-       bc->event_handler = tick_handle_oneshot_broadcast;
-       clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
-       bc->next_event.tv64 = KTIME_MAX;
+       /* Set it up only once ! */
+       if (bc->event_handler != tick_handle_oneshot_broadcast) {
+               int was_periodic = bc->mode == CLOCK_EVT_MODE_PERIODIC;
+               int cpu = smp_processor_id();
+               cpumask_t mask;
+
+               bc->event_handler = tick_handle_oneshot_broadcast;
+               clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
+
+               /* Take the do_timer update */
+               tick_do_timer_cpu = cpu;
+
+               /*
+                * We must be careful here. There might be other CPUs
+                * waiting for periodic broadcast. We need to set the
+                * oneshot_mask bits for those and program the
+                * broadcast device to fire.
+                */
+               mask = tick_broadcast_mask;
+               cpu_clear(cpu, mask);
+               cpus_or(tick_broadcast_oneshot_mask,
+                       tick_broadcast_oneshot_mask, mask);
+
+               if (was_periodic && !cpus_empty(mask)) {
+                       tick_broadcast_init_next_event(&mask, tick_next_period);
+                       tick_broadcast_set_event(tick_next_period, 1);
+               } else
+                       bc->next_event.tv64 = KTIME_MAX;
+       }
 }
 
 /*
index 80c4336f4188409a077d3f4ae4dde727f856de55..c4777193d56734d0276aa210ddbbad2e79c416c8 100644 (file)
@@ -161,6 +161,7 @@ static void tick_setup_device(struct tick_device *td,
        } else {
                handler = td->evtdev->event_handler;
                next_event = td->evtdev->next_event;
+               td->evtdev->event_handler = clockevents_handle_noop;
        }
 
        td->evtdev = newdev;
index f13f2b7f4fd46bda983d7138edce267b1a9e0c91..0ffc2918ea6fb8365523ad0a63266cd68628b65f 100644 (file)
@@ -17,6 +17,8 @@ extern void tick_handle_periodic(struct clock_event_device *dev);
 extern void tick_setup_oneshot(struct clock_event_device *newdev,
                               void (*handler)(struct clock_event_device *),
                               ktime_t nextevt);
+extern int tick_dev_program_event(struct clock_event_device *dev,
+                                 ktime_t expires, int force);
 extern int tick_program_event(ktime_t expires, int force);
 extern void tick_oneshot_notify(void);
 extern int tick_switch_to_oneshot(void (*handler)(struct clock_event_device *));
index 450c04935b66b050e35671d821c5f190b394414f..2e8de678e767a76d444c822307b7bd34baff67c5 100644 (file)
 #include "tick-internal.h"
 
 /**
- * tick_program_event
+ * tick_program_event internal worker function
  */
-int tick_program_event(ktime_t expires, int force)
+int tick_dev_program_event(struct clock_event_device *dev, ktime_t expires,
+                          int force)
 {
-       struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev;
        ktime_t now = ktime_get();
+       int i;
 
-       while (1) {
+       for (i = 0;;) {
                int ret = clockevents_program_event(dev, expires, now);
 
                if (!ret || !force)
                        return ret;
+
+               /*
+                * We tried 2 times to program the device with the given
+                * min_delta_ns. If that's not working then we double it
+                * and emit a warning.
+                */
+               if (++i > 2) {
+                       /* Increase the min. delta and try again */
+                       if (!dev->min_delta_ns)
+                               dev->min_delta_ns = 5000;
+                       else
+                               dev->min_delta_ns += dev->min_delta_ns >> 1;
+
+                       printk(KERN_WARNING
+                              "CE: %s increasing min_delta_ns to %lu nsec\n",
+                              dev->name ? dev->name : "?",
+                              dev->min_delta_ns << 1);
+
+                       i = 0;
+               }
+
                now = ktime_get();
-               expires = ktime_add(now, ktime_set(0, dev->min_delta_ns));
+               expires = ktime_add_ns(now, dev->min_delta_ns);
        }
 }
 
+/**
+ * tick_program_event
+ */
+int tick_program_event(ktime_t expires, int force)
+{
+       struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev;
+
+       return tick_dev_program_event(dev, expires, force);
+}
+
 /**
  * tick_resume_onshot - resume oneshot mode
  */
@@ -61,7 +93,7 @@ void tick_setup_oneshot(struct clock_event_device *newdev,
 {
        newdev->event_handler = handler;
        clockevents_set_mode(newdev, CLOCK_EVT_MODE_ONESHOT);
-       clockevents_program_event(newdev, next_event, ktime_get());
+       tick_dev_program_event(newdev, next_event, 1);
 }
 
 /**
index d8d1d1142248a511561b401a87b1590a5f94ba33..c399bc1093cbedb276f3e974353534560197e940 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <asm/page.h>          /* for PAGE_SIZE */
 #include <asm/div64.h>
+#include <asm/sections.h>      /* for dereference_function_descriptor() */
 
 /* Works only for digits and letters, but small and fast */
 #define TOLOWER(x) ((x) | 0x20)
@@ -513,16 +514,6 @@ static char *string(char *buf, char *end, char *s, int field_width, int precisio
        return buf;
 }
 
-static inline void *dereference_function_descriptor(void *ptr)
-{
-#if defined(CONFIG_IA64) || defined(CONFIG_PPC64)
-       void *p;
-       if (!probe_kernel_address(ptr, p))
-               ptr = p;
-#endif
-       return ptr;
-}
-
 static char *symbol_string(char *buf, char *end, void *ptr, int field_width, int precision, int flags)
 {
        unsigned long value = (unsigned long) ptr;
index 1edfdf4c095ba085ebe134eb6a3ee00d23128f1d..f6348e078aa434077bf26c57ffb8f0eabf4ecbe3 100644 (file)
@@ -49,7 +49,7 @@
 #define BT_DBG(D...)
 #endif
 
-#define VERSION "2.12"
+#define VERSION "2.13"
 
 /* Bluetooth sockets */
 #define BT_MAX_PROTO   8
index ca8d05245ca0cb9e27586cfdbdeb90e5afff81e3..b7002429f1525311053f14171a1d94a25bf1ff04 100644 (file)
@@ -330,7 +330,7 @@ EXPORT_SYMBOL(hci_get_route);
 
 /* Create SCO or ACL connection.
  * Device _must_ be locked */
-struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst)
+struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 auth_type)
 {
        struct hci_conn *acl;
        struct hci_conn *sco;
@@ -344,8 +344,10 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst)
 
        hci_conn_hold(acl);
 
-       if (acl->state == BT_OPEN || acl->state == BT_CLOSED)
+       if (acl->state == BT_OPEN || acl->state == BT_CLOSED) {
+               acl->auth_type = auth_type;
                hci_acl_connect(acl);
+       }
 
        if (type == ACL_LINK)
                return acl;
@@ -374,6 +376,19 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst)
 }
 EXPORT_SYMBOL(hci_connect);
 
+/* Check link security requirement */
+int hci_conn_check_link_mode(struct hci_conn *conn)
+{
+       BT_DBG("conn %p", conn);
+
+       if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0 &&
+                                       !(conn->link_mode & HCI_LM_ENCRYPT))
+               return 0;
+
+       return 1;
+}
+EXPORT_SYMBOL(hci_conn_check_link_mode);
+
 /* Authenticate remote device */
 int hci_conn_auth(struct hci_conn *conn)
 {
@@ -381,7 +396,7 @@ int hci_conn_auth(struct hci_conn *conn)
 
        if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0) {
                if (!(conn->auth_type & 0x01)) {
-                       conn->auth_type = HCI_AT_GENERAL_BONDING_MITM;
+                       conn->auth_type |= 0x01;
                        conn->link_mode &= ~HCI_LM_AUTH;
                }
        }
index 0e3db289f4be2b1f97fca8034f26150b56013b26..ad7a553d77131c469bf4c9ebc3bc8bbfe84d1a33 100644 (file)
@@ -1605,14 +1605,11 @@ static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_b
 
                if (conn->state == BT_CONFIG) {
                        if (!ev->status && hdev->ssp_mode > 0 &&
-                                                       conn->ssp_mode > 0) {
-                               if (conn->out) {
-                                       struct hci_cp_auth_requested cp;
-                                       cp.handle = ev->handle;
-                                       hci_send_cmd(hdev,
-                                               HCI_OP_AUTH_REQUESTED,
+                                       conn->ssp_mode > 0 && conn->out) {
+                               struct hci_cp_auth_requested cp;
+                               cp.handle = ev->handle;
+                               hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED,
                                                        sizeof(cp), &cp);
-                               }
                        } else {
                                conn->state = BT_CONNECTED;
                                hci_proto_connect_cfm(conn, ev->status);
index 3396d5bdef1c3f8e0f24af0a64dd7b1eca7a333f..9610a9c85b9896e69cd6c62712cb5f8376a33040 100644 (file)
@@ -55,7 +55,7 @@
 #define BT_DBG(D...)
 #endif
 
-#define VERSION "2.10"
+#define VERSION "2.11"
 
 static u32 l2cap_feat_mask = 0x0000;
 
@@ -778,6 +778,7 @@ static int l2cap_do_connect(struct sock *sk)
        struct l2cap_conn *conn;
        struct hci_conn *hcon;
        struct hci_dev *hdev;
+       __u8 auth_type;
        int err = 0;
 
        BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst), l2cap_pi(sk)->psm);
@@ -789,7 +790,21 @@ static int l2cap_do_connect(struct sock *sk)
 
        err = -ENOMEM;
 
-       hcon = hci_connect(hdev, ACL_LINK, dst);
+       if (l2cap_pi(sk)->link_mode & L2CAP_LM_AUTH ||
+                       l2cap_pi(sk)->link_mode & L2CAP_LM_ENCRYPT ||
+                               l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE) {
+               if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001))
+                       auth_type = HCI_AT_NO_BONDING_MITM;
+               else
+                       auth_type = HCI_AT_GENERAL_BONDING_MITM;
+       } else {
+               if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001))
+                       auth_type = HCI_AT_NO_BONDING;
+               else
+                       auth_type = HCI_AT_GENERAL_BONDING;
+       }
+
+       hcon = hci_connect(hdev, ACL_LINK, dst, auth_type);
        if (!hcon)
                goto done;
 
@@ -1553,10 +1568,10 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
        struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
        struct l2cap_conn_rsp rsp;
        struct sock *sk, *parent;
-       int result, status = 0;
+       int result, status = L2CAP_CS_NO_INFO;
 
        u16 dcid = 0, scid = __le16_to_cpu(req->scid);
-       __le16 psm  = req->psm;
+       __le16 psm = req->psm;
 
        BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
 
@@ -1567,6 +1582,13 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
                goto sendresp;
        }
 
+       /* Check if the ACL is secure enough (if not SDP) */
+       if (psm != cpu_to_le16(0x0001) &&
+                               !hci_conn_check_link_mode(conn->hcon)) {
+               result = L2CAP_CR_SEC_BLOCK;
+               goto response;
+       }
+
        result = L2CAP_CR_NO_MEM;
 
        /* Check for backlog size */
@@ -2224,7 +2246,7 @@ static int l2cap_auth_cfm(struct hci_conn *hcon, u8 status)
                        rsp.scid   = cpu_to_le16(l2cap_pi(sk)->dcid);
                        rsp.dcid   = cpu_to_le16(l2cap_pi(sk)->scid);
                        rsp.result = cpu_to_le16(result);
-                       rsp.status = cpu_to_le16(0);
+                       rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
                        l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
                                        L2CAP_CONN_RSP, sizeof(rsp), &rsp);
                }
@@ -2296,7 +2318,7 @@ static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
                        rsp.scid   = cpu_to_le16(l2cap_pi(sk)->dcid);
                        rsp.dcid   = cpu_to_le16(l2cap_pi(sk)->scid);
                        rsp.result = cpu_to_le16(result);
-                       rsp.status = cpu_to_le16(0);
+                       rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
                        l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
                                        L2CAP_CONN_RSP, sizeof(rsp), &rsp);
                }
index a16011fedc1d73d3adc24e66ff5e7ff24a37373c..0cc91e6da76d7f9d16983985f176ab1d7319eaab 100644 (file)
@@ -200,7 +200,7 @@ static int sco_connect(struct sock *sk)
        else
                type = SCO_LINK;
 
-       hcon = hci_connect(hdev, type, dst);
+       hcon = hci_connect(hdev, type, dst, HCI_AT_NO_BONDING);
        if (!hcon)
                goto done;
 
index eeee218eed80a9357e2abf5d409e74fcf9423ae6..5bbf07362172fb13733df97ae3d76238e0c7b0a5 100644 (file)
@@ -188,15 +188,21 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                return 0;
 
        case BRCTL_SET_BRIDGE_HELLO_TIME:
+       {
+               unsigned long t = clock_t_to_jiffies(args[1]);
                if (!capable(CAP_NET_ADMIN))
                        return -EPERM;
 
+               if (t < HZ)
+                       return -EINVAL;
+
                spin_lock_bh(&br->lock);
-               br->bridge_hello_time = clock_t_to_jiffies(args[1]);
+               br->bridge_hello_time = t;
                if (br_is_root_bridge(br))
                        br->hello_time = br->bridge_hello_time;
                spin_unlock_bh(&br->lock);
                return 0;
+       }
 
        case BRCTL_SET_BRIDGE_MAX_AGE:
                if (!capable(CAP_NET_ADMIN))
index 27d6a511c8c124534320be3971c1bdc98d1d4c5d..158dee8b4965307c045d6fec2d5a930070a4cd68 100644 (file)
  */
 static ssize_t store_bridge_parm(struct device *d,
                                 const char *buf, size_t len,
-                                void (*set)(struct net_bridge *, unsigned long))
+                                int (*set)(struct net_bridge *, unsigned long))
 {
        struct net_bridge *br = to_bridge(d);
        char *endp;
        unsigned long val;
+       int err;
 
        if (!capable(CAP_NET_ADMIN))
                return -EPERM;
@@ -43,9 +44,9 @@ static ssize_t store_bridge_parm(struct device *d,
                return -EINVAL;
 
        spin_lock_bh(&br->lock);
-       (*set)(br, val);
+       err = (*set)(br, val);
        spin_unlock_bh(&br->lock);
-       return len;
+       return err ? err : len;
 }
 
 
@@ -56,12 +57,13 @@ static ssize_t show_forward_delay(struct device *d,
        return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->forward_delay));
 }
 
-static void set_forward_delay(struct net_bridge *br, unsigned long val)
+static int set_forward_delay(struct net_bridge *br, unsigned long val)
 {
        unsigned long delay = clock_t_to_jiffies(val);
        br->forward_delay = delay;
        if (br_is_root_bridge(br))
                br->bridge_forward_delay = delay;
+       return 0;
 }
 
 static ssize_t store_forward_delay(struct device *d,
@@ -80,12 +82,17 @@ static ssize_t show_hello_time(struct device *d, struct device_attribute *attr,
                       jiffies_to_clock_t(to_bridge(d)->hello_time));
 }
 
-static void set_hello_time(struct net_bridge *br, unsigned long val)
+static int set_hello_time(struct net_bridge *br, unsigned long val)
 {
        unsigned long t = clock_t_to_jiffies(val);
+
+       if (t < HZ)
+               return -EINVAL;
+
        br->hello_time = t;
        if (br_is_root_bridge(br))
                br->bridge_hello_time = t;
+       return 0;
 }
 
 static ssize_t store_hello_time(struct device *d,
@@ -104,12 +111,13 @@ static ssize_t show_max_age(struct device *d, struct device_attribute *attr,
                       jiffies_to_clock_t(to_bridge(d)->max_age));
 }
 
-static void set_max_age(struct net_bridge *br, unsigned long val)
+static int set_max_age(struct net_bridge *br, unsigned long val)
 {
        unsigned long t = clock_t_to_jiffies(val);
        br->max_age = t;
        if (br_is_root_bridge(br))
                br->bridge_max_age = t;
+       return 0;
 }
 
 static ssize_t store_max_age(struct device *d, struct device_attribute *attr,
@@ -126,9 +134,10 @@ static ssize_t show_ageing_time(struct device *d,
        return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->ageing_time));
 }
 
-static void set_ageing_time(struct net_bridge *br, unsigned long val)
+static int set_ageing_time(struct net_bridge *br, unsigned long val)
 {
        br->ageing_time = clock_t_to_jiffies(val);
+       return 0;
 }
 
 static ssize_t store_ageing_time(struct device *d,
@@ -180,9 +189,10 @@ static ssize_t show_priority(struct device *d, struct device_attribute *attr,
                       (br->bridge_id.prio[0] << 8) | br->bridge_id.prio[1]);
 }
 
-static void set_priority(struct net_bridge *br, unsigned long val)
+static int set_priority(struct net_bridge *br, unsigned long val)
 {
        br_stp_set_bridge_priority(br, (u16) val);
+       return 0;
 }
 
 static ssize_t store_priority(struct device *d, struct device_attribute *attr,
index 60c51f7658870257571ee9455f95bb48888b4398..e719ed29310ff5695c347db907a6311aa79e36c5 100644 (file)
@@ -1991,8 +1991,13 @@ static void net_tx_action(struct softirq_action *h)
                                spin_unlock(root_lock);
                        } else {
                                if (!test_bit(__QDISC_STATE_DEACTIVATED,
-                                             &q->state))
+                                             &q->state)) {
                                        __netif_reschedule(q);
+                               } else {
+                                       smp_mb__before_clear_bit();
+                                       clear_bit(__QDISC_STATE_SCHED,
+                                                 &q->state);
+                               }
                        }
                }
        }
index d985bd613d25d3895f3b7d32fee5f571062d52be..743f011b9a84189bd9284721e4a1ac2a704e68b8 100644 (file)
@@ -409,3 +409,38 @@ out:
 }
 
 EXPORT_SYMBOL_GPL(inet_twdr_twcal_tick);
+
+void inet_twsk_purge(struct net *net, struct inet_hashinfo *hashinfo,
+                    struct inet_timewait_death_row *twdr, int family)
+{
+       struct inet_timewait_sock *tw;
+       struct sock *sk;
+       struct hlist_node *node;
+       int h;
+
+       local_bh_disable();
+       for (h = 0; h < (hashinfo->ehash_size); h++) {
+               struct inet_ehash_bucket *head =
+                       inet_ehash_bucket(hashinfo, h);
+               rwlock_t *lock = inet_ehash_lockp(hashinfo, h);
+restart:
+               write_lock(lock);
+               sk_for_each(sk, node, &head->twchain) {
+
+                       tw = inet_twsk(sk);
+                       if (!net_eq(twsk_net(tw), net) ||
+                           tw->tw_family != family)
+                               continue;
+
+                       atomic_inc(&tw->tw_refcnt);
+                       write_unlock(lock);
+                       inet_twsk_deschedule(tw, twdr);
+                       inet_twsk_put(tw);
+
+                       goto restart;
+               }
+               write_unlock(lock);
+       }
+       local_bh_enable();
+}
+EXPORT_SYMBOL_GPL(inet_twsk_purge);
index 44c1e934824bfc024169250bbd5a47de532a91c3..1b4fee20fc932a54ad11f113c1f51786fb4b85f4 100644 (file)
@@ -2376,6 +2376,7 @@ static int __net_init tcp_sk_init(struct net *net)
 static void __net_exit tcp_sk_exit(struct net *net)
 {
        inet_ctl_sock_destroy(net->ipv4.tcp_sock);
+       inet_twsk_purge(net, &tcp_hashinfo, &tcp_death_row, AF_INET);
 }
 
 static struct pernet_operations __net_initdata tcp_sk_ops = {
index 0e844c2736a77b0dad9aa87095298be92d01bf7c..3df2c442d90bc7adef4ea3b2809639bf5955bce4 100644 (file)
@@ -943,39 +943,39 @@ static int ip6_dst_lookup_tail(struct sock *sk,
        }
 
 #ifdef CONFIG_IPV6_OPTIMISTIC_DAD
-               /*
-                * Here if the dst entry we've looked up
-                * has a neighbour entry that is in the INCOMPLETE
-                * state and the src address from the flow is
-                * marked as OPTIMISTIC, we release the found
-                * dst entry and replace it instead with the
-                * dst entry of the nexthop router
-                */
-               if (!((*dst)->neighbour->nud_state & NUD_VALID)) {
-                       struct inet6_ifaddr *ifp;
-                       struct flowi fl_gw;
-                       int redirect;
-
-                       ifp = ipv6_get_ifaddr(net, &fl->fl6_src,
-                                             (*dst)->dev, 1);
-
-                       redirect = (ifp && ifp->flags & IFA_F_OPTIMISTIC);
-                       if (ifp)
-                               in6_ifa_put(ifp);
-
-                       if (redirect) {
-                               /*
-                                * We need to get the dst entry for the
-                                * default router instead
-                                */
-                               dst_release(*dst);
-                               memcpy(&fl_gw, fl, sizeof(struct flowi));
-                               memset(&fl_gw.fl6_dst, 0, sizeof(struct in6_addr));
-                               *dst = ip6_route_output(net, sk, &fl_gw);
-                               if ((err = (*dst)->error))
-                                       goto out_err_release;
-                       }
+       /*
+        * Here if the dst entry we've looked up
+        * has a neighbour entry that is in the INCOMPLETE
+        * state and the src address from the flow is
+        * marked as OPTIMISTIC, we release the found
+        * dst entry and replace it instead with the
+        * dst entry of the nexthop router
+        */
+       if ((*dst)->neighbour && !((*dst)->neighbour->nud_state & NUD_VALID)) {
+               struct inet6_ifaddr *ifp;
+               struct flowi fl_gw;
+               int redirect;
+
+               ifp = ipv6_get_ifaddr(net, &fl->fl6_src,
+                                     (*dst)->dev, 1);
+
+               redirect = (ifp && ifp->flags & IFA_F_OPTIMISTIC);
+               if (ifp)
+                       in6_ifa_put(ifp);
+
+               if (redirect) {
+                       /*
+                        * We need to get the dst entry for the
+                        * default router instead
+                        */
+                       dst_release(*dst);
+                       memcpy(&fl_gw, fl, sizeof(struct flowi));
+                       memset(&fl_gw.fl6_dst, 0, sizeof(struct in6_addr));
+                       *dst = ip6_route_output(net, sk, &fl_gw);
+                       if ((err = (*dst)->error))
+                               goto out_err_release;
                }
+       }
 #endif
 
        return 0;
index 5b90b369ccb2577d41e7ac4ab1f4993147e6108f..b585c850a89a3737b1b6a19aab62dd7dd1cee5cb 100644 (file)
@@ -2148,6 +2148,7 @@ static int tcpv6_net_init(struct net *net)
 static void tcpv6_net_exit(struct net *net)
 {
        inet_ctl_sock_destroy(net->ipv6.tcp_sk);
+       inet_twsk_purge(net, &tcp_hashinfo, &tcp_death_row, AF_INET6);
 }
 
 static struct pernet_operations tcpv6_net_ops = {
index 1b1226d6653f7815970483cdba636c5f22a3934e..20633fdf7e6bb48b48e485b9ba0d110ab1f8459b 100644 (file)
@@ -68,11 +68,21 @@ static const char *const dccprotos[] = {
 static int parse_dcc(char *data, const char *data_end, u_int32_t *ip,
                     u_int16_t *port, char **ad_beg_p, char **ad_end_p)
 {
+       char *tmp;
+
        /* at least 12: "AAAAAAAA P\1\n" */
        while (*data++ != ' ')
                if (data > data_end - 12)
                        return -1;
 
+       /* Make sure we have a newline character within the packet boundaries
+        * because simple_strtoul parses until the first invalid character. */
+       for (tmp = data; tmp <= data_end; tmp++)
+               if (*tmp == '\n')
+                       break;
+       if (tmp > data_end || *tmp != '\n')
+               return -1;
+
        *ad_beg_p = data;
        *ip = simple_strtoul(data, &data, 10);
 
index 654a4f7f12c6f7f74c1412ad432c95661336fcdb..9bd03967fea4b4c66654e5ad1c8f32779a8bc9c2 100644 (file)
@@ -45,12 +45,12 @@ static LIST_HEAD(gre_keymap_list);
 
 void nf_ct_gre_keymap_flush(void)
 {
-       struct list_head *pos, *n;
+       struct nf_ct_gre_keymap *km, *tmp;
 
        write_lock_bh(&nf_ct_gre_lock);
-       list_for_each_safe(pos, n, &gre_keymap_list) {
-               list_del(pos);
-               kfree(pos);
+       list_for_each_entry_safe(km, tmp, &gre_keymap_list, list) {
+               list_del(&km->list);
+               kfree(km);
        }
        write_unlock_bh(&nf_ct_gre_lock);
 }
@@ -97,10 +97,14 @@ int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir,
        kmp = &help->help.ct_pptp_info.keymap[dir];
        if (*kmp) {
                /* check whether it's a retransmission */
+               read_lock_bh(&nf_ct_gre_lock);
                list_for_each_entry(km, &gre_keymap_list, list) {
-                       if (gre_key_cmpfn(km, t) && km == *kmp)
+                       if (gre_key_cmpfn(km, t) && km == *kmp) {
+                               read_unlock_bh(&nf_ct_gre_lock);
                                return 0;
+                       }
                }
+               read_unlock_bh(&nf_ct_gre_lock);
                pr_debug("trying to override keymap_%s for ct %p\n",
                         dir == IP_CT_DIR_REPLY ? "reply" : "orig", ct);
                return -EEXIST;
index 2f9bbc058b487bede799f9cf2e69e7554aa0a63d..1fa306be60fbf47eda01b59ebad301798c364002 100644 (file)
@@ -1193,7 +1193,6 @@ static const struct sip_handler sip_handlers[] = {
 static int process_sip_response(struct sk_buff *skb,
                                const char **dptr, unsigned int *datalen)
 {
-       static const struct sip_handler *handler;
        enum ip_conntrack_info ctinfo;
        struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
        unsigned int matchoff, matchlen;
@@ -1214,6 +1213,8 @@ static int process_sip_response(struct sk_buff *skb,
        dataoff = matchoff + matchlen + 1;
 
        for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) {
+               const struct sip_handler *handler;
+
                handler = &sip_handlers[i];
                if (handler->response == NULL)
                        continue;
@@ -1228,13 +1229,14 @@ static int process_sip_response(struct sk_buff *skb,
 static int process_sip_request(struct sk_buff *skb,
                               const char **dptr, unsigned int *datalen)
 {
-       static const struct sip_handler *handler;
        enum ip_conntrack_info ctinfo;
        struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
        unsigned int matchoff, matchlen;
        unsigned int cseq, i;
 
        for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) {
+               const struct sip_handler *handler;
+
                handler = &sip_handlers[i];
                if (handler->request == NULL)
                        continue;
index 46914b79d850abcba3a4d26b1e28d0b187f33309..b7754b1b73a459fee91885c36d74d1d38b3fc9da 100644 (file)
@@ -1077,6 +1077,7 @@ static void __xfrm_policy_link(struct xfrm_policy *pol, int dir)
        struct hlist_head *chain = policy_hash_bysel(&pol->selector,
                                                     pol->family, dir);
 
+       list_add_tail(&pol->bytype, &xfrm_policy_bytype[pol->type]);
        hlist_add_head(&pol->bydst, chain);
        hlist_add_head(&pol->byidx, xfrm_policy_byidx+idx_hash(pol->index));
        xfrm_policy_count[dir]++;
index 7bd62f61593f576cd7675c1aa79e58bdbcaa558c..0a8f09c3144c835fccbc1e3de4855b654c45a3b9 100644 (file)
@@ -858,6 +858,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
 
                if (km_query(x, tmpl, pol) == 0) {
                        x->km.state = XFRM_STATE_ACQ;
+                       list_add_tail(&x->all, &xfrm_state_all);
                        hlist_add_head(&x->bydst, xfrm_state_bydst+h);
                        h = xfrm_src_hash(daddr, saddr, family);
                        hlist_add_head(&x->bysrc, xfrm_state_bysrc+h);
@@ -1055,6 +1056,7 @@ static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 re
                xfrm_state_hold(x);
                x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ;
                add_timer(&x->timer);
+               list_add_tail(&x->all, &xfrm_state_all);
                hlist_add_head(&x->bydst, xfrm_state_bydst+h);
                h = xfrm_src_hash(daddr, saddr, family);
                hlist_add_head(&x->bysrc, xfrm_state_bysrc+h);
index a37bee094eba4482c612612ae42366002e3b1134..8ebf512ced6caacee8f0f0a8aafa80772e530889 100644 (file)
@@ -91,6 +91,9 @@ endif # SOUND_PRIME
 
 endif # !M68K
 
+endif # SOUND
+
+# AC97_BUS is used from both sound and ucb1400
 config AC97_BUS
        tristate
        help
@@ -99,4 +102,3 @@ config AC97_BUS
          sound although they're sharing the AC97 bus. Concerned drivers
          should "select" this.
 
-endif # SOUND