Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
Linus Torvalds [Wed, 30 Jun 2010 22:45:28 +0000 (15:45 -0700)]
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (22 commits)
  USB: gadget: f_mass_storage: stale common->fsg value bug fix
  USB: gadget: f_mass_storage: fixed fs descriptors not being updated
  USB: musb: Enable the maximum supported burst mode for DMA
  USB: musb: fix Blackfin ulpi stubs
  USB: MUSB: make non-OMAP platforms build with CONFIG_PM=y
  USB: musb_core: make disconnect and suspend interrupts work again
  USB: obey the sysfs power/wakeup setting
  USB: gadget eth: Fix calculate CRC32 in EEM
  USB: qcserial: fix a memory leak in qcprobe error path
  USB: gadget/printer, fix sleep inside atomic
  USB: isp1362-hcd, fix double lock
  USB: serial: ftdi: correct merge conflict with CONTEC id
  USB: fix oops in usb_sg_init()
  USB: s3c2410: deactivate endpoints before gadget unbinding
  USB: ehci-mxc: bail out on transceiver problems
  USB: otg/ulpi: bail out on read errors
  usb: musb: Fix a bug by making suspend interrupt available in device mode
  USB: r8a66597: Fix failure in change of status
  USB: xHCI: Fix bug in link TRB activation change.
  USB: gadget: g_fs: possible invalid pointer reference bug fixed
  ...

82 files changed:
MAINTAINERS
arch/arm/mach-omap2/board-omap3stalker.c
arch/arm/mach-omap2/clock44xx_data.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/pm34xx.c
arch/arm/mach-omap2/usb-ehci.c
arch/arm/mach-vexpress/ct-ca9x4.c
arch/arm/plat-omap/dmtimer.c
arch/arm/plat-omap/gpio.c
arch/arm/plat-omap/iovmm.c
arch/um/include/asm/arch_hweight.h [new file with mode: 0644]
arch/um/os-Linux/mem.c
arch/x86/boot/video-vga.c
arch/x86/include/asm/io_apic.h
arch/x86/include/asm/percpu.h
arch/x86/include/asm/pgtable_32_types.h
arch/x86/include/asm/system.h
arch/x86/kernel/acpi/boot.c
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/cpu/perf_event_intel.c
arch/x86/kernel/mpparse.c
arch/x86/kernel/pci-calgary_64.c
arch/x86/kernel/reboot.c
arch/x86/kernel/sfi.c
arch/x86/mm/pat.c
arch/x86/mm/pat_rbtree.c
block/blk-core.c
block/cfq-iosched.c
block/cfq.h [new file with mode: 0644]
drivers/acpi/apei/apei-base.c
drivers/acpi/atomicio.c
drivers/block/cciss_scsi.c
drivers/block/cpqarray.c
drivers/block/drbd/drbd_main.c
drivers/block/drbd/drbd_nl.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/rtc/rtc-davinci.c
drivers/rtc/rtc-ds1307.c
drivers/serial/cpm_uart/cpm_uart_core.c
drivers/staging/tm6000/tm6000-alsa.c
drivers/staging/tm6000/tm6000-cards.c
drivers/staging/tm6000/tm6000-core.c
drivers/staging/tm6000/tm6000-dvb.c
drivers/video/geode/gxfb_core.c
drivers/video/geode/lxfb_core.c
drivers/video/nuc900fb.c
fs/binfmt_flat.c
fs/dcache.c
fs/fcntl.c
fs/fs-writeback.c
fs/ocfs2/reservations.c
fs/proc/task_nommu.c
fs/super.c
fs/sysv/ialloc.c
fs/ubifs/budget.c
include/linux/backing-dev.h
include/linux/cgroup.h
include/linux/compiler-gcc.h
include/linux/compiler-gcc4.h
include/linux/drbd.h
include/linux/list.h
include/linux/tracepoint.h
kernel/futex.c
kernel/irq/manage.c
kernel/kexec.c
kernel/sched.c
kernel/sched_fair.c
kernel/time/tick-sched.c
kernel/trace/trace_event_perf.c
lib/genalloc.c
lib/idr.c
mm/memcontrol.c
mm/mempolicy.c
mm/page-writeback.c
tools/perf/builtin-record.c
tools/perf/util/event.c
tools/perf/util/newt.c
tools/perf/util/session.c
tools/perf/util/session.h
tools/perf/util/thread.h

index 6c73b3b..7642365 100644 (file)
@@ -896,11 +896,13 @@ S:        Maintained
 
 ARM/SAMSUNG ARM ARCHITECTURES
 M:     Ben Dooks <ben-linux@fluff.org>
+M:     Kukjin Kim <kgene.kim@samsung.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 W:     http://www.fluff.org/ben/linux/
 S:     Maintained
-F:     arch/arm/plat-s3c/
+F:     arch/arm/plat-samsung/
 F:     arch/arm/plat-s3c24xx/
+F:     arch/arm/plat-s5p/
 
 ARM/S3C2410 ARM ARCHITECTURE
 M:     Ben Dooks <ben-linux@fluff.org>
@@ -1148,7 +1150,7 @@ F:        drivers/mmc/host/atmel-mci.c
 F:     drivers/mmc/host/atmel-mci-regs.h
 
 ATMEL AT91 / AT32 SERIAL DRIVER
-M:     Haavard Skinnemoen <hskinnemoen@atmel.com>
+M:     Nicolas Ferre <nicolas.ferre@atmel.com>
 S:     Supported
 F:     drivers/serial/atmel_serial.c
 
@@ -1160,18 +1162,18 @@ F:      drivers/video/atmel_lcdfb.c
 F:     include/video/atmel_lcdc.h
 
 ATMEL MACB ETHERNET DRIVER
-M:     Haavard Skinnemoen <hskinnemoen@atmel.com>
+M:     Nicolas Ferre <nicolas.ferre@atmel.com>
 S:     Supported
 F:     drivers/net/macb.*
 
 ATMEL SPI DRIVER
-M:     Haavard Skinnemoen <hskinnemoen@atmel.com>
+M:     Nicolas Ferre <nicolas.ferre@atmel.com>
 S:     Supported
 F:     drivers/spi/atmel_spi.*
 
 ATMEL USBA UDC DRIVER
-M:     Haavard Skinnemoen <hskinnemoen@atmel.com>
-L:     kernel@avr32linux.org
+M:     Nicolas Ferre <nicolas.ferre@atmel.com>
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 W:     http://avr32linux.org/twiki/bin/view/Main/AtmelUsbDeviceDriver
 S:     Supported
 F:     drivers/usb/gadget/atmel_usba_udc.*
@@ -3380,7 +3382,7 @@ KPROBES
 M:     Ananth N Mavinakayanahalli <ananth@in.ibm.com>
 M:     Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
 M:     "David S. Miller" <davem@davemloft.net>
-M:     Masami Hiramatsu <mhiramat@redhat.com>
+M:     Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
 S:     Maintained
 F:     Documentation/kprobes.txt
 F:     include/linux/kprobes.h
@@ -4628,6 +4630,12 @@ M:       Robert Jarzmik <robert.jarzmik@free.fr>
 L:     rtc-linux@googlegroups.com
 S:     Maintained
 
+QLOGIC QLA1280 SCSI DRIVER
+M:     Michael Reed <mdr@sgi.com>
+L:     linux-scsi@vger.kernel.org
+S:     Maintained
+F:     drivers/scsi/qla1280.[ch]
+
 QLOGIC QLA2XXX FC-SCSI DRIVER
 M:     Andrew Vasquez <andrew.vasquez@qlogic.com>
 M:     linux-driver@qlogic.com
index f848ba8..a04cffd 100644 (file)
@@ -538,9 +538,7 @@ static void ads7846_dev_init(void)
                printk(KERN_ERR "can't get ads7846 pen down GPIO\n");
 
        gpio_direction_input(OMAP3_STALKER_TS_GPIO);
-
-       omap_set_gpio_debounce(OMAP3_STALKER_TS_GPIO, 1);
-       omap_set_gpio_debounce_time(OMAP3_STALKER_TS_GPIO, 0xa);
+       gpio_set_debounce(OMAP3_STALKER_TS_GPIO, 310);
 }
 
 static int ads7846_get_pendown_state(void)
index 0280422..e10db7a 100644 (file)
@@ -1369,6 +1369,7 @@ static struct clk emif1_ick = {
        .ops            = &clkops_omap2_dflt,
        .enable_reg     = OMAP4430_CM_MEMIF_EMIF_1_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
+       .flags          = ENABLE_ON_INIT,
        .clkdm_name     = "l3_emif_clkdm",
        .parent         = &ddrphy_ck,
        .recalc         = &followparent_recalc,
@@ -1379,6 +1380,7 @@ static struct clk emif2_ick = {
        .ops            = &clkops_omap2_dflt,
        .enable_reg     = OMAP4430_CM_MEMIF_EMIF_2_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
+       .flags          = ENABLE_ON_INIT,
        .clkdm_name     = "l3_emif_clkdm",
        .parent         = &ddrphy_ck,
        .recalc         = &followparent_recalc,
index 95c9a5f..b7a4133 100644 (file)
@@ -409,10 +409,11 @@ static int _init_main_clk(struct omap_hwmod *oh)
                return 0;
 
        oh->_clk = omap_clk_get_by_name(oh->main_clk);
-       if (!oh->_clk)
+       if (!oh->_clk) {
                pr_warning("omap_hwmod: %s: cannot clk_get main_clk %s\n",
                           oh->name, oh->main_clk);
                return -EINVAL;
+       }
 
        if (!oh->_clk->clkdm)
                pr_warning("omap_hwmod: %s: missing clockdomain for %s.\n",
@@ -444,10 +445,11 @@ static int _init_interface_clks(struct omap_hwmod *oh)
                        continue;
 
                c = omap_clk_get_by_name(os->clk);
-               if (!c)
+               if (!c) {
                        pr_warning("omap_hwmod: %s: cannot clk_get interface_clk %s\n",
                                   oh->name, os->clk);
                        ret = -EINVAL;
+               }
                os->_clk = c;
        }
 
@@ -470,10 +472,11 @@ static int _init_opt_clks(struct omap_hwmod *oh)
 
        for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++) {
                c = omap_clk_get_by_name(oc->clk);
-               if (!c)
+               if (!c) {
                        pr_warning("omap_hwmod: %s: cannot clk_get opt_clk %s\n",
                                   oh->name, oc->clk);
                        ret = -EINVAL;
+               }
                oc->_clk = c;
        }
 
index 2e96771..b88737f 100644 (file)
@@ -99,7 +99,7 @@ static void omap3_enable_io_chain(void)
                /* Do a readback to assure write has been done */
                prm_read_mod_reg(WKUP_MOD, PM_WKEN);
 
-               while (!(prm_read_mod_reg(WKUP_MOD, PM_WKST) &
+               while (!(prm_read_mod_reg(WKUP_MOD, PM_WKEN) &
                         OMAP3430_ST_IO_CHAIN_MASK)) {
                        timeout++;
                        if (timeout > 1000) {
@@ -108,7 +108,7 @@ static void omap3_enable_io_chain(void)
                                return;
                        }
                        prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK,
-                                            WKUP_MOD, PM_WKST);
+                                            WKUP_MOD, PM_WKEN);
                }
        }
 }
index c68f799..d72d1ac 100644 (file)
@@ -20,6 +20,8 @@
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
+#include <linux/dma-mapping.h>
+
 #include <asm/io.h>
 #include <plat/mux.h>
 
index e6f7303..9b11eed 100644 (file)
@@ -2,6 +2,7 @@
  * Versatile Express Core Tile Cortex A9x4 Support
  */
 #include <linux/init.h>
+#include <linux/gfp.h>
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
index c64875f..44bafda 100644 (file)
@@ -541,11 +541,11 @@ void omap_dm_timer_stop(struct omap_dm_timer *timer)
                  * timer is stopped
                  */
                udelay(3500000 / clk_get_rate(timer->fclk) + 1);
-               /* Ack possibly pending interrupt */
-               omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG,
-                               OMAP_TIMER_INT_OVERFLOW);
 #endif
        }
+       /* Ack possibly pending interrupt */
+       omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG,
+                       OMAP_TIMER_INT_OVERFLOW);
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
 
index 393e921..9b7e354 100644 (file)
@@ -673,6 +673,7 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
                if (cpu_is_omap34xx() || cpu_is_omap44xx())
                        clk_disable(bank->dbck);
        }
+       bank->dbck_enable_mask = val;
 
        __raw_writel(val, reg);
 }
index e43983b..8ce0de2 100644 (file)
@@ -140,8 +140,10 @@ static struct sg_table *sgtable_alloc(const size_t bytes, u32 flags)
                return ERR_PTR(-ENOMEM);
 
        err = sg_alloc_table(sgt, nr_entries, GFP_KERNEL);
-       if (err)
+       if (err) {
+               kfree(sgt);
                return ERR_PTR(err);
+       }
 
        pr_debug("%s: sgt:%p(%d entries)\n", __func__, sgt, nr_entries);
 
diff --git a/arch/um/include/asm/arch_hweight.h b/arch/um/include/asm/arch_hweight.h
new file mode 100644 (file)
index 0000000..c656cf4
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _ASM_UM_HWEIGHT_H
+#define _ASM_UM_HWEIGHT_H
+
+#include <asm-generic/bitops/arch_hweight.h>
+
+#endif
index 93a11d7..e696144 100644 (file)
@@ -10,6 +10,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <string.h>
+#include <sys/stat.h>
 #include <sys/mman.h>
 #include <sys/param.h>
 #include "init.h"
index ed7aeff..45bc940 100644 (file)
@@ -41,13 +41,12 @@ static __videocard video_vga;
 static u8 vga_set_basic_mode(void)
 {
        struct biosregs ireg, oreg;
-       u16 ax;
        u8 mode;
 
        initregs(&ireg);
 
        /* Query current mode */
-       ax = 0x0f00;
+       ireg.ax = 0x0f00;
        intcall(0x10, &ireg, &oreg);
        mode = oreg.al;
 
index 63cb409..9cb2edb 100644 (file)
@@ -183,7 +183,7 @@ struct mp_ioapic_gsi{
        u32 gsi_end;
 };
 extern struct mp_ioapic_gsi  mp_gsi_routing[];
-extern u32 gsi_end;
+extern u32 gsi_top;
 int mp_find_ioapic(u32 gsi);
 int mp_find_ioapic_pin(int ioapic, u32 gsi);
 void __init mp_register_ioapic(int id, u32 address, u32 gsi_base);
@@ -197,7 +197,7 @@ static const int timer_through_8259 = 0;
 static inline void ioapic_init_mappings(void)  { }
 static inline void ioapic_insert_resources(void) { }
 static inline void probe_nr_irqs_gsi(void)     { }
-#define gsi_end (NR_IRQS_LEGACY - 1)
+#define gsi_top (NR_IRQS_LEGACY)
 static inline int mp_find_ioapic(u32 gsi) { return 0; }
 
 struct io_apic_irq_attr;
index 0797e74..cd28f9a 100644 (file)
@@ -77,6 +77,7 @@ do {                                                  \
        if (0) {                                        \
                pto_T__ pto_tmp__;                      \
                pto_tmp__ = (val);                      \
+               (void)pto_tmp__;                        \
        }                                               \
        switch (sizeof(var)) {                          \
        case 1:                                         \
@@ -115,6 +116,7 @@ do {                                                                        \
        if (0) {                                                        \
                pao_T__ pao_tmp__;                                      \
                pao_tmp__ = (val);                                      \
+               (void)pao_tmp__;                                        \
        }                                                               \
        switch (sizeof(var)) {                                          \
        case 1:                                                         \
index 5e67c15..ed5903b 100644 (file)
@@ -26,7 +26,7 @@
  */
 #define VMALLOC_OFFSET (8 * 1024 * 1024)
 
-#ifndef __ASSEMBLER__
+#ifndef __ASSEMBLY__
 extern bool __vmalloc_start_set; /* set once high_memory is set */
 #endif
 
index b8fe48e..e7f4d33 100644 (file)
@@ -451,7 +451,7 @@ void stop_this_cpu(void *dummy);
  *
  * (Could use an alternative three way for this if there was one.)
  */
-static inline void rdtsc_barrier(void)
+static __always_inline void rdtsc_barrier(void)
 {
        alternative(ASM_NOP3, "mfence", X86_FEATURE_MFENCE_RDTSC);
        alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC);
index 60cc405..c05872a 100644 (file)
@@ -118,7 +118,7 @@ static unsigned int gsi_to_irq(unsigned int gsi)
        if (gsi >= NR_IRQS_LEGACY)
                irq = gsi;
        else
-               irq = gsi_end + 1 + gsi;
+               irq = gsi_top + gsi;
 
        return irq;
 }
@@ -129,10 +129,10 @@ static u32 irq_to_gsi(int irq)
 
        if (irq < NR_IRQS_LEGACY)
                gsi = isa_irq_to_gsi[irq];
-       else if (irq <= gsi_end)
+       else if (irq < gsi_top)
                gsi = irq;
-       else if (irq <= (gsi_end + NR_IRQS_LEGACY))
-               gsi = irq - gsi_end;
+       else if (irq < (gsi_top + NR_IRQS_LEGACY))
+               gsi = irq - gsi_top;
        else
                gsi = 0xffffffff;
 
index 33f3563..e41ed24 100644 (file)
@@ -89,8 +89,8 @@ int nr_ioapics;
 /* IO APIC gsi routing info */
 struct mp_ioapic_gsi  mp_gsi_routing[MAX_IO_APICS];
 
-/* The last gsi number used */
-u32 gsi_end;
+/* The one past the highest gsi number used */
+u32 gsi_top;
 
 /* MP IRQ source entries */
 struct mpc_intsrc mp_irqs[MAX_IRQ_SOURCES];
@@ -1035,7 +1035,7 @@ static int pin_2_irq(int idx, int apic, int pin)
                if (gsi >= NR_IRQS_LEGACY)
                        irq = gsi;
                else
-                       irq = gsi_end + 1 + gsi;
+                       irq = gsi_top + gsi;
        }
 
 #ifdef CONFIG_X86_32
@@ -3853,7 +3853,7 @@ void __init probe_nr_irqs_gsi(void)
 {
        int nr;
 
-       nr = gsi_end + 1 + NR_IRQS_LEGACY;
+       nr = gsi_top + NR_IRQS_LEGACY;
        if (nr > nr_irqs_gsi)
                nr_irqs_gsi = nr;
 
@@ -4294,8 +4294,8 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
         */
        nr_ioapic_registers[idx] = entries;
 
-       if (mp_gsi_routing[idx].gsi_end > gsi_end)
-               gsi_end = mp_gsi_routing[idx].gsi_end;
+       if (mp_gsi_routing[idx].gsi_end >= gsi_top)
+               gsi_top = mp_gsi_routing[idx].gsi_end + 1;
 
        printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
               "GSI %d-%d\n", idx, mp_ioapics[idx].apicid,
index fdbc652..214ac86 100644 (file)
@@ -72,6 +72,7 @@ static struct event_constraint intel_westmere_event_constraints[] =
        INTEL_EVENT_CONSTRAINT(0x51, 0x3), /* L1D */
        INTEL_EVENT_CONSTRAINT(0x60, 0x1), /* OFFCORE_REQUESTS_OUTSTANDING */
        INTEL_EVENT_CONSTRAINT(0x63, 0x3), /* CACHE_LOCK_CYCLES */
+       INTEL_EVENT_CONSTRAINT(0xb3, 0x1), /* SNOOPQ_REQUEST_OUTSTANDING */
        EVENT_CONSTRAINT_END
 };
 
index 5ae5d24..d86dbf7 100644 (file)
@@ -123,7 +123,7 @@ static void __init MP_ioapic_info(struct mpc_ioapic *m)
        printk(KERN_INFO "I/O APIC #%d Version %d at 0x%X.\n",
               m->apicid, m->apicver, m->apicaddr);
 
-       mp_register_ioapic(m->apicid, m->apicaddr, gsi_end + 1);
+       mp_register_ioapic(m->apicid, m->apicaddr, gsi_top);
 }
 
 static void print_MP_intsrc_info(struct mpc_intsrc *m)
index fb99f7e..0b96b55 100644 (file)
@@ -103,11 +103,16 @@ int use_calgary __read_mostly = 0;
 #define PMR_SOFTSTOPFAULT      0x40000000
 #define PMR_HARDSTOP           0x20000000
 
-#define MAX_NUM_OF_PHBS                8 /* how many PHBs in total? */
-#define MAX_NUM_CHASSIS                8 /* max number of chassis */
-/* MAX_PHB_BUS_NUM is the maximal possible dev->bus->number */
-#define MAX_PHB_BUS_NUM                (MAX_NUM_OF_PHBS * MAX_NUM_CHASSIS * 2)
-#define PHBS_PER_CALGARY       4
+/*
+ * The maximum PHB bus number.
+ * x3950M2 (rare): 8 chassis, 48 PHBs per chassis = 384
+ * x3950M2: 4 chassis, 48 PHBs per chassis        = 192
+ * x3950 (PCIE): 8 chassis, 32 PHBs per chassis   = 256
+ * x3950 (PCIX): 8 chassis, 16 PHBs per chassis   = 128
+ */
+#define MAX_PHB_BUS_NUM                384
+
+#define PHBS_PER_CALGARY         4
 
 /* register offsets in Calgary's internal register space */
 static const unsigned long tar_offsets[] = {
index 8e1aac8..e3af342 100644 (file)
@@ -228,6 +228,14 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation T5400"),
                },
        },
+       {       /* Handle problems with rebooting on Dell T7400's */
+               .callback = set_bios_reboot,
+               .ident = "Dell Precision T7400",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation T7400"),
+               },
+       },
        {       /* Handle problems with rebooting on HP laptops */
                .callback = set_bios_reboot,
                .ident = "HP Compaq Laptop",
index 7ded578..cb22acf 100644 (file)
@@ -93,7 +93,7 @@ static int __init sfi_parse_ioapic(struct sfi_table_header *table)
        pentry = (struct sfi_apic_table_entry *)sb->pentry;
 
        for (i = 0; i < num; i++) {
-               mp_register_ioapic(i, pentry->phys_addr, gsi_end + 1);
+               mp_register_ioapic(i, pentry->phys_addr, gsi_top);
                pentry++;
        }
 
index acc15b2..64121a1 100644 (file)
@@ -302,7 +302,7 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
                return -EINVAL;
        }
 
-       new  = kmalloc(sizeof(struct memtype), GFP_KERNEL);
+       new  = kzalloc(sizeof(struct memtype), GFP_KERNEL);
        if (!new)
                return -ENOMEM;
 
index f537087..f20eeec 100644 (file)
@@ -226,6 +226,7 @@ int rbt_memtype_check_insert(struct memtype *new, unsigned long *ret_type)
                if (ret_type)
                        new->type = *ret_type;
 
+               new->subtree_max_end = new->end;
                memtype_rb_insert(&memtype_rbroot, new);
        }
        return err;
index f84cce4..f0640d7 100644 (file)
@@ -1149,13 +1149,10 @@ void init_request_from_bio(struct request *req, struct bio *bio)
        else
                req->cmd_flags |= bio->bi_rw & REQ_FAILFAST_MASK;
 
-       if (unlikely(bio_rw_flagged(bio, BIO_RW_DISCARD))) {
+       if (bio_rw_flagged(bio, BIO_RW_DISCARD))
                req->cmd_flags |= REQ_DISCARD;
-               if (bio_rw_flagged(bio, BIO_RW_BARRIER))
-                       req->cmd_flags |= REQ_SOFTBARRIER;
-       } else if (unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER)))
+       if (bio_rw_flagged(bio, BIO_RW_BARRIER))
                req->cmd_flags |= REQ_HARDBARRIER;
-
        if (bio_rw_flagged(bio, BIO_RW_SYNCIO))
                req->cmd_flags |= REQ_RW_SYNC;
        if (bio_rw_flagged(bio, BIO_RW_META))
@@ -1586,7 +1583,7 @@ void submit_bio(int rw, struct bio *bio)
         * If it's a regular read/write or a barrier with data attached,
         * go through the normal accounting stuff before submission.
         */
-       if (bio_has_data(bio)) {
+       if (bio_has_data(bio) && !(rw & (1 << BIO_RW_DISCARD))) {
                if (rw & WRITE) {
                        count_vm_events(PGPGOUT, count);
                } else {
index 5ff4f48..7982b83 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/rbtree.h>
 #include <linux/ioprio.h>
 #include <linux/blktrace_api.h>
-#include "blk-cgroup.h"
+#include "cfq.h"
 
 /*
  * tunables
@@ -879,7 +879,7 @@ cfq_group_service_tree_del(struct cfq_data *cfqd, struct cfq_group *cfqg)
        if (!RB_EMPTY_NODE(&cfqg->rb_node))
                cfq_rb_erase(&cfqg->rb_node, st);
        cfqg->saved_workload_slice = 0;
-       blkiocg_update_dequeue_stats(&cfqg->blkg, 1);
+       cfq_blkiocg_update_dequeue_stats(&cfqg->blkg, 1);
 }
 
 static inline unsigned int cfq_cfqq_slice_usage(struct cfq_queue *cfqq)
@@ -939,8 +939,8 @@ static void cfq_group_served(struct cfq_data *cfqd, struct cfq_group *cfqg,
 
        cfq_log_cfqg(cfqd, cfqg, "served: vt=%llu min_vt=%llu", cfqg->vdisktime,
                                        st->min_vdisktime);
-       blkiocg_update_timeslice_used(&cfqg->blkg, used_sl);
-       blkiocg_set_start_empty_time(&cfqg->blkg);
+       cfq_blkiocg_update_timeslice_used(&cfqg->blkg, used_sl);
+       cfq_blkiocg_set_start_empty_time(&cfqg->blkg);
 }
 
 #ifdef CONFIG_CFQ_GROUP_IOSCHED
@@ -995,7 +995,7 @@ cfq_find_alloc_cfqg(struct cfq_data *cfqd, struct cgroup *cgroup, int create)
 
        /* Add group onto cgroup list */
        sscanf(dev_name(bdi->dev), "%u:%u", &major, &minor);
-       blkiocg_add_blkio_group(blkcg, &cfqg->blkg, (void *)cfqd,
+       cfq_blkiocg_add_blkio_group(blkcg, &cfqg->blkg, (void *)cfqd,
                                        MKDEV(major, minor));
        cfqg->weight = blkcg_get_weight(blkcg, cfqg->blkg.dev);
 
@@ -1079,7 +1079,7 @@ static void cfq_release_cfq_groups(struct cfq_data *cfqd)
                 * it from cgroup list, then it will take care of destroying
                 * cfqg also.
                 */
-               if (!blkiocg_del_blkio_group(&cfqg->blkg))
+               if (!cfq_blkiocg_del_blkio_group(&cfqg->blkg))
                        cfq_destroy_cfqg(cfqd, cfqg);
        }
 }
@@ -1421,10 +1421,10 @@ static void cfq_reposition_rq_rb(struct cfq_queue *cfqq, struct request *rq)
 {
        elv_rb_del(&cfqq->sort_list, rq);
        cfqq->queued[rq_is_sync(rq)]--;
-       blkiocg_update_io_remove_stats(&(RQ_CFQG(rq))->blkg, rq_data_dir(rq),
-                                               rq_is_sync(rq));
+       cfq_blkiocg_update_io_remove_stats(&(RQ_CFQG(rq))->blkg,
+                                       rq_data_dir(rq), rq_is_sync(rq));
        cfq_add_rq_rb(rq);
-       blkiocg_update_io_add_stats(&(RQ_CFQG(rq))->blkg,
+       cfq_blkiocg_update_io_add_stats(&(RQ_CFQG(rq))->blkg,
                        &cfqq->cfqd->serving_group->blkg, rq_data_dir(rq),
                        rq_is_sync(rq));
 }
@@ -1482,8 +1482,8 @@ static void cfq_remove_request(struct request *rq)
        cfq_del_rq_rb(rq);
 
        cfqq->cfqd->rq_queued--;
-       blkiocg_update_io_remove_stats(&(RQ_CFQG(rq))->blkg, rq_data_dir(rq),
-                                               rq_is_sync(rq));
+       cfq_blkiocg_update_io_remove_stats(&(RQ_CFQG(rq))->blkg,
+                                       rq_data_dir(rq), rq_is_sync(rq));
        if (rq_is_meta(rq)) {
                WARN_ON(!cfqq->meta_pending);
                cfqq->meta_pending--;
@@ -1518,8 +1518,8 @@ static void cfq_merged_request(struct request_queue *q, struct request *req,
 static void cfq_bio_merged(struct request_queue *q, struct request *req,
                                struct bio *bio)
 {
-       blkiocg_update_io_merged_stats(&(RQ_CFQG(req))->blkg, bio_data_dir(bio),
-                                       cfq_bio_sync(bio));
+       cfq_blkiocg_update_io_merged_stats(&(RQ_CFQG(req))->blkg,
+                                       bio_data_dir(bio), cfq_bio_sync(bio));
 }
 
 static void
@@ -1539,8 +1539,8 @@ cfq_merged_requests(struct request_queue *q, struct request *rq,
        if (cfqq->next_rq == next)
                cfqq->next_rq = rq;
        cfq_remove_request(next);
-       blkiocg_update_io_merged_stats(&(RQ_CFQG(rq))->blkg, rq_data_dir(next),
-                                       rq_is_sync(next));
+       cfq_blkiocg_update_io_merged_stats(&(RQ_CFQG(rq))->blkg,
+                                       rq_data_dir(next), rq_is_sync(next));
 }
 
 static int cfq_allow_merge(struct request_queue *q, struct request *rq,
@@ -1571,7 +1571,7 @@ static int cfq_allow_merge(struct request_queue *q, struct request *rq,
 static inline void cfq_del_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq)
 {
        del_timer(&cfqd->idle_slice_timer);
-       blkiocg_update_idle_time_stats(&cfqq->cfqg->blkg);
+       cfq_blkiocg_update_idle_time_stats(&cfqq->cfqg->blkg);
 }
 
 static void __cfq_set_active_queue(struct cfq_data *cfqd,
@@ -1580,7 +1580,7 @@ static void __cfq_set_active_queue(struct cfq_data *cfqd,
        if (cfqq) {
                cfq_log_cfqq(cfqd, cfqq, "set_active wl_prio:%d wl_type:%d",
                                cfqd->serving_prio, cfqd->serving_type);
-               blkiocg_update_avg_queue_size_stats(&cfqq->cfqg->blkg);
+               cfq_blkiocg_update_avg_queue_size_stats(&cfqq->cfqg->blkg);
                cfqq->slice_start = 0;
                cfqq->dispatch_start = jiffies;
                cfqq->allocated_slice = 0;
@@ -1911,7 +1911,7 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd)
        sl = cfqd->cfq_slice_idle;
 
        mod_timer(&cfqd->idle_slice_timer, jiffies + sl);
-       blkiocg_update_set_idle_time_stats(&cfqq->cfqg->blkg);
+       cfq_blkiocg_update_set_idle_time_stats(&cfqq->cfqg->blkg);
        cfq_log_cfqq(cfqd, cfqq, "arm_idle: %lu", sl);
 }
 
@@ -1931,7 +1931,7 @@ static void cfq_dispatch_insert(struct request_queue *q, struct request *rq)
        elv_dispatch_sort(q, rq);
 
        cfqd->rq_in_flight[cfq_cfqq_sync(cfqq)]++;
-       blkiocg_update_dispatch_stats(&cfqq->cfqg->blkg, blk_rq_bytes(rq),
+       cfq_blkiocg_update_dispatch_stats(&cfqq->cfqg->blkg, blk_rq_bytes(rq),
                                        rq_data_dir(rq), rq_is_sync(rq));
 }
 
@@ -1986,6 +1986,15 @@ static void cfq_setup_merge(struct cfq_queue *cfqq, struct cfq_queue *new_cfqq)
        int process_refs, new_process_refs;
        struct cfq_queue *__cfqq;
 
+       /*
+        * If there are no process references on the new_cfqq, then it is
+        * unsafe to follow the ->new_cfqq chain as other cfqq's in the
+        * chain may have dropped their last reference (not just their
+        * last process reference).
+        */
+       if (!cfqq_process_refs(new_cfqq))
+               return;
+
        /* Avoid a circular list and skip interim queue merges */
        while ((__cfqq = new_cfqq->new_cfqq)) {
                if (__cfqq == cfqq)
@@ -1994,17 +2003,17 @@ static void cfq_setup_merge(struct cfq_queue *cfqq, struct cfq_queue *new_cfqq)
        }
 
        process_refs = cfqq_process_refs(cfqq);
+       new_process_refs = cfqq_process_refs(new_cfqq);
        /*
         * If the process for the cfqq has gone away, there is no
         * sense in merging the queues.
         */
-       if (process_refs == 0)
+       if (process_refs == 0 || new_process_refs == 0)
                return;
 
        /*
         * Merge in the direction of the lesser amount of work.
         */
-       new_process_refs = cfqq_process_refs(new_cfqq);
        if (new_process_refs >= process_refs) {
                cfqq->new_cfqq = new_cfqq;
                atomic_add(process_refs, &new_cfqq->ref);
@@ -3248,7 +3257,7 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
                                cfq_clear_cfqq_wait_request(cfqq);
                                __blk_run_queue(cfqd->queue);
                        } else {
-                               blkiocg_update_idle_time_stats(
+                               cfq_blkiocg_update_idle_time_stats(
                                                &cfqq->cfqg->blkg);
                                cfq_mark_cfqq_must_dispatch(cfqq);
                        }
@@ -3276,7 +3285,7 @@ static void cfq_insert_request(struct request_queue *q, struct request *rq)
        rq_set_fifo_time(rq, jiffies + cfqd->cfq_fifo_expire[rq_is_sync(rq)]);
        list_add_tail(&rq->queuelist, &cfqq->fifo);
        cfq_add_rq_rb(rq);
-       blkiocg_update_io_add_stats(&(RQ_CFQG(rq))->blkg,
+       cfq_blkiocg_update_io_add_stats(&(RQ_CFQG(rq))->blkg,
                        &cfqd->serving_group->blkg, rq_data_dir(rq),
                        rq_is_sync(rq));
        cfq_rq_enqueued(cfqd, cfqq, rq);
@@ -3364,9 +3373,9 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq)
        WARN_ON(!cfqq->dispatched);
        cfqd->rq_in_driver--;
        cfqq->dispatched--;
-       blkiocg_update_completion_stats(&cfqq->cfqg->blkg, rq_start_time_ns(rq),
-                       rq_io_start_time_ns(rq), rq_data_dir(rq),
-                       rq_is_sync(rq));
+       cfq_blkiocg_update_completion_stats(&cfqq->cfqg->blkg,
+                       rq_start_time_ns(rq), rq_io_start_time_ns(rq),
+                       rq_data_dir(rq), rq_is_sync(rq));
 
        cfqd->rq_in_flight[cfq_cfqq_sync(cfqq)]--;
 
@@ -3730,7 +3739,7 @@ static void cfq_exit_queue(struct elevator_queue *e)
 
        cfq_put_async_queues(cfqd);
        cfq_release_cfq_groups(cfqd);
-       blkiocg_del_blkio_group(&cfqd->root_group.blkg);
+       cfq_blkiocg_del_blkio_group(&cfqd->root_group.blkg);
 
        spin_unlock_irq(q->queue_lock);
 
@@ -3798,8 +3807,8 @@ static void *cfq_init_queue(struct request_queue *q)
         */
        atomic_set(&cfqg->ref, 1);
        rcu_read_lock();
-       blkiocg_add_blkio_group(&blkio_root_cgroup, &cfqg->blkg, (void *)cfqd,
-                                       0);
+       cfq_blkiocg_add_blkio_group(&blkio_root_cgroup, &cfqg->blkg,
+                                       (void *)cfqd, 0);
        rcu_read_unlock();
 #endif
        /*
diff --git a/block/cfq.h b/block/cfq.h
new file mode 100644 (file)
index 0000000..93448e5
--- /dev/null
@@ -0,0 +1,115 @@
+#ifndef _CFQ_H
+#define _CFQ_H
+#include "blk-cgroup.h"
+
+#ifdef CONFIG_CFQ_GROUP_IOSCHED
+static inline void cfq_blkiocg_update_io_add_stats(struct blkio_group *blkg,
+       struct blkio_group *curr_blkg, bool direction, bool sync)
+{
+       blkiocg_update_io_add_stats(blkg, curr_blkg, direction, sync);
+}
+
+static inline void cfq_blkiocg_update_dequeue_stats(struct blkio_group *blkg,
+                       unsigned long dequeue)
+{
+       blkiocg_update_dequeue_stats(blkg, dequeue);
+}
+
+static inline void cfq_blkiocg_update_timeslice_used(struct blkio_group *blkg,
+                       unsigned long time)
+{
+       blkiocg_update_timeslice_used(blkg, time);
+}
+
+static inline void cfq_blkiocg_set_start_empty_time(struct blkio_group *blkg)
+{
+       blkiocg_set_start_empty_time(blkg);
+}
+
+static inline void cfq_blkiocg_update_io_remove_stats(struct blkio_group *blkg,
+                               bool direction, bool sync)
+{
+       blkiocg_update_io_remove_stats(blkg, direction, sync);
+}
+
+static inline void cfq_blkiocg_update_io_merged_stats(struct blkio_group *blkg,
+               bool direction, bool sync)
+{
+       blkiocg_update_io_merged_stats(blkg, direction, sync);
+}
+
+static inline void cfq_blkiocg_update_idle_time_stats(struct blkio_group *blkg)
+{
+       blkiocg_update_idle_time_stats(blkg);
+}
+
+static inline void
+cfq_blkiocg_update_avg_queue_size_stats(struct blkio_group *blkg)
+{
+       blkiocg_update_avg_queue_size_stats(blkg);
+}
+
+static inline void
+cfq_blkiocg_update_set_idle_time_stats(struct blkio_group *blkg)
+{
+       blkiocg_update_set_idle_time_stats(blkg);
+}
+
+static inline void cfq_blkiocg_update_dispatch_stats(struct blkio_group *blkg,
+                               uint64_t bytes, bool direction, bool sync)
+{
+       blkiocg_update_dispatch_stats(blkg, bytes, direction, sync);
+}
+
+static inline void cfq_blkiocg_update_completion_stats(struct blkio_group *blkg, uint64_t start_time, uint64_t io_start_time, bool direction, bool sync)
+{
+       blkiocg_update_completion_stats(blkg, start_time, io_start_time,
+                               direction, sync);
+}
+
+static inline void cfq_blkiocg_add_blkio_group(struct blkio_cgroup *blkcg,
+                       struct blkio_group *blkg, void *key, dev_t dev) {
+       blkiocg_add_blkio_group(blkcg, blkg, key, dev);
+}
+
+static inline int cfq_blkiocg_del_blkio_group(struct blkio_group *blkg)
+{
+       return blkiocg_del_blkio_group(blkg);
+}
+
+#else /* CFQ_GROUP_IOSCHED */
+static inline void cfq_blkiocg_update_io_add_stats(struct blkio_group *blkg,
+       struct blkio_group *curr_blkg, bool direction, bool sync) {}
+
+static inline void cfq_blkiocg_update_dequeue_stats(struct blkio_group *blkg,
+                       unsigned long dequeue) {}
+
+static inline void cfq_blkiocg_update_timeslice_used(struct blkio_group *blkg,
+                       unsigned long time) {}
+static inline void cfq_blkiocg_set_start_empty_time(struct blkio_group *blkg) {}
+static inline void cfq_blkiocg_update_io_remove_stats(struct blkio_group *blkg,
+                               bool direction, bool sync) {}
+static inline void cfq_blkiocg_update_io_merged_stats(struct blkio_group *blkg,
+               bool direction, bool sync) {}
+static inline void cfq_blkiocg_update_idle_time_stats(struct blkio_group *blkg)
+{
+}
+static inline void
+cfq_blkiocg_update_avg_queue_size_stats(struct blkio_group *blkg) {}
+
+static inline void
+cfq_blkiocg_update_set_idle_time_stats(struct blkio_group *blkg) {}
+
+static inline void cfq_blkiocg_update_dispatch_stats(struct blkio_group *blkg,
+                               uint64_t bytes, bool direction, bool sync) {}
+static inline void cfq_blkiocg_update_completion_stats(struct blkio_group *blkg, uint64_t start_time, uint64_t io_start_time, bool direction, bool sync) {}
+
+static inline void cfq_blkiocg_add_blkio_group(struct blkio_cgroup *blkcg,
+                       struct blkio_group *blkg, void *key, dev_t dev) {}
+static inline int cfq_blkiocg_del_blkio_group(struct blkio_group *blkg)
+{
+       return 0;
+}
+
+#endif /* CFQ_GROUP_IOSCHED */
+#endif
index db3946e..216e1e9 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/acpi.h>
+#include <linux/slab.h>
 #include <linux/io.h>
 #include <linux/kref.h>
 #include <linux/rculist.h>
index 814b192..8f8bd73 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/kref.h>
 #include <linux/rculist.h>
 #include <linux/interrupt.h>
+#include <linux/slab.h>
 #include <acpi/atomicio.h>
 
 #define ACPI_PFX "ACPI: "
index 3381505..72dae92 100644 (file)
@@ -861,6 +861,7 @@ cciss_scsi_detect(int ctlr)
        sh->n_io_port = 0;      // I don't think we use these two...
        sh->this_id = SELF_SCSI_ID;  
        sh->sg_tablesize = hba[ctlr]->maxsgentries;
+       sh->max_cmd_len = MAX_COMMAND_SIZE;
 
        ((struct cciss_scsi_adapter_data_t *) 
                hba[ctlr]->scsi_ctlr)->scsi_host = sh;
index 91d1163..abb4ec6 100644 (file)
@@ -386,7 +386,7 @@ static void __devexit cpqarray_remove_one_eisa (int i)
 }
 
 /* pdev is NULL for eisa */
-static int __init cpqarray_register_ctlr( int i, struct pci_dev *pdev)
+static int __devinit cpqarray_register_ctlr( int i, struct pci_dev *pdev)
 {
        struct request_queue *q;
        int j;
@@ -503,7 +503,7 @@ Enomem4:
        return -1;
 }
 
-static int __init cpqarray_init_one( struct pci_dev *pdev,
+static int __devinit cpqarray_init_one( struct pci_dev *pdev,
        const struct pci_device_id *ent)
 {
        int i;
@@ -740,7 +740,7 @@ __setup("smart2=", cpqarray_setup);
 /*
  * Find an EISA controller's signature.  Set up an hba if we find it.
  */
-static int __init cpqarray_eisa_detect(void)
+static int __devinit cpqarray_eisa_detect(void)
 {
        int i=0, j;
        __u32 board_id;
index 6b077f9..7258c95 100644 (file)
@@ -1236,8 +1236,6 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
        /* Last part of the attaching process ... */
        if (ns.conn >= C_CONNECTED &&
            os.disk == D_ATTACHING && ns.disk == D_NEGOTIATING) {
-               kfree(mdev->p_uuid); /* We expect to receive up-to-date UUIDs soon. */
-               mdev->p_uuid = NULL; /* ...to not use the old ones in the mean time */
                drbd_send_sizes(mdev, 0, 0);  /* to start sync... */
                drbd_send_uuids(mdev);
                drbd_send_state(mdev);
index 632e324..2151f18 100644 (file)
@@ -1114,6 +1114,12 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
                mdev->new_state_tmp.i = ns.i;
                ns.i = os.i;
                ns.disk = D_NEGOTIATING;
+
+               /* We expect to receive up-to-date UUIDs soon.
+                  To avoid a race in receive_state, free p_uuid while
+                  holding req_lock. I.e. atomic with the state change */
+               kfree(mdev->p_uuid);
+               mdev->p_uuid = NULL;
        }
 
        rv = _drbd_set_state(mdev, ns, CS_VERBOSE, NULL);
index 35603dd..094bdc3 100644 (file)
@@ -302,6 +302,12 @@ struct smi_info {
 
 static int force_kipmid[SI_MAX_PARMS];
 static int num_force_kipmid;
+#ifdef CONFIG_PCI
+static int pci_registered;
+#endif
+#ifdef CONFIG_PPC_OF
+static int of_registered;
+#endif
 
 static unsigned int kipmid_max_busy_us[SI_MAX_PARMS];
 static int num_max_busy_us;
@@ -1018,7 +1024,7 @@ static int ipmi_thread(void *data)
                else if (smi_result == SI_SM_IDLE)
                        schedule_timeout_interruptible(100);
                else
-                       schedule_timeout_interruptible(0);
+                       schedule_timeout_interruptible(1);
        }
        return 0;
 }
@@ -3314,6 +3320,8 @@ static __devinit int init_ipmi_si(void)
        rv = pci_register_driver(&ipmi_pci_driver);
        if (rv)
                printk(KERN_ERR PFX "Unable to register PCI driver: %d\n", rv);
+       else
+               pci_registered = 1;
 #endif
 
 #ifdef CONFIG_ACPI
@@ -3330,6 +3338,7 @@ static __devinit int init_ipmi_si(void)
 
 #ifdef CONFIG_PPC_OF
        of_register_platform_driver(&ipmi_of_platform_driver);
+       of_registered = 1;
 #endif
 
        /* We prefer devices with interrupts, but in the case of a machine
@@ -3383,11 +3392,13 @@ static __devinit int init_ipmi_si(void)
        if (unload_when_empty && list_empty(&smi_infos)) {
                mutex_unlock(&smi_infos_lock);
 #ifdef CONFIG_PCI
-               pci_unregister_driver(&ipmi_pci_driver);
+               if (pci_registered)
+                       pci_unregister_driver(&ipmi_pci_driver);
 #endif
 
 #ifdef CONFIG_PPC_OF
-               of_unregister_platform_driver(&ipmi_of_platform_driver);
+               if (of_registered)
+                       of_unregister_platform_driver(&ipmi_of_platform_driver);
 #endif
                driver_unregister(&ipmi_driver.driver);
                printk(KERN_WARNING PFX
@@ -3478,14 +3489,16 @@ static __exit void cleanup_ipmi_si(void)
                return;
 
 #ifdef CONFIG_PCI
-       pci_unregister_driver(&ipmi_pci_driver);
+       if (pci_registered)
+               pci_unregister_driver(&ipmi_pci_driver);
 #endif
 #ifdef CONFIG_ACPI
        pnp_unregister_driver(&ipmi_pnp_driver);
 #endif
 
 #ifdef CONFIG_PPC_OF
-       of_unregister_platform_driver(&ipmi_of_platform_driver);
+       if (of_registered)
+               of_unregister_platform_driver(&ipmi_of_platform_driver);
 #endif
 
        mutex_lock(&smi_infos_lock);
index 724038d..7face91 100644 (file)
@@ -1,5 +1,5 @@
 #
-# GPIO infrastructure and expanders
+# platform-neutral GPIO infrastructure and expanders
 #
 
 config ARCH_WANT_OPTIONAL_GPIOLIB
index 51c3cdd..e53dcff 100644 (file)
@@ -1,4 +1,8 @@
-# gpio support: dedicated expander chips, etc
+# generic gpio support: dedicated expander chips, etc
+#
+# NOTE: platform-specific GPIO drivers don't belong in the
+# drivers/gpio directory; put them with other platform setup
+# code, IRQ controllers, board init, etc.
 
 ccflags-$(CONFIG_DEBUG_GPIO)   += -DDEBUG
 
index 92a8f6c..34647fc 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/bcd.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/slab.h>
 
 /*
  * The DaVinci RTC is a simple RTC with the following
index de033b7..d827ce5 100644 (file)
@@ -777,7 +777,7 @@ static int __devinit ds1307_probe(struct i2c_client *client,
 
 read_rtc:
        /* read RTC registers */
-       tmp = ds1307->read_block_data(ds1307->client, 0, 8, buf);
+       tmp = ds1307->read_block_data(ds1307->client, ds1307->offset, 8, buf);
        if (tmp != 8) {
                pr_debug("read error %d\n", tmp);
                err = -EIO;
@@ -862,7 +862,7 @@ read_rtc:
                if (ds1307->regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
                        tmp += 12;
                i2c_smbus_write_byte_data(client,
-                               DS1307_REG_HOUR,
+                               ds1307->offset + DS1307_REG_HOUR,
                                bin2bcd(tmp));
        }
 
index 9eb62a2..cd6cf57 100644 (file)
@@ -930,6 +930,83 @@ static void cpm_uart_config_port(struct uart_port *port, int flags)
        }
 }
 
+#if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_CPM_CONSOLE)
+/*
+ * Write a string to the serial port
+ * Note that this is called with interrupts already disabled
+ */
+static void cpm_uart_early_write(struct uart_cpm_port *pinfo,
+               const char *string, u_int count)
+{
+       unsigned int i;
+       cbd_t __iomem *bdp, *bdbase;
+       unsigned char *cpm_outp_addr;
+
+       /* Get the address of the host memory buffer.
+        */
+       bdp = pinfo->tx_cur;
+       bdbase = pinfo->tx_bd_base;
+
+       /*
+        * Now, do each character.  This is not as bad as it looks
+        * since this is a holding FIFO and not a transmitting FIFO.
+        * We could add the complexity of filling the entire transmit
+        * buffer, but we would just wait longer between accesses......
+        */
+       for (i = 0; i < count; i++, string++) {
+               /* Wait for transmitter fifo to empty.
+                * Ready indicates output is ready, and xmt is doing
+                * that, not that it is ready for us to send.
+                */
+               while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
+                       ;
+
+               /* Send the character out.
+                * If the buffer address is in the CPM DPRAM, don't
+                * convert it.
+                */
+               cpm_outp_addr = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr),
+                                       pinfo);
+               *cpm_outp_addr = *string;
+
+               out_be16(&bdp->cbd_datlen, 1);
+               setbits16(&bdp->cbd_sc, BD_SC_READY);
+
+               if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
+                       bdp = bdbase;
+               else
+                       bdp++;
+
+               /* if a LF, also do CR... */
+               if (*string == 10) {
+                       while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
+                               ;
+
+                       cpm_outp_addr = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr),
+                                               pinfo);
+                       *cpm_outp_addr = 13;
+
+                       out_be16(&bdp->cbd_datlen, 1);
+                       setbits16(&bdp->cbd_sc, BD_SC_READY);
+
+                       if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
+                               bdp = bdbase;
+                       else
+                               bdp++;
+               }
+       }
+
+       /*
+        * Finally, Wait for transmitter & holding register to empty
+        *  and restore the IER
+        */
+       while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
+               ;
+
+       pinfo->tx_cur = bdp;
+}
+#endif
+
 #ifdef CONFIG_CONSOLE_POLL
 /* Serial polling routines for writing and reading from the uart while
  * in an interrupt or debug context.
@@ -999,7 +1076,7 @@ static void cpm_put_poll_char(struct uart_port *port,
        static char ch[2];
 
        ch[0] = (char)c;
-       cpm_uart_early_write(pinfo->port.line, ch, 1);
+       cpm_uart_early_write(pinfo, ch, 1);
 }
 #endif /* CONFIG_CONSOLE_POLL */
 
@@ -1130,9 +1207,6 @@ static void cpm_uart_console_write(struct console *co, const char *s,
                                   u_int count)
 {
        struct uart_cpm_port *pinfo = &cpm_uart_ports[co->index];
-       unsigned int i;
-       cbd_t __iomem *bdp, *bdbase;
-       unsigned char *cp;
        unsigned long flags;
        int nolock = oops_in_progress;
 
@@ -1142,66 +1216,7 @@ static void cpm_uart_console_write(struct console *co, const char *s,
                spin_lock_irqsave(&pinfo->port.lock, flags);
        }
 
-       /* Get the address of the host memory buffer.
-        */
-       bdp = pinfo->tx_cur;
-       bdbase = pinfo->tx_bd_base;
-
-       /*
-        * Now, do each character.  This is not as bad as it looks
-        * since this is a holding FIFO and not a transmitting FIFO.
-        * We could add the complexity of filling the entire transmit
-        * buffer, but we would just wait longer between accesses......
-        */
-       for (i = 0; i < count; i++, s++) {
-               /* Wait for transmitter fifo to empty.
-                * Ready indicates output is ready, and xmt is doing
-                * that, not that it is ready for us to send.
-                */
-               while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
-                       ;
-
-               /* Send the character out.
-                * If the buffer address is in the CPM DPRAM, don't
-                * convert it.
-                */
-               cp = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
-               *cp = *s;
-
-               out_be16(&bdp->cbd_datlen, 1);
-               setbits16(&bdp->cbd_sc, BD_SC_READY);
-
-               if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
-                       bdp = bdbase;
-               else
-                       bdp++;
-
-               /* if a LF, also do CR... */
-               if (*s == 10) {
-                       while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
-                               ;
-
-                       cp = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
-                       *cp = 13;
-
-                       out_be16(&bdp->cbd_datlen, 1);
-                       setbits16(&bdp->cbd_sc, BD_SC_READY);
-
-                       if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
-                               bdp = bdbase;
-                       else
-                               bdp++;
-               }
-       }
-
-       /*
-        * Finally, Wait for transmitter & holding register to empty
-        *  and restore the IER
-        */
-       while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
-               ;
-
-       pinfo->tx_cur = bdp;
+       cpm_uart_early_write(pinfo, s, count);
 
        if (unlikely(nolock)) {
                local_irq_restore(flags);
index ce081cd..273e26e 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/device.h>
 #include <linux/interrupt.h>
 #include <linux/usb.h>
+#include <linux/slab.h>
 
 #include <asm/delay.h>
 #include <sound/core.h>
index cedd904..6a9ae40 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/i2c.h>
 #include <linux/usb.h>
 #include <linux/version.h>
+#include <linux/slab.h>
 #include <media/v4l2-common.h>
 #include <media/tuner.h>
 #include <media/tvaudio.h>
index 27f3f55..c3690e3 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/slab.h>
 #include <linux/usb.h>
 #include <linux/i2c.h>
 #include "tm6000.h"
index 261e66a..86c1c8b 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/slab.h>
 #include <linux/usb.h>
 
 #include "tm6000.h"
index 76e7dac..70b1d9d 100644 (file)
@@ -40,7 +40,7 @@ static int vram;
 static int vt_switch;
 
 /* Modes relevant to the GX (taken from modedb.c) */
-static struct fb_videomode gx_modedb[] __initdata = {
+static struct fb_videomode gx_modedb[] __devinitdata = {
        /* 640x480-60 VESA */
        { NULL, 60, 640, 480, 39682,  48, 16, 33, 10, 96, 2,
          0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
@@ -110,14 +110,15 @@ static struct fb_videomode gx_modedb[] __initdata = {
 #ifdef CONFIG_OLPC
 #include <asm/olpc.h>
 
-static struct fb_videomode gx_dcon_modedb[] __initdata = {
+static struct fb_videomode gx_dcon_modedb[] __devinitdata = {
        /* The only mode the DCON has is 1200x900 */
        { NULL, 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3,
          FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
          FB_VMODE_NONINTERLACED, 0 }
 };
 
-static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size)
+static void __devinit get_modedb(struct fb_videomode **modedb,
+               unsigned int *size)
 {
        if (olpc_has_dcon()) {
                *modedb = (struct fb_videomode *) gx_dcon_modedb;
@@ -129,7 +130,8 @@ static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size)
 }
 
 #else
-static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size)
+static void __devinit get_modedb(struct fb_videomode **modedb,
+               unsigned int *size)
 {
        *modedb = (struct fb_videomode *) gx_modedb;
        *size = ARRAY_SIZE(gx_modedb);
@@ -226,7 +228,8 @@ static int gxfb_blank(int blank_mode, struct fb_info *info)
        return gx_blank_display(info, blank_mode);
 }
 
-static int __init gxfb_map_video_memory(struct fb_info *info, struct pci_dev *dev)
+static int __devinit gxfb_map_video_memory(struct fb_info *info,
+               struct pci_dev *dev)
 {
        struct gxfb_par *par = info->par;
        int ret;
@@ -290,7 +293,7 @@ static struct fb_ops gxfb_ops = {
        .fb_imageblit   = cfb_imageblit,
 };
 
-static struct fb_info * __init gxfb_init_fbinfo(struct device *dev)
+static struct fb_info *__devinit gxfb_init_fbinfo(struct device *dev)
 {
        struct gxfb_par *par;
        struct fb_info *info;
@@ -371,7 +374,8 @@ static int gxfb_resume(struct pci_dev *pdev)
 }
 #endif
 
-static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+static int __devinit gxfb_probe(struct pci_dev *pdev,
+               const struct pci_device_id *id)
 {
        struct gxfb_par *par;
        struct fb_info *info;
@@ -451,7 +455,7 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i
        return ret;
 }
 
-static void gxfb_remove(struct pci_dev *pdev)
+static void __devexit gxfb_remove(struct pci_dev *pdev)
 {
        struct fb_info *info = pci_get_drvdata(pdev);
        struct gxfb_par *par = info->par;
index 1a18da8..39bdbed 100644 (file)
@@ -35,7 +35,7 @@ static int vt_switch;
  * we try to make it something sane - 640x480-60 is sane
  */
 
-static struct fb_videomode geode_modedb[] __initdata = {
+static struct fb_videomode geode_modedb[] __devinitdata = {
        /* 640x480-60 */
        { NULL, 60, 640, 480, 39682, 48, 8, 25, 2, 88, 2,
          FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
@@ -219,14 +219,15 @@ static struct fb_videomode geode_modedb[] __initdata = {
 #ifdef CONFIG_OLPC
 #include <asm/olpc.h>
 
-static struct fb_videomode olpc_dcon_modedb[] __initdata = {
+static struct fb_videomode olpc_dcon_modedb[] __devinitdata = {
        /* The only mode the DCON has is 1200x900 */
        { NULL, 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3,
          FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
          FB_VMODE_NONINTERLACED, 0 }
 };
 
-static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size)
+static void __devinit get_modedb(struct fb_videomode **modedb,
+               unsigned int *size)
 {
        if (olpc_has_dcon()) {
                *modedb = (struct fb_videomode *) olpc_dcon_modedb;
@@ -238,7 +239,8 @@ static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size)
 }
 
 #else
-static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size)
+static void __devinit get_modedb(struct fb_videomode **modedb,
+               unsigned int *size)
 {
        *modedb = (struct fb_videomode *) geode_modedb;
        *size = ARRAY_SIZE(geode_modedb);
@@ -334,7 +336,7 @@ static int lxfb_blank(int blank_mode, struct fb_info *info)
 }
 
 
-static int __init lxfb_map_video_memory(struct fb_info *info,
+static int __devinit lxfb_map_video_memory(struct fb_info *info,
                                        struct pci_dev *dev)
 {
        struct lxfb_par *par = info->par;
@@ -412,7 +414,7 @@ static struct fb_ops lxfb_ops = {
        .fb_imageblit   = cfb_imageblit,
 };
 
-static struct fb_info * __init lxfb_init_fbinfo(struct device *dev)
+static struct fb_info * __devinit lxfb_init_fbinfo(struct device *dev)
 {
        struct lxfb_par *par;
        struct fb_info *info;
@@ -496,7 +498,7 @@ static int lxfb_resume(struct pci_dev *pdev)
 #define lxfb_resume NULL
 #endif
 
-static int __init lxfb_probe(struct pci_dev *pdev,
+static int __devinit lxfb_probe(struct pci_dev *pdev,
                             const struct pci_device_id *id)
 {
        struct lxfb_par *par;
@@ -588,7 +590,7 @@ err:
        return ret;
 }
 
-static void lxfb_remove(struct pci_dev *pdev)
+static void __devexit lxfb_remove(struct pci_dev *pdev)
 {
        struct fb_info *info = pci_get_drvdata(pdev);
        struct lxfb_par *par = info->par;
index d4cde79..81687ed 100644 (file)
@@ -596,8 +596,6 @@ static int __devinit nuc900fb_probe(struct platform_device *pdev)
                goto release_regs;
        }
 
-       nuc900_driver_clksrc_div(&pdev->dev, "ext", 0x2);
-
        fbi->clk = clk_get(&pdev->dev, NULL);
        if (!fbi->clk || IS_ERR(fbi->clk)) {
                printk(KERN_ERR "nuc900-lcd:failed to get lcd clock source\n");
index b6ab27c..811384b 100644 (file)
  * Here we can be a bit looser than the data sections since this
  * needs to only meet arch ABI requirements.
  */
-#ifdef ARCH_SLAB_MINALIGN
-#define FLAT_STACK_ALIGN       (ARCH_SLAB_MINALIGN)
-#else
-#define FLAT_STACK_ALIGN       (sizeof(void *))
-#endif
+#define FLAT_STACK_ALIGN       max_t(unsigned long, sizeof(void *), ARCH_SLAB_MINALIGN)
 
 #define RELOC_FAILED 0xff00ff01                /* Relocation incorrect somewhere */
 #define UNLOADED_LIB 0x7ff000ff                /* Placeholder for unused library */
index d96047b..c8c78ba 100644 (file)
@@ -590,6 +590,8 @@ static void prune_dcache(int count)
                        up_read(&sb->s_umount);
                }
                spin_lock(&sb_lock);
+               /* lock was dropped, must reset next */
+               list_safe_reset_next(sb, n, s_list);
                count -= pruned;
                __put_super(sb);
                /* more work left to do? */
index 51e11bf..9d175d6 100644 (file)
@@ -733,12 +733,14 @@ static void kill_fasync_rcu(struct fasync_struct *fa, int sig, int band)
 {
        while (fa) {
                struct fown_struct *fown;
+               unsigned long flags;
+
                if (fa->magic != FASYNC_MAGIC) {
                        printk(KERN_ERR "kill_fasync: bad magic number in "
                               "fasync_struct!\n");
                        return;
                }
-               spin_lock(&fa->fa_lock);
+               spin_lock_irqsave(&fa->fa_lock, flags);
                if (fa->fa_file) {
                        fown = &fa->fa_file->f_owner;
                        /* Don't send SIGURG to processes which have not set a
@@ -747,7 +749,7 @@ static void kill_fasync_rcu(struct fasync_struct *fa, int sig, int band)
                        if (!(sig == SIGURG && fown->signum == 0))
                                send_sigio(fown, fa->fa_fd, band);
                }
-               spin_unlock(&fa->fa_lock);
+               spin_unlock_irqrestore(&fa->fa_lock, flags);
                fa = rcu_dereference(fa->fa_next);
        }
 }
index 1d1088f..0609607 100644 (file)
@@ -63,24 +63,16 @@ struct bdi_work {
 };
 
 enum {
-       WS_USED_B = 0,
-       WS_ONSTACK_B,
+       WS_INPROGRESS = 0,
+       WS_ONSTACK,
 };
 
-#define WS_USED (1 << WS_USED_B)
-#define WS_ONSTACK (1 << WS_ONSTACK_B)
-
-static inline bool bdi_work_on_stack(struct bdi_work *work)
-{
-       return test_bit(WS_ONSTACK_B, &work->state);
-}
-
 static inline void bdi_work_init(struct bdi_work *work,
                                 struct wb_writeback_args *args)
 {
        INIT_RCU_HEAD(&work->rcu_head);
        work->args = *args;
-       work->state = WS_USED;
+       __set_bit(WS_INPROGRESS, &work->state);
 }
 
 /**
@@ -95,43 +87,16 @@ int writeback_in_progress(struct backing_dev_info *bdi)
        return !list_empty(&bdi->work_list);
 }
 
-static void bdi_work_clear(struct bdi_work *work)
-{
-       clear_bit(WS_USED_B, &work->state);
-       smp_mb__after_clear_bit();
-       /*
-        * work can have disappeared at this point. bit waitq functions
-        * should be able to tolerate this, provided bdi_sched_wait does
-        * not dereference it's pointer argument.
-       */
-       wake_up_bit(&work->state, WS_USED_B);
-}
-
 static void bdi_work_free(struct rcu_head *head)
 {
        struct bdi_work *work = container_of(head, struct bdi_work, rcu_head);
 
-       if (!bdi_work_on_stack(work))
-               kfree(work);
-       else
-               bdi_work_clear(work);
-}
-
-static void wb_work_complete(struct bdi_work *work)
-{
-       const enum writeback_sync_modes sync_mode = work->args.sync_mode;
-       int onstack = bdi_work_on_stack(work);
+       clear_bit(WS_INPROGRESS, &work->state);
+       smp_mb__after_clear_bit();
+       wake_up_bit(&work->state, WS_INPROGRESS);
 
-       /*
-        * For allocated work, we can clear the done/seen bit right here.
-        * For on-stack work, we need to postpone both the clear and free
-        * to after the RCU grace period, since the stack could be invalidated
-        * as soon as bdi_work_clear() has done the wakeup.
-        */
-       if (!onstack)
-               bdi_work_clear(work);
-       if (sync_mode == WB_SYNC_NONE || onstack)
-               call_rcu(&work->rcu_head, bdi_work_free);
+       if (!test_bit(WS_ONSTACK, &work->state))
+               kfree(work);
 }
 
 static void wb_clear_pending(struct bdi_writeback *wb, struct bdi_work *work)
@@ -147,7 +112,7 @@ static void wb_clear_pending(struct bdi_writeback *wb, struct bdi_work *work)
                list_del_rcu(&work->list);
                spin_unlock(&bdi->wb_lock);
 
-               wb_work_complete(work);
+               call_rcu(&work->rcu_head, bdi_work_free);
        }
 }
 
@@ -185,9 +150,9 @@ static void bdi_queue_work(struct backing_dev_info *bdi, struct bdi_work *work)
  * Used for on-stack allocated work items. The caller needs to wait until
  * the wb threads have acked the work before it's safe to continue.
  */
-static void bdi_wait_on_work_clear(struct bdi_work *work)
+static void bdi_wait_on_work_done(struct bdi_work *work)
 {
-       wait_on_bit(&work->state, WS_USED_B, bdi_sched_wait,
+       wait_on_bit(&work->state, WS_INPROGRESS, bdi_sched_wait,
                    TASK_UNINTERRUPTIBLE);
 }
 
@@ -213,37 +178,28 @@ static void bdi_alloc_queue_work(struct backing_dev_info *bdi,
 }
 
 /**
- * bdi_sync_writeback - start and wait for writeback
- * @bdi: the backing device to write from
+ * bdi_queue_work_onstack - start and wait for writeback
  * @sb: write inodes from this super_block
  *
  * Description:
- *   This does WB_SYNC_ALL data integrity writeback and waits for the
- *   IO to complete. Callers must hold the sb s_umount semaphore for
+ *   This function initiates writeback and waits for the operation to
+ *   complete. Callers must hold the sb s_umount semaphore for
  *   reading, to avoid having the super disappear before we are done.
  */
-static void bdi_sync_writeback(struct backing_dev_info *bdi,
-                              struct super_block *sb)
+static void bdi_queue_work_onstack(struct wb_writeback_args *args)
 {
-       struct wb_writeback_args args = {
-               .sb             = sb,
-               .sync_mode      = WB_SYNC_ALL,
-               .nr_pages       = LONG_MAX,
-               .range_cyclic   = 0,
-       };
        struct bdi_work work;
 
-       bdi_work_init(&work, &args);
-       work.state |= WS_ONSTACK;
+       bdi_work_init(&work, args);
+       __set_bit(WS_ONSTACK, &work.state);
 
-       bdi_queue_work(bdi, &work);
-       bdi_wait_on_work_clear(&work);
+       bdi_queue_work(args->sb->s_bdi, &work);
+       bdi_wait_on_work_done(&work);
 }
 
 /**
  * bdi_start_writeback - start writeback
  * @bdi: the backing device to write from
- * @sb: write inodes from this super_block
  * @nr_pages: the number of pages to write
  *
  * Description:
@@ -252,25 +208,34 @@ static void bdi_sync_writeback(struct backing_dev_info *bdi,
  *   completion. Caller need not hold sb s_umount semaphore.
  *
  */
-void bdi_start_writeback(struct backing_dev_info *bdi, struct super_block *sb,
-                        long nr_pages)
+void bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages)
 {
        struct wb_writeback_args args = {
-               .sb             = sb,
                .sync_mode      = WB_SYNC_NONE,
                .nr_pages       = nr_pages,
                .range_cyclic   = 1,
        };
 
-       /*
-        * We treat @nr_pages=0 as the special case to do background writeback,
-        * ie. to sync pages until the background dirty threshold is reached.
-        */
-       if (!nr_pages) {
-               args.nr_pages = LONG_MAX;
-               args.for_background = 1;
-       }
+       bdi_alloc_queue_work(bdi, &args);
+}
 
+/**
+ * bdi_start_background_writeback - start background writeback
+ * @bdi: the backing device to write from
+ *
+ * Description:
+ *   This does WB_SYNC_NONE background writeback. The IO is only
+ *   started when this function returns, we make no guarentees on
+ *   completion. Caller need not hold sb s_umount semaphore.
+ */
+void bdi_start_background_writeback(struct backing_dev_info *bdi)
+{
+       struct wb_writeback_args args = {
+               .sync_mode      = WB_SYNC_NONE,
+               .nr_pages       = LONG_MAX,
+               .for_background = 1,
+               .range_cyclic   = 1,
+       };
        bdi_alloc_queue_work(bdi, &args);
 }
 
@@ -561,48 +526,30 @@ select_queue:
        return ret;
 }
 
-static void unpin_sb_for_writeback(struct super_block *sb)
-{
-       up_read(&sb->s_umount);
-       put_super(sb);
-}
-
-enum sb_pin_state {
-       SB_PINNED,
-       SB_NOT_PINNED,
-       SB_PIN_FAILED
-};
-
 /*
- * For WB_SYNC_NONE writeback, the caller does not have the sb pinned
+ * For background writeback the caller does not have the sb pinned
  * before calling writeback. So make sure that we do pin it, so it doesn't
  * go away while we are writing inodes from it.
  */
-static enum sb_pin_state pin_sb_for_writeback(struct writeback_control *wbc,
-                                             struct super_block *sb)
+static bool pin_sb_for_writeback(struct super_block *sb)
 {
-       /*
-        * Caller must already hold the ref for this
-        */
-       if (wbc->sync_mode == WB_SYNC_ALL) {
-               WARN_ON(!rwsem_is_locked(&sb->s_umount));
-               return SB_NOT_PINNED;
-       }
        spin_lock(&sb_lock);
+       if (list_empty(&sb->s_instances)) {
+               spin_unlock(&sb_lock);
+               return false;
+       }
+
        sb->s_count++;
+       spin_unlock(&sb_lock);
+
        if (down_read_trylock(&sb->s_umount)) {
-               if (sb->s_root) {
-                       spin_unlock(&sb_lock);
-                       return SB_PINNED;
-               }
-               /*
-                * umounted, drop rwsem again and fall through to failure
-                */
+               if (sb->s_root)
+                       return true;
                up_read(&sb->s_umount);
        }
-       sb->s_count--;
-       spin_unlock(&sb_lock);
-       return SB_PIN_FAILED;
+
+       put_super(sb);
+       return false;
 }
 
 /*
@@ -681,24 +628,31 @@ static void writeback_inodes_wb(struct bdi_writeback *wb,
                struct inode *inode = list_entry(wb->b_io.prev,
                                                 struct inode, i_list);
                struct super_block *sb = inode->i_sb;
-               enum sb_pin_state state;
 
-               if (wbc->sb && sb != wbc->sb) {
-                       /* super block given and doesn't
-                          match, skip this inode */
-                       redirty_tail(inode);
-                       continue;
-               }
-               state = pin_sb_for_writeback(wbc, sb);
+               if (wbc->sb) {
+                       /*
+                        * We are requested to write out inodes for a specific
+                        * superblock.  This means we already have s_umount
+                        * taken by the caller which also waits for us to
+                        * complete the writeout.
+                        */
+                       if (sb != wbc->sb) {
+                               redirty_tail(inode);
+                               continue;
+                       }
 
-               if (state == SB_PIN_FAILED) {
-                       requeue_io(inode);
-                       continue;
+                       WARN_ON(!rwsem_is_locked(&sb->s_umount));
+
+                       ret = writeback_sb_inodes(sb, wb, wbc);
+               } else {
+                       if (!pin_sb_for_writeback(sb)) {
+                               requeue_io(inode);
+                               continue;
+                       }
+                       ret = writeback_sb_inodes(sb, wb, wbc);
+                       drop_super(sb);
                }
-               ret = writeback_sb_inodes(sb, wb, wbc);
 
-               if (state == SB_PINNED)
-                       unpin_sb_for_writeback(sb);
                if (ret)
                        break;
        }
@@ -911,7 +865,7 @@ long wb_do_writeback(struct bdi_writeback *wb, int force_wait)
                 * If this isn't a data integrity operation, just notify
                 * that we have seen this work and we are now starting it.
                 */
-               if (args.sync_mode == WB_SYNC_NONE)
+               if (!test_bit(WS_ONSTACK, &work->state))
                        wb_clear_pending(wb, work);
 
                wrote += wb_writeback(wb, &args);
@@ -920,7 +874,7 @@ long wb_do_writeback(struct bdi_writeback *wb, int force_wait)
                 * This is a data integrity writeback, so only do the
                 * notification when we have completed the work.
                 */
-               if (args.sync_mode == WB_SYNC_ALL)
+               if (test_bit(WS_ONSTACK, &work->state))
                        wb_clear_pending(wb, work);
        }
 
@@ -978,42 +932,32 @@ int bdi_writeback_task(struct bdi_writeback *wb)
 }
 
 /*
- * Schedule writeback for all backing devices. This does WB_SYNC_NONE
- * writeback, for integrity writeback see bdi_sync_writeback().
+ * Start writeback of `nr_pages' pages.  If `nr_pages' is zero, write back
+ * the whole world.
  */
-static void bdi_writeback_all(struct super_block *sb, long nr_pages)
+void wakeup_flusher_threads(long nr_pages)
 {
+       struct backing_dev_info *bdi;
        struct wb_writeback_args args = {
-               .sb             = sb,
-               .nr_pages       = nr_pages,
                .sync_mode      = WB_SYNC_NONE,
        };
-       struct backing_dev_info *bdi;
 
-       rcu_read_lock();
+       if (nr_pages) {
+               args.nr_pages = nr_pages;
+       } else {
+               args.nr_pages = global_page_state(NR_FILE_DIRTY) +
+                               global_page_state(NR_UNSTABLE_NFS);
+       }
 
+       rcu_read_lock();
        list_for_each_entry_rcu(bdi, &bdi_list, bdi_list) {
                if (!bdi_has_dirty_io(bdi))
                        continue;
-
                bdi_alloc_queue_work(bdi, &args);
        }
-
        rcu_read_unlock();
 }
 
-/*
- * Start writeback of `nr_pages' pages.  If `nr_pages' is zero, write back
- * the whole world.
- */
-void wakeup_flusher_threads(long nr_pages)
-{
-       if (nr_pages == 0)
-               nr_pages = global_page_state(NR_FILE_DIRTY) +
-                               global_page_state(NR_UNSTABLE_NFS);
-       bdi_writeback_all(NULL, nr_pages);
-}
-
 static noinline void block_dump___mark_inode_dirty(struct inode *inode)
 {
        if (inode->i_ino || strcmp(inode->i_sb->s_id, "bdev")) {
@@ -1218,12 +1162,17 @@ void writeback_inodes_sb(struct super_block *sb)
 {
        unsigned long nr_dirty = global_page_state(NR_FILE_DIRTY);
        unsigned long nr_unstable = global_page_state(NR_UNSTABLE_NFS);
-       long nr_to_write;
+       struct wb_writeback_args args = {
+               .sb             = sb,
+               .sync_mode      = WB_SYNC_NONE,
+       };
+
+       WARN_ON(!rwsem_is_locked(&sb->s_umount));
 
-       nr_to_write = nr_dirty + nr_unstable +
+       args.nr_pages = nr_dirty + nr_unstable +
                        (inodes_stat.nr_inodes - inodes_stat.nr_unused);
 
-       bdi_start_writeback(sb->s_bdi, sb, nr_to_write);
+       bdi_queue_work_onstack(&args);
 }
 EXPORT_SYMBOL(writeback_inodes_sb);
 
@@ -1237,7 +1186,9 @@ EXPORT_SYMBOL(writeback_inodes_sb);
 int writeback_inodes_sb_if_idle(struct super_block *sb)
 {
        if (!writeback_in_progress(sb->s_bdi)) {
+               down_read(&sb->s_umount);
                writeback_inodes_sb(sb);
+               up_read(&sb->s_umount);
                return 1;
        } else
                return 0;
@@ -1253,7 +1204,16 @@ EXPORT_SYMBOL(writeback_inodes_sb_if_idle);
  */
 void sync_inodes_sb(struct super_block *sb)
 {
-       bdi_sync_writeback(sb->s_bdi, sb);
+       struct wb_writeback_args args = {
+               .sb             = sb,
+               .sync_mode      = WB_SYNC_ALL,
+               .nr_pages       = LONG_MAX,
+               .range_cyclic   = 0,
+       };
+
+       WARN_ON(!rwsem_is_locked(&sb->s_umount));
+
+       bdi_queue_work_onstack(&args);
        wait_sb_inodes(sb);
 }
 EXPORT_SYMBOL(sync_inodes_sb);
index 4065002..d8b6e42 100644 (file)
@@ -26,7 +26,6 @@
 
 #include <linux/fs.h>
 #include <linux/types.h>
-#include <linux/slab.h>
 #include <linux/highmem.h>
 #include <linux/bitops.h>
 #include <linux/list.h>
index 46d4b5d..cb6306e 100644 (file)
@@ -122,11 +122,20 @@ int task_statm(struct mm_struct *mm, int *shared, int *text,
        return size;
 }
 
+static void pad_len_spaces(struct seq_file *m, int len)
+{
+       len = 25 + sizeof(void*) * 6 - len;
+       if (len < 1)
+               len = 1;
+       seq_printf(m, "%*c", len, ' ');
+}
+
 /*
  * display a single VMA to a sequenced file
  */
 static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma)
 {
+       struct mm_struct *mm = vma->vm_mm;
        unsigned long ino = 0;
        struct file *file;
        dev_t dev = 0;
@@ -155,11 +164,14 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma)
                   MAJOR(dev), MINOR(dev), ino, &len);
 
        if (file) {
-               len = 25 + sizeof(void *) * 6 - len;
-               if (len < 1)
-                       len = 1;
-               seq_printf(m, "%*c", len, ' ');
+               pad_len_spaces(m, len);
                seq_path(m, &file->f_path, "");
+       } else if (mm) {
+               if (vma->vm_start <= mm->start_stack &&
+                       vma->vm_end >= mm->start_stack) {
+                       pad_len_spaces(m, len);
+                       seq_puts(m, "[stack]");
+               }
        }
 
        seq_putc(m, '\n');
index 5c35bc7..938119a 100644 (file)
@@ -374,6 +374,8 @@ void sync_supers(void)
                        up_read(&sb->s_umount);
 
                        spin_lock(&sb_lock);
+                       /* lock was dropped, must reset next */
+                       list_safe_reset_next(sb, n, s_list);
                        __put_super(sb);
                }
        }
@@ -405,6 +407,8 @@ void iterate_supers(void (*f)(struct super_block *, void *), void *arg)
                up_read(&sb->s_umount);
 
                spin_lock(&sb_lock);
+               /* lock was dropped, must reset next */
+               list_safe_reset_next(sb, n, s_list);
                __put_super(sb);
        }
        spin_unlock(&sb_lock);
@@ -585,6 +589,8 @@ static void do_emergency_remount(struct work_struct *work)
                }
                up_write(&sb->s_umount);
                spin_lock(&sb_lock);
+               /* lock was dropped, must reset next */
+               list_safe_reset_next(sb, n, s_list);
                __put_super(sb);
        }
        spin_unlock(&sb_lock);
index bbd69bd..fcc498e 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/stat.h>
 #include <linux/string.h>
 #include <linux/buffer_head.h>
+#include <linux/writeback.h>
 #include "sysv.h"
 
 /* We don't trust the value of
@@ -139,6 +140,9 @@ struct inode * sysv_new_inode(const struct inode * dir, mode_t mode)
        struct inode *inode;
        sysv_ino_t ino;
        unsigned count;
+       struct writeback_control wbc = {
+               .sync_mode = WB_SYNC_NONE
+       };
 
        inode = new_inode(sb);
        if (!inode)
@@ -168,7 +172,7 @@ struct inode * sysv_new_inode(const struct inode * dir, mode_t mode)
        insert_inode_hash(inode);
        mark_inode_dirty(inode);
 
-       sysv_write_inode(inode, 0);     /* ensure inode not allocated again */
+       sysv_write_inode(inode, &wbc);  /* ensure inode not allocated again */
        mark_inode_dirty(inode);        /* cleared by sysv_write_inode() */
        /* That's it. */
        unlock_super(sb);
index 076ca50..c8ff0d1 100644 (file)
@@ -62,7 +62,9 @@
  */
 static void shrink_liability(struct ubifs_info *c, int nr_to_write)
 {
+       down_read(&c->vfs_sb->s_umount);
        writeback_inodes_sb(c->vfs_sb);
+       up_read(&c->vfs_sb->s_umount);
 }
 
 /**
index aee5f6c..9ae2889 100644 (file)
@@ -105,8 +105,8 @@ int bdi_register(struct backing_dev_info *bdi, struct device *parent,
 int bdi_register_dev(struct backing_dev_info *bdi, dev_t dev);
 void bdi_unregister(struct backing_dev_info *bdi);
 int bdi_setup_and_register(struct backing_dev_info *, char *, unsigned int);
-void bdi_start_writeback(struct backing_dev_info *bdi, struct super_block *sb,
-                               long nr_pages);
+void bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages);
+void bdi_start_background_writeback(struct backing_dev_info *bdi);
 int bdi_writeback_task(struct bdi_writeback *wb);
 int bdi_has_dirty_io(struct backing_dev_info *bdi);
 void bdi_arm_supers_timer(void);
index 0c62160..e3d00fd 100644 (file)
@@ -525,13 +525,21 @@ static inline struct cgroup_subsys_state *cgroup_subsys_state(
        return cgrp->subsys[subsys_id];
 }
 
-static inline struct cgroup_subsys_state *task_subsys_state(
-       struct task_struct *task, int subsys_id)
+/*
+ * function to get the cgroup_subsys_state which allows for extra
+ * rcu_dereference_check() conditions, such as locks used during the
+ * cgroup_subsys::attach() methods.
+ */
+#define task_subsys_state_check(task, subsys_id, __c)                  \
+       rcu_dereference_check(task->cgroups->subsys[subsys_id],         \
+                             rcu_read_lock_held() ||                   \
+                             lockdep_is_held(&task->alloc_lock) ||     \
+                             cgroup_lock_is_held() || (__c))
+
+static inline struct cgroup_subsys_state *
+task_subsys_state(struct task_struct *task, int subsys_id)
 {
-       return rcu_dereference_check(task->cgroups->subsys[subsys_id],
-                                    rcu_read_lock_held() ||
-                                    lockdep_is_held(&task->alloc_lock) ||
-                                    cgroup_lock_is_held());
+       return task_subsys_state_check(task, subsys_id, false);
 }
 
 static inline struct cgroup* task_cgroup(struct task_struct *task,
index 73dcf80..0da5b18 100644 (file)
  * naked functions because then mcount is called without stack and frame pointer
  * being set up and there is no chance to restore the lr register to the value
  * before mcount was called.
+ *
+ * The asm() bodies of naked functions often depend on standard calling conventions,
+ * therefore they must be noinline and noclone.  GCC 4.[56] currently fail to enforce
+ * this, so we must do so ourselves.  See GCC PR44290.
  */
-#define __naked                                __attribute__((naked)) notrace
+#define __naked                                __attribute__((naked)) noinline __noclone notrace
 
 #define __noreturn                     __attribute__((noreturn))
 
@@ -85,3 +89,7 @@
 #define _gcc_header(x) __gcc_header(linux/compiler-gcc##x.h)
 #define gcc_header(x) _gcc_header(x)
 #include gcc_header(__GNUC__)
+
+#if !defined(__noclone)
+#define __noclone      /* not needed */
+#endif
index 94dea3f..fcfa5b9 100644 (file)
  * unreleased.  Really, we need to have autoconf for the kernel.
  */
 #define unreachable() __builtin_unreachable()
+
+/* Mark a function definition as prohibited from being cloned. */
+#define __noclone      __attribute__((__noclone__))
+
 #endif
 
 #endif
index 30da4ae..b8d2516 100644 (file)
@@ -53,7 +53,7 @@
 
 
 extern const char *drbd_buildtag(void);
-#define REL_VERSION "8.3.8rc2"
+#define REL_VERSION "8.3.8"
 #define API_VERSION 88
 #define PRO_VERSION_MIN 86
 #define PRO_VERSION_MAX 94
index 8392884..5d57a3a 100644 (file)
@@ -544,6 +544,21 @@ static inline void list_splice_tail_init(struct list_head *list,
             &pos->member != (head);                                    \
             pos = n, n = list_entry(n->member.prev, typeof(*n), member))
 
+/**
+ * list_safe_reset_next - reset a stale list_for_each_entry_safe loop
+ * @pos:       the loop cursor used in the list_for_each_entry_safe loop
+ * @n:         temporary storage used in list_for_each_entry_safe
+ * @member:    the name of the list_struct within the struct.
+ *
+ * list_safe_reset_next is not safe to use in general if the list may be
+ * modified concurrently (eg. the lock is dropped in the loop body). An
+ * exception to this is if the cursor element (pos) is pinned in the list,
+ * and list_safe_reset_next is called after re-taking the lock and before
+ * completing the current iteration of the loop body.
+ */
+#define list_safe_reset_next(pos, n, member)                           \
+       n = list_entry(pos->member.next, typeof(*pos), member)
+
 /*
  * Double linked lists with a single pointer list head.
  * Mostly useful for hash tables where the two pointer list head is
index 9a59d1f..103d1b6 100644 (file)
@@ -14,6 +14,7 @@
  * See the file COPYING for more details.
  */
 
+#include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/rcupdate.h>
 
index e7a35f1..6a3a5fa 100644 (file)
@@ -429,20 +429,11 @@ static void free_pi_state(struct futex_pi_state *pi_state)
 static struct task_struct * futex_find_get_task(pid_t pid)
 {
        struct task_struct *p;
-       const struct cred *cred = current_cred(), *pcred;
 
        rcu_read_lock();
        p = find_task_by_vpid(pid);
-       if (!p) {
-               p = ERR_PTR(-ESRCH);
-       } else {
-               pcred = __task_cred(p);
-               if (cred->euid != pcred->euid &&
-                   cred->euid != pcred->uid)
-                       p = ERR_PTR(-ESRCH);
-               else
-                       get_task_struct(p);
-       }
+       if (p)
+               get_task_struct(p);
 
        rcu_read_unlock();
 
@@ -564,8 +555,8 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
        if (!pid)
                return -ESRCH;
        p = futex_find_get_task(pid);
-       if (IS_ERR(p))
-               return PTR_ERR(p);
+       if (!p)
+               return -ESRCH;
 
        /*
         * We need to look at the task state flags to figure out,
index 3164ba7..e149748 100644 (file)
@@ -456,6 +456,9 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
                /* note that IRQF_TRIGGER_MASK == IRQ_TYPE_SENSE_MASK */
                desc->status &= ~(IRQ_LEVEL | IRQ_TYPE_SENSE_MASK);
                desc->status |= flags;
+
+               if (chip != desc->chip)
+                       irq_chip_set_defaults(desc->chip);
        }
 
        return ret;
index 474a847..131b170 100644 (file)
@@ -1089,9 +1089,10 @@ void crash_kexec(struct pt_regs *regs)
 
 size_t crash_get_memory_size(void)
 {
-       size_t size;
+       size_t size = 0;
        mutex_lock(&kexec_mutex);
-       size = crashk_res.end - crashk_res.start + 1;
+       if (crashk_res.end != crashk_res.start)
+               size = crashk_res.end - crashk_res.start + 1;
        mutex_unlock(&kexec_mutex);
        return size;
 }
@@ -1134,7 +1135,7 @@ int crash_shrink_memory(unsigned long new_size)
 
        free_reserved_phys_range(end, crashk_res.end);
 
-       if (start == end)
+       if ((start == end) && (crashk_res.parent != NULL))
                release_resource(&crashk_res);
        crashk_res.end = end - 1;
 
index f8b8996..cb816e3 100644 (file)
@@ -306,52 +306,6 @@ static int init_task_group_load = INIT_TASK_GROUP_LOAD;
  */
 struct task_group init_task_group;
 
-/* return group to which a task belongs */
-static inline struct task_group *task_group(struct task_struct *p)
-{
-       struct task_group *tg;
-
-#ifdef CONFIG_CGROUP_SCHED
-       tg = container_of(task_subsys_state(p, cpu_cgroup_subsys_id),
-                               struct task_group, css);
-#else
-       tg = &init_task_group;
-#endif
-       return tg;
-}
-
-/* Change a task's cfs_rq and parent entity if it moves across CPUs/groups */
-static inline void set_task_rq(struct task_struct *p, unsigned int cpu)
-{
-       /*
-        * Strictly speaking this rcu_read_lock() is not needed since the
-        * task_group is tied to the cgroup, which in turn can never go away
-        * as long as there are tasks attached to it.
-        *
-        * However since task_group() uses task_subsys_state() which is an
-        * rcu_dereference() user, this quiets CONFIG_PROVE_RCU.
-        */
-       rcu_read_lock();
-#ifdef CONFIG_FAIR_GROUP_SCHED
-       p->se.cfs_rq = task_group(p)->cfs_rq[cpu];
-       p->se.parent = task_group(p)->se[cpu];
-#endif
-
-#ifdef CONFIG_RT_GROUP_SCHED
-       p->rt.rt_rq  = task_group(p)->rt_rq[cpu];
-       p->rt.parent = task_group(p)->rt_se[cpu];
-#endif
-       rcu_read_unlock();
-}
-
-#else
-
-static inline void set_task_rq(struct task_struct *p, unsigned int cpu) { }
-static inline struct task_group *task_group(struct task_struct *p)
-{
-       return NULL;
-}
-
 #endif /* CONFIG_CGROUP_SCHED */
 
 /* CFS-related fields in a runqueue */
@@ -644,6 +598,49 @@ static inline int cpu_of(struct rq *rq)
 #define cpu_curr(cpu)          (cpu_rq(cpu)->curr)
 #define raw_rq()               (&__raw_get_cpu_var(runqueues))
 
+#ifdef CONFIG_CGROUP_SCHED
+
+/*
+ * Return the group to which this tasks belongs.
+ *
+ * We use task_subsys_state_check() and extend the RCU verification
+ * with lockdep_is_held(&task_rq(p)->lock) because cpu_cgroup_attach()
+ * holds that lock for each task it moves into the cgroup. Therefore
+ * by holding that lock, we pin the task to the current cgroup.
+ */
+static inline struct task_group *task_group(struct task_struct *p)
+{
+       struct cgroup_subsys_state *css;
+
+       css = task_subsys_state_check(p, cpu_cgroup_subsys_id,
+                       lockdep_is_held(&task_rq(p)->lock));
+       return container_of(css, struct task_group, css);
+}
+
+/* Change a task's cfs_rq and parent entity if it moves across CPUs/groups */
+static inline void set_task_rq(struct task_struct *p, unsigned int cpu)
+{
+#ifdef CONFIG_FAIR_GROUP_SCHED
+       p->se.cfs_rq = task_group(p)->cfs_rq[cpu];
+       p->se.parent = task_group(p)->se[cpu];
+#endif
+
+#ifdef CONFIG_RT_GROUP_SCHED
+       p->rt.rt_rq  = task_group(p)->rt_rq[cpu];
+       p->rt.parent = task_group(p)->rt_se[cpu];
+#endif
+}
+
+#else /* CONFIG_CGROUP_SCHED */
+
+static inline void set_task_rq(struct task_struct *p, unsigned int cpu) { }
+static inline struct task_group *task_group(struct task_struct *p)
+{
+       return NULL;
+}
+
+#endif /* CONFIG_CGROUP_SCHED */
+
 inline void update_rq_clock(struct rq *rq)
 {
        if (!rq->skip_clock_update)
@@ -1257,6 +1254,12 @@ static void sched_avg_update(struct rq *rq)
        s64 period = sched_avg_period();
 
        while ((s64)(rq->clock - rq->age_stamp) > period) {
+               /*
+                * Inline assembly required to prevent the compiler
+                * optimising this loop into a divmod call.
+                * See __iter_div_u64_rem() for another example of this.
+                */
+               asm("" : "+rm" (rq->age_stamp));
                rq->age_stamp += period;
                rq->rt_avg /= 2;
        }
@@ -1660,9 +1663,6 @@ static void update_shares(struct sched_domain *sd)
 
 static void update_h_load(long cpu)
 {
-       if (root_task_group_empty())
-               return;
-
        walk_tg_tree(tg_load_down, tg_nop, (void *)cpu);
 }
 
@@ -2494,7 +2494,16 @@ void sched_fork(struct task_struct *p, int clone_flags)
        if (p->sched_class->task_fork)
                p->sched_class->task_fork(p);
 
+       /*
+        * The child is not yet in the pid-hash so no cgroup attach races,
+        * and the cgroup is pinned to this child due to cgroup_fork()
+        * is ran before sched_fork().
+        *
+        * Silence PROVE_RCU.
+        */
+       rcu_read_lock();
        set_task_cpu(p, cpu);
+       rcu_read_unlock();
 
 #if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
        if (likely(sched_info_on()))
@@ -4465,16 +4474,6 @@ recheck:
        }
 
        if (user) {
-#ifdef CONFIG_RT_GROUP_SCHED
-               /*
-                * Do not allow realtime tasks into groups that have no runtime
-                * assigned.
-                */
-               if (rt_bandwidth_enabled() && rt_policy(policy) &&
-                               task_group(p)->rt_bandwidth.rt_runtime == 0)
-                       return -EPERM;
-#endif
-
                retval = security_task_setscheduler(p, policy, param);
                if (retval)
                        return retval;
@@ -4490,6 +4489,22 @@ recheck:
         * runqueue lock must be held.
         */
        rq = __task_rq_lock(p);
+
+#ifdef CONFIG_RT_GROUP_SCHED
+       if (user) {
+               /*
+                * Do not allow realtime tasks into groups that have no runtime
+                * assigned.
+                */
+               if (rt_bandwidth_enabled() && rt_policy(policy) &&
+                               task_group(p)->rt_bandwidth.rt_runtime == 0) {
+                       __task_rq_unlock(rq);
+                       raw_spin_unlock_irqrestore(&p->pi_lock, flags);
+                       return -EPERM;
+               }
+       }
+#endif
+
        /* recheck policy now with rq lock held */
        if (unlikely(oldpolicy != -1 && oldpolicy != p->policy)) {
                policy = oldpolicy = -1;
index eed35ed..a878b53 100644 (file)
@@ -1240,6 +1240,7 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p, int sync)
         * effect of the currently running task from the load
         * of the current CPU:
         */
+       rcu_read_lock();
        if (sync) {
                tg = task_group(current);
                weight = current->se.load.weight;
@@ -1275,6 +1276,7 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p, int sync)
                balanced = this_eff_load <= prev_eff_load;
        } else
                balanced = true;
+       rcu_read_unlock();
 
        /*
         * If the currently running task will sleep within
index 1d7b9bc..783fbad 100644 (file)
@@ -315,9 +315,6 @@ void tick_nohz_stop_sched_tick(int inidle)
                goto end;
        }
 
-       if (nohz_ratelimit(cpu))
-               goto end;
-
        ts->idle_calls++;
        /* Read jiffies and the time when jiffies were updated last */
        do {
@@ -328,7 +325,7 @@ void tick_nohz_stop_sched_tick(int inidle)
        } while (read_seqretry(&xtime_lock, seq));
 
        if (rcu_needs_cpu(cpu) || printk_needs_cpu(cpu) ||
-           arch_needs_cpu(cpu)) {
+           arch_needs_cpu(cpu) || nohz_ratelimit(cpu)) {
                next_jiffies = last_jiffies + 1;
                delta_jiffies = 1;
        } else {
index e6f6588..8a2b73f 100644 (file)
@@ -96,7 +96,9 @@ int perf_trace_init(struct perf_event *p_event)
        mutex_lock(&event_mutex);
        list_for_each_entry(tp_event, &ftrace_events, list) {
                if (tp_event->event.type == event_id &&
-                   tp_event->class && tp_event->class->perf_probe &&
+                   tp_event->class &&
+                   (tp_event->class->perf_probe ||
+                    tp_event->class->reg) &&
                    try_module_get(tp_event->mod)) {
                        ret = perf_trace_event_init(tp_event, p_event);
                        break;
index 736c3b0..1923f14 100644 (file)
@@ -128,7 +128,6 @@ unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size)
                chunk = list_entry(_chunk, struct gen_pool_chunk, next_chunk);
 
                end_bit = (chunk->end_addr - chunk->start_addr) >> order;
-               end_bit -= nbits + 1;
 
                spin_lock_irqsave(&chunk->lock, flags);
                start_bit = bitmap_find_next_zero_area(chunk->bits, end_bit, 0,
index c1a2069..7f1a4f0 100644 (file)
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -602,7 +602,7 @@ void *idr_get_next(struct idr *idp, int *nextidp)
        /* find first ent */
        n = idp->layers * IDR_BITS;
        max = 1 << n;
-       p = rcu_dereference(idp->top);
+       p = rcu_dereference_raw(idp->top);
        if (!p)
                return NULL;
 
@@ -610,7 +610,7 @@ void *idr_get_next(struct idr *idp, int *nextidp)
                while (n > 0 && p) {
                        n -= IDR_BITS;
                        *paa++ = p;
-                       p = rcu_dereference(p->ary[(id >> n) & IDR_MASK]);
+                       p = rcu_dereference_raw(p->ary[(id >> n) & IDR_MASK]);
                }
 
                if (p) {
index c6ece0a..20a8193 100644 (file)
@@ -1370,7 +1370,7 @@ static void memcg_wakeup_oom(struct mem_cgroup *mem)
 
 static void memcg_oom_recover(struct mem_cgroup *mem)
 {
-       if (mem->oom_kill_disable && atomic_read(&mem->oom_lock))
+       if (atomic_read(&mem->oom_lock))
                memcg_wakeup_oom(mem);
 }
 
@@ -3781,6 +3781,8 @@ static int mem_cgroup_oom_control_write(struct cgroup *cgrp,
                return -EINVAL;
        }
        mem->oom_kill_disable = val;
+       if (!val)
+               memcg_oom_recover(mem);
        cgroup_unlock();
        return 0;
 }
index 5d6fb33..5bc0a96 100644 (file)
@@ -2094,7 +2094,7 @@ void mpol_shared_policy_init(struct shared_policy *sp, struct mempolicy *mpol)
                NODEMASK_SCRATCH(scratch);
 
                if (!scratch)
-                       return;
+                       goto put_mpol;
                /* contextualize the tmpfs mount point mempolicy */
                new = mpol_new(mpol->mode, mpol->flags, &mpol->w.user_nodemask);
                if (IS_ERR(new))
@@ -2103,19 +2103,20 @@ void mpol_shared_policy_init(struct shared_policy *sp, struct mempolicy *mpol)
                task_lock(current);
                ret = mpol_set_nodemask(new, &mpol->w.user_nodemask, scratch);
                task_unlock(current);
-               mpol_put(mpol); /* drop our ref on sb mpol */
                if (ret)
-                       goto put_free;
+                       goto put_new;
 
                /* Create pseudo-vma that contains just the policy */
                memset(&pvma, 0, sizeof(struct vm_area_struct));
                pvma.vm_end = TASK_SIZE;        /* policy covers entire file */
                mpol_set_shared_policy(sp, &pvma, new); /* adds ref */
 
-put_free:
+put_new:
                mpol_put(new);                  /* drop initial ref */
 free_scratch:
                NODEMASK_SCRATCH_FREE(scratch);
+put_mpol:
+               mpol_put(mpol); /* drop our incoming ref on sb mpol */
        }
 }
 
index bbd396a..54f28bd 100644 (file)
@@ -597,7 +597,7 @@ static void balance_dirty_pages(struct address_space *mapping,
            (!laptop_mode && ((global_page_state(NR_FILE_DIRTY)
                               + global_page_state(NR_UNSTABLE_NFS))
                                          > background_thresh)))
-               bdi_start_writeback(bdi, NULL, 0);
+               bdi_start_background_writeback(bdi);
 }
 
 void set_page_dirty_balance(struct page *page, int page_mkwrite)
@@ -705,9 +705,8 @@ void laptop_mode_timer_fn(unsigned long data)
         * We want to write everything out, not just down to the dirty
         * threshold
         */
-
        if (bdi_has_dirty_io(&q->backing_dev_info))
-               bdi_start_writeback(&q->backing_dev_info, NULL, nr_pages);
+               bdi_start_writeback(&q->backing_dev_info, nr_pages);
 }
 
 /*
index dc3435e..711745f 100644 (file)
@@ -193,7 +193,7 @@ static void sig_handler(int sig)
 
 static void sig_atexit(void)
 {
-       if (child_pid != -1)
+       if (child_pid > 0)
                kill(child_pid, SIGTERM);
 
        if (signr == -1)
index 1f08f00..2fbf6a4 100644 (file)
@@ -538,8 +538,10 @@ int event__process_task(event_t *self, struct perf_session *session)
        dump_printf("(%d:%d):(%d:%d)\n", self->fork.pid, self->fork.tid,
                    self->fork.ppid, self->fork.ptid);
 
-       if (self->header.type == PERF_RECORD_EXIT)
+       if (self->header.type == PERF_RECORD_EXIT) {
+               perf_session__remove_thread(session, thread);
                return 0;
+       }
 
        if (thread == NULL || parent == NULL ||
            thread__fork(thread, parent) < 0) {
index cf182ca..7537ca1 100644 (file)
@@ -43,6 +43,9 @@ struct ui_progress *ui_progress__new(const char *title, u64 total)
 
        if (self != NULL) {
                int cols;
+
+               if (use_browser <= 0)   
+                       return self;
                newtGetScreenSize(&cols, NULL);
                cols -= 4;
                newtCenteredWindow(cols, 1, title);
@@ -67,14 +70,22 @@ out_free_self:
 
 void ui_progress__update(struct ui_progress *self, u64 curr)
 {
+       /*
+        * FIXME: We should have a per UI backend way of showing progress,
+        * stdio will just show a percentage as NN%, etc.
+        */
+       if (use_browser <= 0)
+               return;
        newtScaleSet(self->scale, curr);
        newtRefresh();
 }
 
 void ui_progress__delete(struct ui_progress *self)
 {
-       newtFormDestroy(self->form);
-       newtPopWindow();
+       if (use_browser > 0) {
+               newtFormDestroy(self->form);
+               newtPopWindow();
+       }
        free(self);
 }
 
index 8f83a18..c422cd6 100644 (file)
@@ -90,6 +90,7 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc
 
        memcpy(self->filename, filename, len);
        self->threads = RB_ROOT;
+       INIT_LIST_HEAD(&self->dead_threads);
        self->hists_tree = RB_ROOT;
        self->last_match = NULL;
        self->mmap_window = 32;
@@ -131,6 +132,16 @@ void perf_session__delete(struct perf_session *self)
        free(self);
 }
 
+void perf_session__remove_thread(struct perf_session *self, struct thread *th)
+{
+       rb_erase(&th->rb_node, &self->threads);
+       /*
+        * We may have references to this thread, for instance in some hist_entry
+        * instances, so just move them to a separate list.
+        */
+       list_add_tail(&th->node, &self->dead_threads);
+}
+
 static bool symbol__match_parent_regex(struct symbol *sym)
 {
        if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0))
index 55c6881..9fa0fc2 100644 (file)
@@ -26,6 +26,7 @@ struct perf_session {
        unsigned long           size;
        unsigned long           mmap_window;
        struct rb_root          threads;
+       struct list_head        dead_threads;
        struct thread           *last_match;
        struct machine          host_machine;
        struct rb_root          machines;
@@ -99,6 +100,7 @@ int perf_session__create_kernel_maps(struct perf_session *self);
 
 int do_read(int fd, void *buf, size_t size);
 void perf_session__update_sample_type(struct perf_session *self);
+void perf_session__remove_thread(struct perf_session *self, struct thread *th);
 
 static inline
 struct machine *perf_session__find_host_machine(struct perf_session *self)
index 1dfd9ff..ee6bbcf 100644 (file)
@@ -6,7 +6,10 @@
 #include "symbol.h"
 
 struct thread {
-       struct rb_node          rb_node;
+       union {
+               struct rb_node   rb_node;
+               struct list_head node;
+       };
        struct map_groups       mg;
        pid_t                   pid;
        char                    shortname[3];