]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
Merge commit 'v2.6.35-rc4' into perf/core
authorIngo Molnar <mingo@elte.hu>
Mon, 5 Jul 2010 06:30:55 +0000 (08:30 +0200)
committerIngo Molnar <mingo@elte.hu>
Mon, 5 Jul 2010 06:30:58 +0000 (08:30 +0200)
Merge reason: Pick up the latest perf fixes

Signed-off-by: Ingo Molnar <mingo@elte.hu>
179 files changed:
Documentation/watchdog/watchdog-parameters.txt
MAINTAINERS
Makefile
arch/arm/Kconfig
arch/arm/include/asm/mach/udc_pxa2xx.h
arch/arm/include/asm/processor.h
arch/arm/kernel/perf_event.c
arch/arm/mach-mx3/mach-mx31lilly.c
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-pxa/mioa701.c
arch/arm/mach-pxa/z2.c
arch/arm/mach-realview/Kconfig
arch/arm/mach-realview/include/mach/barriers.h [new file with mode: 0644]
arch/arm/mach-realview/realview_eb.c
arch/arm/mach-realview/realview_pb1176.c
arch/arm/mach-realview/realview_pb11mp.c
arch/arm/mach-realview/realview_pba8.c
arch/arm/mach-realview/realview_pbx.c
arch/arm/mach-vexpress/ct-ca9x4.c
arch/arm/mm/Kconfig
arch/arm/mm/cache-v6.S
arch/arm/mm/dma-mapping.c
arch/arm/plat-omap/dmtimer.c
arch/arm/plat-omap/gpio.c
arch/arm/plat-omap/iovmm.c
arch/arm/plat-pxa/Makefile
arch/ia64/mm/tlb.c
arch/um/os-Linux/mem.c
arch/x86/kernel/cpu/perf_event_amd.c
arch/x86/kernel/traps.c
block/blk-core.c
block/cfq-iosched.c
block/cfq.h [new file with mode: 0644]
drivers/acpi/apei/erst.c
drivers/ata/ahci.c
drivers/ata/ata_generic.c
drivers/ata/libahci.c
drivers/block/cciss_scsi.c
drivers/block/cpqarray.c
drivers/block/drbd/drbd_main.c
drivers/block/drbd/drbd_nl.c
drivers/char/agp/generic.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/cpuidle/governors/menu.c
drivers/dma/ppc4xx/adma.c
drivers/edac/amd64_edac.c
drivers/edac/i7core_edac.c
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/i915/dvo_tfp410.c
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/evergreen_cs.c
drivers/gpu/drm/radeon/evergreend.h
drivers/gpu/drm/radeon/r100.c
drivers/gpu/drm/radeon/r200.c
drivers/gpu/drm/radeon/r300.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_asic.c
drivers/gpu/drm/radeon/radeon_bios.c
drivers/gpu/drm/radeon/radeon_combios.c
drivers/gpu/drm/radeon/radeon_cursor.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_encoders.c
drivers/gpu/drm/radeon/radeon_legacy_encoders.c
drivers/gpu/drm/radeon/radeon_mode.h
drivers/gpu/drm/radeon/radeon_pm.c
drivers/gpu/drm/radeon/reg_srcs/evergreen
drivers/gpu/drm/radeon/rs690.c
drivers/gpu/drm/radeon/rv770.c
drivers/gpu/drm/ttm/ttm_page_alloc.c
drivers/power/z2_battery.c
drivers/rtc/rtc-ds1307.c
drivers/serial/cpm_uart/cpm_uart_core.c
drivers/staging/batman-adv/bat_sysfs.c
drivers/staging/batman-adv/device.c
drivers/staging/comedi/drivers/adl_pci9111.c
drivers/staging/comedi/drivers/cb_pcidda.c
drivers/staging/hv/channel_mgmt.c
drivers/staging/hv/hv_utils.c
drivers/staging/hv/vmbus.h
drivers/staging/hv/vmbus_drv.c
drivers/staging/mrst-touchscreen/intel-mid-touch.c
drivers/staging/rt2860/usb_main_dev.c
drivers/staging/rtl8187se/r8180_core.c
drivers/staging/rtl8192su/r8192U_core.c
drivers/staging/rtl8192u/r8192U_core.c
drivers/staging/usbip/usbip_common.c
drivers/staging/wlags49_h2/wl_enc.c
drivers/staging/wlags49_h2/wl_sysfs.h
drivers/usb/core/driver.c
drivers/usb/core/message.c
drivers/usb/gadget/f_eem.c
drivers/usb/gadget/f_mass_storage.c
drivers/usb/gadget/g_ffs.c
drivers/usb/gadget/printer.c
drivers/usb/gadget/s3c2410_udc.c
drivers/usb/gadget/u_serial.c
drivers/usb/host/ehci-mxc.c
drivers/usb/host/isp1362-hcd.c
drivers/usb/host/r8a66597-hcd.c
drivers/usb/host/xhci-ring.c
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_core.h
drivers/usb/musb/musbhsdma.c
drivers/usb/otg/ulpi.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/usb/serial/qcserial.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/proc/task_nommu.c
fs/super.c
fs/sysv/ialloc.c
fs/ubifs/budget.c
fs/xfs/linux-2.6/xfs_export.c
fs/xfs/linux-2.6/xfs_ioctl.c
fs/xfs/linux-2.6/xfs_ioctl32.c
fs/xfs/quota/xfs_qm.c
fs/xfs/quota/xfs_qm_syscalls.c
fs/xfs/xfs_dfrag.c
fs/xfs/xfs_ialloc.c
fs/xfs/xfs_iget.c
fs/xfs/xfs_inode.c
fs/xfs/xfs_inode.h
fs/xfs/xfs_itable.c
fs/xfs/xfs_itable.h
fs/xfs/xfs_log_recover.c
fs/xfs/xfs_mount.c
fs/xfs/xfs_rtalloc.c
fs/xfs/xfs_trans_inode.c
fs/xfs/xfs_vnodeops.c
include/linux/agp_backend.h
include/linux/backing-dev.h
include/linux/compiler-gcc.h
include/linux/compiler-gcc4.h
include/linux/drbd.h
include/linux/dynamic_debug.h
include/linux/fb.h
include/linux/list.h
include/linux/pci_ids.h
include/linux/sched.h
init/main.c
kernel/futex.c
kernel/kexec.c
kernel/module.c
kernel/sched.c
kernel/time/tick-sched.c
lib/dynamic_debug.c
lib/genalloc.c
mm/memcontrol.c
mm/mempolicy.c
mm/page-writeback.c
scripts/package/Makefile
scripts/setlocalversion
tools/perf/util/thread.c

index 41c95cc1dc1ff990f27d9b83647770d65a171745..17ddd822b4563c2cdf80ba80f422db5b4b35e002 100644 (file)
@@ -125,6 +125,11 @@ ibmasr:
 nowayout: Watchdog cannot be stopped once started
        (default=kernel config parameter)
 -------------------------------------------------
+imx2_wdt:
+timeout: Watchdog timeout in seconds (default 60 s)
+nowayout: Watchdog cannot be stopped once started
+       (default=kernel config parameter)
+-------------------------------------------------
 indydog:
 nowayout: Watchdog cannot be stopped once started
        (default=kernel config parameter)
index f9730fa0b24c242b130dd91068fcc896ca236f54..9f90de2e00f85b7edc2bac01fbc2a169f6f59c9b 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.*
@@ -2109,11 +2111,18 @@ F:      drivers/edac/i5000_edac.c
 
 EDAC-I5400
 M:     Mauro Carvalho Chehab <mchehab@redhat.com>
-L:     bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
+L:     linux-edac@vger.kernel.org
 W:     bluesmoke.sourceforge.net
 S:     Maintained
 F:     drivers/edac/i5400_edac.c
 
+EDAC-I7CORE
+M:     Mauro Carvalho Chehab <mchehab@redhat.com>
+L:     linux-edac@vger.kernel.org
+W:     bluesmoke.sourceforge.net
+S:     Maintained
+F:     drivers/edac/i7core_edac.c linux/edac_mce.h drivers/edac/edac_mce.c
+
 EDAC-I82975X
 M:     Ranganathan Desikan <ravi@jetztechnologies.com>
 M:     "Arvind R." <arvind@jetztechnologies.com>
@@ -3373,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
@@ -4621,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 f6c206a5b01a7ccdf9e0493782253d1673b55308..0a20cd413b02cc6f4a0aee32076583178461b5b1 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 35
-EXTRAVERSION = -rc3
+EXTRAVERSION = -rc4
 NAME = Sheep on Meth
 
 # *DOCUMENTATION*
@@ -883,80 +883,10 @@ PHONY += $(vmlinux-dirs)
 $(vmlinux-dirs): prepare scripts
        $(Q)$(MAKE) $(build)=$@
 
-# Build the kernel release string
-#
-# The KERNELRELEASE value built here is stored in the file
-# include/config/kernel.release, and is used when executing several
-# make targets, such as "make install" or "make modules_install."
-#
-# The eventual kernel release string consists of the following fields,
-# shown in a hierarchical format to show how smaller parts are concatenated
-# to form the larger and final value, with values coming from places like
-# the Makefile, kernel config options, make command line options and/or
-# SCM tag information.
-#
-#      $(KERNELVERSION)
-#        $(VERSION)                    eg, 2
-#        $(PATCHLEVEL)                 eg, 6
-#        $(SUBLEVEL)                   eg, 18
-#        $(EXTRAVERSION)               eg, -rc6
-#      $(localver-full)
-#        $(localver)
-#          localversion*               (files without backups, containing '~')
-#          $(CONFIG_LOCALVERSION)      (from kernel config setting)
-#        $(LOCALVERSION)               (from make command line, if provided)
-#        $(localver-extra)
-#          $(scm-identifier)           (unique SCM tag, if one exists)
-#            ./scripts/setlocalversion (only with CONFIG_LOCALVERSION_AUTO)
-#            .scmversion               (only with CONFIG_LOCALVERSION_AUTO)
-#          +                           (only without CONFIG_LOCALVERSION_AUTO
-#                                       and without LOCALVERSION= and
-#                                       repository is at non-tagged commit)
-#
-# For kernels without CONFIG_LOCALVERSION_AUTO compiled from an SCM that has
-# been revised beyond a tagged commit, `+' is appended to the version string
-# when not overridden by using "make LOCALVERSION=".  This indicates that the
-# kernel is not a vanilla release version and has been modified.
-
-pattern = ".*/localversion[^~]*"
-string  = $(shell cat /dev/null \
-          `find $(objtree) $(srctree) -maxdepth 1 -regex $(pattern) | sort -u`)
-
-localver = $(subst $(space),, $(string) \
-                             $(patsubst "%",%,$(CONFIG_LOCALVERSION)))
-
-# scripts/setlocalversion is called to create a unique identifier if the source
-# is managed by a known SCM and the repository has been revised since the last
-# tagged (release) commit.  The format of the identifier is determined by the
-# SCM's implementation.
-#
-# .scmversion is used when generating rpm packages so we do not loose
-# the version information from the SCM when we do the build of the kernel
-# from the copied source
-ifeq ($(wildcard .scmversion),)
-        scm-identifier = $(shell $(CONFIG_SHELL) \
-                         $(srctree)/scripts/setlocalversion $(srctree))
-else
-        scm-identifier = $(shell cat .scmversion 2> /dev/null)
-endif
-
-ifdef CONFIG_LOCALVERSION_AUTO
-       localver-extra = $(scm-identifier)
-else
-       ifneq ($(scm-identifier),)
-               ifeq ("$(origin LOCALVERSION)", "undefined")
-                       localver-extra = +
-               endif
-       endif
-endif
-
-localver-full = $(localver)$(LOCALVERSION)$(localver-extra)
-
 # Store (new) KERNELRELASE string in include/config/kernel.release
-kernelrelease = $(KERNELVERSION)$(localver-full)
 include/config/kernel.release: include/config/auto.conf FORCE
        $(Q)rm -f $@
-       $(Q)echo $(kernelrelease) > $@
+       $(Q)echo "$(KERNELVERSION)$$($(CONFIG_SHELL) scripts/setlocalversion $(srctree))" > $@
 
 
 # Things we need to do before we recursively start building the kernel
index 1f254bd6c937ece2e6d6a6b1040d954cc923cd7a..98922f7d2d1236dd7fd29fa404447b46189c0222 100644 (file)
@@ -955,7 +955,8 @@ config XSCALE_PMU
        default y
 
 config CPU_HAS_PMU
-       depends on CPU_V6 || CPU_V7 || XSCALE_PMU
+       depends on (CPU_V6 || CPU_V7 || XSCALE_PMU) && \
+                  (!ARCH_OMAP3 || OMAP3_EMU)
        default y
        bool
 
index f3eabf1ecec333643273d9f797a7afd70cc4894d..833306ee9e7fec2059c457e7e107d586198c4de6 100644 (file)
@@ -21,8 +21,8 @@ struct pxa2xx_udc_mach_info {
         * here.  Note that sometimes the signals go through inverters...
         */
        bool    gpio_vbus_inverted;
-       u16     gpio_vbus;                      /* high == vbus present */
+       int     gpio_vbus;                      /* high == vbus present */
        bool    gpio_pullup_inverted;
-       u16     gpio_pullup;                    /* high == pullup activated */
+       int     gpio_pullup;                    /* high == pullup activated */
 };
 
index 6a89567ffc5bc49a326c0a56747aced339fd53db..7bed3daf83b8f27547ac608d574ffb00de8d1871 100644 (file)
@@ -91,7 +91,11 @@ extern void release_thread(struct task_struct *);
 
 unsigned long get_wchan(struct task_struct *p);
 
+#if __LINUX_ARM_ARCH__ == 6
+#define cpu_relax()                    smp_mb()
+#else
 #define cpu_relax()                    barrier()
+#endif
 
 /*
  * Create a new kernel thread
index 5b7cfafc0720550e7bab62eb9d1ab2e912029fb4..417c392ddf1cb55066fa5f99e83e77514bd89901 100644 (file)
@@ -201,7 +201,7 @@ armpmu_event_update(struct perf_event *event,
 {
        int shift = 64 - 32;
        s64 prev_raw_count, new_raw_count;
-       s64 delta;
+       u64 delta;
 
 again:
        prev_raw_count = local64_read(&hwc->prev_count);
index d3d5877c750ef2c3ca427a7a2d445a820c500a7c..b2c7f512070fe450b710db83da53ce439a2a2bd4 100644 (file)
@@ -115,6 +115,8 @@ static struct platform_device physmap_flash_device = {
 
 /* USB */
 
+#if defined(CONFIG_USB_ULPI)
+
 #define USB_PAD_CFG (PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST | PAD_CTL_HYS_CMOS | \
                        PAD_CTL_ODE_CMOS | PAD_CTL_100K_PU)
 
@@ -244,10 +246,20 @@ static struct mxc_usbh_platform_data usbh2_pdata = {
        .flags  = MXC_EHCI_POWER_PINS_ENABLED,
 };
 
-static struct platform_device *devices[] __initdata = {
-       &smsc91x_device,
-       &physmap_flash_device,
-};
+static void lilly1131_usb_init(void)
+{
+       usbotg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
+                               USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
+       usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
+                               USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
+
+       mxc_register_device(&mxc_usbh1, &usbh1_pdata);
+       mxc_register_device(&mxc_usbh2, &usbh2_pdata);
+}
+
+#else
+static inline void lilly1131_usb_init(void) {}
+#endif /* CONFIG_USB_ULPI */
 
 /* SPI */
 
@@ -279,6 +291,11 @@ static struct spi_board_info mc13783_dev __initdata = {
        .platform_data  = &mc13783_pdata,
 };
 
+static struct platform_device *devices[] __initdata = {
+       &smsc91x_device,
+       &physmap_flash_device,
+};
+
 static int mx31lilly_baseboard;
 core_param(mx31lilly_baseboard, mx31lilly_baseboard, int, 0444);
 
@@ -321,13 +338,7 @@ static void __init mx31lilly_board_init(void)
        platform_add_devices(devices, ARRAY_SIZE(devices));
 
        /* USB */
-       usbotg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-                               USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
-       usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-                               USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
-
-       mxc_register_device(&mxc_usbh1, &usbh1_pdata);
-       mxc_register_device(&mxc_usbh2, &usbh2_pdata);
+       lilly1131_usb_init();
 }
 
 static void __init mx31lilly_timer_init(void)
index f848ba8dbc16916d82ec3c6cae2a436d7c849265..a04cffd691c55995812365aa78c373e7950d0b2c 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 02804224517b26abb7460f1ebd98ff5c266e0dea..e10db7a90cb270f5f833cd1b9076bd7b6cb38356 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 95c9a5f774e13f1d123bd2a0968dd418e92bafd4..b7a4133267d80b73cd0ff59fe8d339efae649839 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 2e967716cc3fd27bb368951b6ee0599897b2b490..b88737fd6cfe7a434f6254e81dad7f90d8e3cd1a 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 c68f799e83c57bb53fb20c10fb0610fdbc53e8fc..d72d1ac303338e23bed5abe38392e9aed6e0183b 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 d60db87dde0872e32fddae50a0454e4bdfc6161f..fa6a708b40997feb7ae0296c04d91d1afa8930c9 100644 (file)
@@ -697,7 +697,7 @@ static struct i2c_board_info __initdata mioa701_pi2c_devices[] = {
 };
 
 /* Board I2C devices. */
-static struct i2c_board_info __initdata mioa701_i2c_devices[] = {
+static struct i2c_board_info mioa701_i2c_devices[] = {
        {
                I2C_BOARD_INFO("mt9m111", 0x5d),
        },
index f5d1ae3db3a46783b4421bf818d50ca4eed1e690..d303c6929d3282803e3b547e9509e7b7aab3b177 100644 (file)
@@ -3,8 +3,9 @@
  *
  *  Support for the Zipit Z2 Handheld device.
  *
- *  Author:    Ken McGuire
- *  Created:   Jan 25, 2009
+ *  Copyright (C) 2009-2010 Marek Vasut <marek.vasut@gmail.com>
+ *
+ *  Based on research and code by: Ken McGuire
  *  Based on mainstone.c as modified for the Zipit Z2.
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -157,21 +158,14 @@ static struct mtd_partition z2_flash_parts[] = {
        {
                .name   = "U-Boot Bootloader",
                .offset = 0x0,
-               .size   = 0x20000,
-       },
-       {
-               .name   = "Linux Kernel",
-               .offset = 0x20000,
-               .size   = 0x220000,
-       },
-       {
-               .name   = "Filesystem",
-               .offset = 0x240000,
-               .size   = 0x5b0000,
-       },
-       {
+               .size   = 0x40000,
+       }, {
                .name   = "U-Boot Environment",
-               .offset = 0x7f0000,
+               .offset = 0x40000,
+               .size   = 0x60000,
+       }, {
+               .name   = "Flash",
+               .offset = 0x60000,
                .size   = MTDPART_SIZ_FULL,
        },
 };
index ee5e392430e87e4f45721320e33172f68e933e56..b4575ae9648ee7220ffb40d31359e8f12b7cecbb 100644 (file)
@@ -18,6 +18,7 @@ config REALVIEW_EB_ARM11MP
        bool "Support ARM11MPCore tile"
        depends on MACH_REALVIEW_EB
        select CPU_V6
+       select ARCH_HAS_BARRIERS if SMP
        help
          Enable support for the ARM11MPCore tile on the Realview platform.
 
@@ -35,6 +36,7 @@ config MACH_REALVIEW_PB11MP
        select CPU_V6
        select ARM_GIC
        select HAVE_PATA_PLATFORM
+       select ARCH_HAS_BARRIERS if SMP
        help
          Include support for the ARM(R) RealView MPCore Platform Baseboard.
          PB11MPCore is a platform with an on-board ARM11MPCore and has
diff --git a/arch/arm/mach-realview/include/mach/barriers.h b/arch/arm/mach-realview/include/mach/barriers.h
new file mode 100644 (file)
index 0000000..0c5d749
--- /dev/null
@@ -0,0 +1,8 @@
+/*
+ * Barriers redefined for RealView ARM11MPCore platforms with L220 cache
+ * controller to work around hardware errata causing the outer_sync()
+ * operation to deadlock the system.
+ */
+#define mb()           dsb()
+#define rmb()          dmb()
+#define wmb()          mb()
index 422ccd70d5f532066eb7ce4f855be243563db32d..4425018fab828c864e662dfb4bfd5db369a76a15 100644 (file)
@@ -32,6 +32,7 @@
 #include <asm/leds.h>
 #include <asm/mach-types.h>
 #include <asm/pmu.h>
+#include <asm/pgtable.h>
 #include <asm/hardware/gic.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/localtimer.h>
@@ -457,7 +458,7 @@ static void __init realview_eb_init(void)
 
 MACHINE_START(REALVIEW_EB, "ARM-RealView EB")
        /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-       .phys_io        = REALVIEW_EB_UART0_BASE,
+       .phys_io        = REALVIEW_EB_UART0_BASE & SECTION_MASK,
        .io_pg_offst    = (IO_ADDRESS(REALVIEW_EB_UART0_BASE) >> 18) & 0xfffc,
        .boot_params    = PHYS_OFFSET + 0x00000100,
        .fixup          = realview_fixup,
index 96568ebfa2bb1b5b3c76b3990bbb4c7cea66252f..099a1f125cf8f6c10b1720ccdcee7623ff5a73ad 100644 (file)
@@ -32,6 +32,7 @@
 #include <asm/leds.h>
 #include <asm/mach-types.h>
 #include <asm/pmu.h>
+#include <asm/pgtable.h>
 #include <asm/hardware/gic.h>
 #include <asm/hardware/cache-l2x0.h>
 
@@ -351,7 +352,7 @@ static void __init realview_pb1176_init(void)
 
 MACHINE_START(REALVIEW_PB1176, "ARM-RealView PB1176")
        /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-       .phys_io        = REALVIEW_PB1176_UART0_BASE,
+       .phys_io        = REALVIEW_PB1176_UART0_BASE & SECTION_MASK,
        .io_pg_offst    = (IO_ADDRESS(REALVIEW_PB1176_UART0_BASE) >> 18) & 0xfffc,
        .boot_params    = PHYS_OFFSET + 0x00000100,
        .fixup          = realview_pb1176_fixup,
index 7fbefbbebaf06e488eae02f5521b4cc7d66b54f7..0e07a5ccb75f56de33bec477f242d93d88bca448 100644 (file)
@@ -32,6 +32,7 @@
 #include <asm/leds.h>
 #include <asm/mach-types.h>
 #include <asm/pmu.h>
+#include <asm/pgtable.h>
 #include <asm/hardware/gic.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/localtimer.h>
@@ -373,7 +374,7 @@ static void __init realview_pb11mp_init(void)
 
 MACHINE_START(REALVIEW_PB11MP, "ARM-RealView PB11MPCore")
        /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-       .phys_io        = REALVIEW_PB11MP_UART0_BASE,
+       .phys_io        = REALVIEW_PB11MP_UART0_BASE & SECTION_MASK,
        .io_pg_offst    = (IO_ADDRESS(REALVIEW_PB11MP_UART0_BASE) >> 18) & 0xfffc,
        .boot_params    = PHYS_OFFSET + 0x00000100,
        .fixup          = realview_fixup,
index d3c113b3dfcecef2e32b3788624e2fbd97d26b1d..ac2f06f1ca500e9bd26603b21ba6c6badf046e11 100644 (file)
@@ -31,6 +31,7 @@
 #include <asm/leds.h>
 #include <asm/mach-types.h>
 #include <asm/pmu.h>
+#include <asm/pgtable.h>
 #include <asm/hardware/gic.h>
 
 #include <asm/mach/arch.h>
@@ -323,7 +324,7 @@ static void __init realview_pba8_init(void)
 
 MACHINE_START(REALVIEW_PBA8, "ARM-RealView PB-A8")
        /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-       .phys_io        = REALVIEW_PBA8_UART0_BASE,
+       .phys_io        = REALVIEW_PBA8_UART0_BASE & SECTION_MASK,
        .io_pg_offst    = (IO_ADDRESS(REALVIEW_PBA8_UART0_BASE) >> 18) & 0xfffc,
        .boot_params    = PHYS_OFFSET + 0x00000100,
        .fixup          = realview_fixup,
index a235ba30996ba42341c9c2d28e724d67f34e54af..08fd683adc4ced929eb255fd8da2e3b733850a87 100644 (file)
@@ -31,6 +31,7 @@
 #include <asm/mach-types.h>
 #include <asm/pmu.h>
 #include <asm/smp_twd.h>
+#include <asm/pgtable.h>
 #include <asm/hardware/gic.h>
 #include <asm/hardware/cache-l2x0.h>
 
@@ -409,7 +410,7 @@ static void __init realview_pbx_init(void)
 
 MACHINE_START(REALVIEW_PBX, "ARM-RealView PBX")
        /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-       .phys_io        = REALVIEW_PBX_UART0_BASE,
+       .phys_io        = REALVIEW_PBX_UART0_BASE & SECTION_MASK,
        .io_pg_offst    = (IO_ADDRESS(REALVIEW_PBX_UART0_BASE) >> 18) & 0xfffc,
        .boot_params    = PHYS_OFFSET + 0x00000100,
        .fixup          = realview_pbx_fixup,
index 9b11eedba65fc4163cb33929addc2bf4e6784cbf..6353459bb5671bc2623377529b9a6dfcd5db4a8f 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/amba/clcd.h>
 
 #include <asm/clkdev.h>
+#include <asm/pgtable.h>
 #include <asm/hardware/arm_timer.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/hardware/gic.h>
@@ -236,7 +237,7 @@ static void ct_ca9x4_init(void)
 }
 
 MACHINE_START(VEXPRESS, "ARM-Versatile Express CA9x4")
-       .phys_io        = V2M_UART0,
+       .phys_io        = V2M_UART0 & SECTION_MASK,
        .io_pg_offst    = (__MMIO_P2V(V2M_UART0) >> 18) & 0xfffc,
        .boot_params    = PHYS_OFFSET + 0x00000100,
        .map_io         = ct_ca9x4_map_io,
index 346ae14824a5ea96365f6e9b66fa8f78cd8cd4bc..101105e5261070118f8039c5ecbcde350792f38f 100644 (file)
@@ -735,6 +735,25 @@ config NEEDS_SYSCALL_FOR_CMPXCHG
          Forget about fast user space cmpxchg support.
          It is just not possible.
 
+config DMA_CACHE_RWFO
+       bool "Enable read/write for ownership DMA cache maintenance"
+       depends on CPU_V6 && SMP
+       default y
+       help
+         The Snoop Control Unit on ARM11MPCore does not detect the
+         cache maintenance operations and the dma_{map,unmap}_area()
+         functions may leave stale cache entries on other CPUs. By
+         enabling this option, Read or Write For Ownership in the ARMv6
+         DMA cache maintenance functions is performed. These LDR/STR
+         instructions change the cache line state to shared or modified
+         so that the cache operation has the desired effect.
+
+         Note that the workaround is only valid on processors that do
+         not perform speculative loads into the D-cache. For such
+         processors, if cache maintenance operations are not broadcast
+         in hardware, other workarounds are needed (e.g. cache
+         maintenance broadcasting in software via FIQ).
+
 config OUTER_CACHE
        bool
 
@@ -794,6 +813,8 @@ config ARM_L1_CACHE_SHIFT
 
 config ARM_DMA_MEM_BUFFERABLE
        bool "Use non-cacheable memory for DMA" if CPU_V6 && !CPU_V7
+       depends on !(MACH_REALVIEW_PB1176 || REALVIEW_EB_ARM11MP || \
+                    MACH_REALVIEW_PB11MP)
        default y if CPU_V6 || CPU_V7
        help
          Historically, the kernel has used strongly ordered mappings to
index e46ecd8471383102b52e5c6475873f3f4bdfc65d..86aa689ef1aa2f6b53cf84a717427df11a25ce1e 100644 (file)
@@ -211,8 +211,9 @@ v6_dma_inv_range:
        mcrne   p15, 0, r1, c7, c15, 1          @ clean & invalidate unified line
 #endif
 1:
-#ifdef CONFIG_SMP
-       str     r0, [r0]                        @ write for ownership
+#ifdef CONFIG_DMA_CACHE_RWFO
+       ldr     r2, [r0]                        @ read for ownership
+       str     r2, [r0]                        @ write for ownership
 #endif
 #ifdef HARVARD_CACHE
        mcr     p15, 0, r0, c7, c6, 1           @ invalidate D line
@@ -234,7 +235,7 @@ v6_dma_inv_range:
 v6_dma_clean_range:
        bic     r0, r0, #D_CACHE_LINE_SIZE - 1
 1:
-#ifdef CONFIG_SMP
+#ifdef CONFIG_DMA_CACHE_RWFO
        ldr     r2, [r0]                        @ read for ownership
 #endif
 #ifdef HARVARD_CACHE
@@ -257,7 +258,7 @@ v6_dma_clean_range:
 ENTRY(v6_dma_flush_range)
        bic     r0, r0, #D_CACHE_LINE_SIZE - 1
 1:
-#ifdef CONFIG_SMP
+#ifdef CONFIG_DMA_CACHE_RWFO
        ldr     r2, [r0]                        @ read for ownership
        str     r2, [r0]                        @ write for ownership
 #endif
@@ -283,9 +284,13 @@ ENTRY(v6_dma_map_area)
        add     r1, r1, r0
        teq     r2, #DMA_FROM_DEVICE
        beq     v6_dma_inv_range
+#ifndef CONFIG_DMA_CACHE_RWFO
+       b       v6_dma_clean_range
+#else
        teq     r2, #DMA_TO_DEVICE
        beq     v6_dma_clean_range
        b       v6_dma_flush_range
+#endif
 ENDPROC(v6_dma_map_area)
 
 /*
@@ -295,6 +300,11 @@ ENDPROC(v6_dma_map_area)
  *     - dir   - DMA direction
  */
 ENTRY(v6_dma_unmap_area)
+#ifndef CONFIG_DMA_CACHE_RWFO
+       add     r1, r1, r0
+       teq     r2, #DMA_TO_DEVICE
+       bne     v6_dma_inv_range
+#endif
        mov     pc, lr
 ENDPROC(v6_dma_unmap_area)
 
index 13fa536d82e695ff69b6e74f8e95853cf7199ede..9e7742f0a102fe5c7d091134391db81d93d71726 100644 (file)
 #include <asm/tlbflush.h>
 #include <asm/sizes.h>
 
-/* Sanity check size */
-#if (CONSISTENT_DMA_SIZE % SZ_2M)
-#error "CONSISTENT_DMA_SIZE must be multiple of 2MiB"
-#endif
-
-#define CONSISTENT_OFFSET(x)   (((unsigned long)(x) - CONSISTENT_BASE) >> PAGE_SHIFT)
-#define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PGDIR_SHIFT)
-#define NUM_CONSISTENT_PTES (CONSISTENT_DMA_SIZE >> PGDIR_SHIFT)
-
 static u64 get_coherent_dma_mask(struct device *dev)
 {
        u64 mask = ISA_DMA_THRESHOLD;
@@ -123,6 +114,15 @@ static void __dma_free_buffer(struct page *page, size_t size)
 }
 
 #ifdef CONFIG_MMU
+/* Sanity check size */
+#if (CONSISTENT_DMA_SIZE % SZ_2M)
+#error "CONSISTENT_DMA_SIZE must be multiple of 2MiB"
+#endif
+
+#define CONSISTENT_OFFSET(x)   (((unsigned long)(x) - CONSISTENT_BASE) >> PAGE_SHIFT)
+#define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PGDIR_SHIFT)
+#define NUM_CONSISTENT_PTES (CONSISTENT_DMA_SIZE >> PGDIR_SHIFT)
+
 /*
  * These are the page tables (2MB each) covering uncached, DMA consistent allocations
  */
index c64875f11fac9d937f79d5805d682bc0f4cb9bbe..44bafdab2dceaa94d7d6facbcfd422b2f65b660c 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 393e9219a5b68afe61f6416c3fac531cc188cefc..9b7e3545f32552e1cdb7d4bfc0b9cc6331de8b0f 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 e43983ba59c5eb77ac61caa3a2ebaca83b50416c..8ce0de247c71fc7b59863a6722036ef011238240 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);
 
index 6187edfbcb777a13a11eb5eea273abb4901b5c7d..a17cc0c6a6b0117f1a590f3d773bf10c69e2581a 100644 (file)
@@ -2,8 +2,9 @@
 # Makefile for code common across different PXA processor families
 #
 
-obj-y  := dma.o pmu.o
+obj-y  := dma.o
 
+obj-$(CONFIG_ARCH_PXA)         += pmu.o
 obj-$(CONFIG_GENERIC_GPIO)     += gpio.o
 obj-$(CONFIG_PXA3xx)           += mfp.o
 obj-$(CONFIG_ARCH_MMP)         += mfp.o
index 5dfd916e9ea610db1a047e0462d6398082bde63e..7b3cdc6c6d9147d3edd422ab31b97adf90e46f6c 100644 (file)
@@ -121,7 +121,7 @@ static inline void down_spin(struct spinaphore *ss)
        ia64_invala();
 
        for (;;) {
-               asm volatile ("ld4.c.nc %0=[%1]" : "=r"(serve) : "r"(&ss->serve) : "memory");
+               asm volatile ("ld8.c.nc %0=[%1]" : "=r"(serve) : "r"(&ss->serve) : "memory");
                if (time_before(t, serve))
                        return;
                cpu_relax();
index 93a11d7edfa0505a7acfd9bd99a0266aec97f933..e696144d2be3ddb23ba952fdd17ea8fdf923036c 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 611df11ba15e7f9145e49f2fa2c7e61b1371d77c..c2897b7b4a3b1c7a6cfe4fe7e70b3d7378432d4c 100644 (file)
@@ -102,8 +102,8 @@ static const u64 amd_perfmon_event_map[] =
   [PERF_COUNT_HW_INSTRUCTIONS]         = 0x00c0,
   [PERF_COUNT_HW_CACHE_REFERENCES]     = 0x0080,
   [PERF_COUNT_HW_CACHE_MISSES]         = 0x0081,
-  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]  = 0x00c4,
-  [PERF_COUNT_HW_BRANCH_MISSES]                = 0x00c5,
+  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]  = 0x00c2,
+  [PERF_COUNT_HW_BRANCH_MISSES]                = 0x00c3,
 };
 
 static u64 amd_pmu_event_map(int hw_event)
index 142d70c74b027c31512c02dafea1e510d686a2fb..725ef4d17cd5922289b24e515c8b030e86cf6c18 100644 (file)
@@ -526,6 +526,7 @@ asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs)
 dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code)
 {
        struct task_struct *tsk = current;
+       int user_icebp = 0;
        unsigned long dr6;
        int si_code;
 
@@ -534,6 +535,14 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code)
        /* Filter out all the reserved bits which are preset to 1 */
        dr6 &= ~DR6_RESERVED;
 
+       /*
+        * If dr6 has no reason to give us about the origin of this trap,
+        * then it's very likely the result of an icebp/int01 trap.
+        * User wants a sigtrap for that.
+        */
+       if (!dr6 && user_mode(regs))
+               user_icebp = 1;
+
        /* Catch kmemcheck conditions first of all! */
        if ((dr6 & DR_STEP) && kmemcheck_trap(regs))
                return;
@@ -575,7 +584,7 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code)
                regs->flags &= ~X86_EFLAGS_TF;
        }
        si_code = get_si_code(tsk->thread.debugreg6);
-       if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS))
+       if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS) || user_icebp)
                send_sigtrap(tsk, regs, error_code, si_code);
        preempt_conditional_cli(regs);
 
index f84cce42fc58da2dc0bc48186cbd9f6bd1d7dfc3..f0640d7f800f7164c5b04a59791410a029a48cc4 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 5ff4f4850e717ddb319423e9678e0e44cd7f265c..7982b830db58df900fb679919c81edfc0ee34689 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 2ebc39115507e8662db312c7c3921d2a2ee248fd..864dd46c346fd33cc9c96d830d39719053c6354e 100644 (file)
@@ -781,7 +781,7 @@ static int __init erst_init(void)
        status = acpi_get_table(ACPI_SIG_ERST, 0,
                                (struct acpi_table_header **)&erst_tab);
        if (status == AE_NOT_FOUND) {
-               pr_err(ERST_PFX "Table is not found!\n");
+               pr_info(ERST_PFX "Table is not found!\n");
                goto err;
        } else if (ACPI_FAILURE(status)) {
                const char *msg = acpi_format_exception(status);
index 8ca16f54e1ed6648365f90e935eedc9140372c98..f2522534ae6327a94678afb080eafc5dac2d9f4c 100644 (file)
@@ -1053,6 +1053,16 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable)
                return -ENODEV;
 
+       /*
+        * For some reason, MCP89 on MacBook 7,1 doesn't work with
+        * ahci, use ata_generic instead.
+        */
+       if (pdev->vendor == PCI_VENDOR_ID_NVIDIA &&
+           pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA &&
+           pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE &&
+           pdev->subsystem_device == 0xcb89)
+               return -ENODEV;
+
        /* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode.
         * At the moment, we can only use the AHCI mode. Let the users know
         * that for SAS drives they're out of luck.
index 573158a9668da008482f4c85c23cef78f4f47ad3..7107a6929deb8816121afb4ce1048bcedc2c588b 100644 (file)
  *     A generic parallel ATA driver using libata
  */
 
+enum {
+       ATA_GEN_CLASS_MATCH             = (1 << 0),
+       ATA_GEN_FORCE_DMA               = (1 << 1),
+};
+
 /**
  *     generic_set_mode        -       mode setting
  *     @link: link to set up
 static int generic_set_mode(struct ata_link *link, struct ata_device **unused)
 {
        struct ata_port *ap = link->ap;
+       const struct pci_device_id *id = ap->host->private_data;
        int dma_enabled = 0;
        struct ata_device *dev;
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 
-       /* Bits 5 and 6 indicate if DMA is active on master/slave */
-       if (ap->ioaddr.bmdma_addr)
+       if (id->driver_data & ATA_GEN_FORCE_DMA) {
+               dma_enabled = 0xff;
+       } else if (ap->ioaddr.bmdma_addr) {
+               /* Bits 5 and 6 indicate if DMA is active on master/slave */
                dma_enabled = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+       }
 
        if (pdev->vendor == PCI_VENDOR_ID_CENATEK)
                dma_enabled = 0xFF;
@@ -126,7 +135,7 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id
        const struct ata_port_info *ppi[] = { &info, NULL };
 
        /* Don't use the generic entry unless instructed to do so */
-       if (id->driver_data == 1 && all_generic_ide == 0)
+       if ((id->driver_data & ATA_GEN_CLASS_MATCH) && all_generic_ide == 0)
                return -ENODEV;
 
        /* Devices that need care */
@@ -155,7 +164,7 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id
                        return rc;
                pcim_pin_device(dev);
        }
-       return ata_pci_bmdma_init_one(dev, ppi, &generic_sht, NULL, 0);
+       return ata_pci_bmdma_init_one(dev, ppi, &generic_sht, (void *)id, 0);
 }
 
 static struct pci_device_id ata_generic[] = {
@@ -167,7 +176,15 @@ static struct pci_device_id ata_generic[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_HINT,   PCI_DEVICE_ID_HINT_VXPROII_IDE), },
        { PCI_DEVICE(PCI_VENDOR_ID_VIA,    PCI_DEVICE_ID_VIA_82C561), },
        { PCI_DEVICE(PCI_VENDOR_ID_OPTI,   PCI_DEVICE_ID_OPTI_82C558), },
-       { PCI_DEVICE(PCI_VENDOR_ID_CENATEK,PCI_DEVICE_ID_CENATEK_IDE), },
+       { PCI_DEVICE(PCI_VENDOR_ID_CENATEK,PCI_DEVICE_ID_CENATEK_IDE),
+         .driver_data = ATA_GEN_FORCE_DMA },
+       /*
+        * For some reason, MCP89 on MacBook 7,1 doesn't work with
+        * ahci, use ata_generic instead.
+        */
+       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA,
+         PCI_VENDOR_ID_APPLE, 0xcb89,
+         .driver_data = ATA_GEN_FORCE_DMA },
 #if !defined(CONFIG_PATA_TOSHIBA) && !defined(CONFIG_PATA_TOSHIBA_MODULE)
        { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), },
        { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2),  },
@@ -175,7 +192,8 @@ static struct pci_device_id ata_generic[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_5),  },
 #endif 
        /* Must come last. If you add entries adjust this table appropriately */
-       { PCI_ANY_ID,           PCI_ANY_ID,                        PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 1},
+       { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL),
+         .driver_data = ATA_GEN_CLASS_MATCH },
        { 0, },
 };
 
index 261f86d102e8ba520105dfd10efac3930a9d7a12..81e772a94d59857187fda27dbfe7702469fb590f 100644 (file)
@@ -324,6 +324,7 @@ static ssize_t ahci_store_em_buffer(struct device *dev,
        struct ahci_host_priv *hpriv = ap->host->private_data;
        void __iomem *mmio = hpriv->mmio;
        void __iomem *em_mmio = mmio + hpriv->em_loc;
+       const unsigned char *msg_buf = buf;
        u32 em_ctl, msg;
        unsigned long flags;
        int i;
@@ -343,8 +344,8 @@ static ssize_t ahci_store_em_buffer(struct device *dev,
        }
 
        for (i = 0; i < size; i += 4) {
-               msg = buf[i] | buf[i + 1] << 8 |
-                     buf[i + 2] << 16 | buf[i + 3] << 24;
+               msg = msg_buf[i] | msg_buf[i + 1] << 8 |
+                     msg_buf[i + 2] << 16 | msg_buf[i + 3] << 24;
                writel(msg, em_mmio + i);
        }
 
index 3381505c8a6c309c7838cb7d0a4daff7e3e162e7..72dae92f3cab89770e0c43abd6e7b01aa554b62c 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 91d11631cec96a523f8f7f9504ce6405edba920a..abb4ec6690fcc7b45f96bf8067d96c9e83999ebe 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 6b077f93acc620eaf40fa85599dbe83745779c28..7258c95e895e3c3ff7c91bdc3660154d55061413 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 632e3245d1bb2a2f74d01394a4fb55862e30b226..2151f18b21deb27e0d5ecbd369180f12333b3479 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 4b51982fd23a23a2c2683bfc3dd87dd1abe6af24..d2abf51439836383fd9b03612a44bdf1779448fa 100644 (file)
@@ -97,20 +97,18 @@ EXPORT_SYMBOL(agp_flush_chipset);
 void agp_alloc_page_array(size_t size, struct agp_memory *mem)
 {
        mem->pages = NULL;
-       mem->vmalloc_flag = false;
 
        if (size <= 2*PAGE_SIZE)
-               mem->pages = kmalloc(size, GFP_KERNEL | __GFP_NORETRY);
+               mem->pages = kmalloc(size, GFP_KERNEL | __GFP_NOWARN);
        if (mem->pages == NULL) {
                mem->pages = vmalloc(size);
-               mem->vmalloc_flag = true;
        }
 }
 EXPORT_SYMBOL(agp_alloc_page_array);
 
 void agp_free_page_array(struct agp_memory *mem)
 {
-       if (mem->vmalloc_flag) {
+       if (is_vmalloc_addr(mem->pages)) {
                vfree(mem->pages);
        } else {
                kfree(mem->pages);
index 35603dd4e6c5276911dec0b3a11464a152beb8a5..094bdc355b1fe753c003d30277fbf9a038281444 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 52ff8aa63f8449b04d5bcd046b028e23dcf6d68b..1b128702d300bc5a07ba7ec09f03ec83f3b11b43 100644 (file)
@@ -143,7 +143,7 @@ static inline int which_bucket(unsigned int duration)
         * This allows us to calculate
         * E(duration)|iowait
         */
-       if (nr_iowait_cpu())
+       if (nr_iowait_cpu(smp_processor_id()))
                bucket = BUCKETS/2;
 
        if (duration < 10)
@@ -175,7 +175,7 @@ static inline int performance_multiplier(void)
        mult += 2 * get_loadavg();
 
        /* for IO wait tasks (per cpu!) we add 5x each */
-       mult += 10 * nr_iowait_cpu();
+       mult += 10 * nr_iowait_cpu(smp_processor_id());
 
        return mult;
 }
index 5a22ca6927e5da6bd10b1abe04736218e0b31459..7c3747902a37ad29f7a1031dd7039c69556d3ea3 100644 (file)
@@ -4257,10 +4257,12 @@ static int ppc440spe_adma_setup_irqs(struct ppc440spe_adma_device *adev,
                                     struct ppc440spe_adma_chan *chan,
                                     int *initcode)
 {
+       struct of_device *ofdev;
        struct device_node *np;
        int ret;
 
-       np = container_of(adev->dev, struct of_device, dev)->node;
+       ofdev = container_of(adev->dev, struct of_device, dev);
+       np = ofdev->dev.of_node;
        if (adev->id != PPC440SPE_XOR_ID) {
                adev->err_irq = irq_of_parse_and_map(np, 1);
                if (adev->err_irq == NO_IRQ) {
index cf17dbb8014f75bb0f5109c0008dda9f7c2a27cd..ac9f7985096db06f83302ada4bed9601c7287657 100644 (file)
@@ -1958,20 +1958,20 @@ static int get_channel_from_ecc_syndrome(struct mem_ctl_info *mci, u16 syndrome)
        u32 value = 0;
        int err_sym = 0;
 
-       amd64_read_pci_cfg(pvt->misc_f3_ctl, 0x180, &value);
+       if (boot_cpu_data.x86 == 0x10) {
 
-       /* F3x180[EccSymbolSize]=1, x8 symbols */
-       if (boot_cpu_data.x86 == 0x10 &&
-           boot_cpu_data.x86_model > 7 &&
-           value & BIT(25)) {
-               err_sym = decode_syndrome(syndrome, x8_vectors,
-                                         ARRAY_SIZE(x8_vectors), 8);
-               return map_err_sym_to_channel(err_sym, 8);
-       } else {
-               err_sym = decode_syndrome(syndrome, x4_vectors,
-                                         ARRAY_SIZE(x4_vectors), 4);
-               return map_err_sym_to_channel(err_sym, 4);
+               amd64_read_pci_cfg(pvt->misc_f3_ctl, 0x180, &value);
+
+               /* F3x180[EccSymbolSize]=1 => x8 symbols */
+               if (boot_cpu_data.x86_model > 7 &&
+                   value & BIT(25)) {
+                       err_sym = decode_syndrome(syndrome, x8_vectors,
+                                                 ARRAY_SIZE(x8_vectors), 8);
+                       return map_err_sym_to_channel(err_sym, 8);
+               }
        }
+       err_sym = decode_syndrome(syndrome, x4_vectors, ARRAY_SIZE(x4_vectors), 4);
+       return map_err_sym_to_channel(err_sym, 4);
 }
 
 /*
index 6b8b7b41ec5f8bbad42647792417ce64f433d117..cc9357da0e3442ad9666a415f80b3dd29321b6a0 100644 (file)
@@ -1233,10 +1233,28 @@ static void __init i7core_xeon_pci_fixup(struct pci_id_table *table)
                        for (i = 0; i < MAX_SOCKET_BUSES; i++)
                                pcibios_scan_specific_bus(255-i);
                }
+               pci_dev_put(pdev);
                table++;
        }
 }
 
+static unsigned i7core_pci_lastbus(void)
+{
+       int last_bus = 0, bus;
+       struct pci_bus *b = NULL;
+
+       while ((b = pci_find_next_bus(b)) != NULL) {
+               bus = b->number;
+               debugf0("Found bus %d\n", bus);
+               if (bus > last_bus)
+                       last_bus = bus;
+       }
+
+       debugf0("Last bus %d\n", last_bus);
+
+       return last_bus;
+}
+
 /*
  *     i7core_get_devices      Find and perform 'get' operation on the MCH's
  *                     device/functions we want to reference for this driver
@@ -1244,7 +1262,8 @@ static void __init i7core_xeon_pci_fixup(struct pci_id_table *table)
  *                     Need to 'get' device 16 func 1 and func 2
  */
 int i7core_get_onedevice(struct pci_dev **prev, int devno,
-                        struct pci_id_descr *dev_descr, unsigned n_devs)
+                        struct pci_id_descr *dev_descr, unsigned n_devs,
+                        unsigned last_bus)
 {
        struct i7core_dev *i7core_dev;
 
@@ -1291,10 +1310,7 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno,
        }
        bus = pdev->bus->number;
 
-       if (bus == 0x3f)
-               socket = 0;
-       else
-               socket = 255 - bus;
+       socket = last_bus - bus;
 
        i7core_dev = get_i7core_dev(socket);
        if (!i7core_dev) {
@@ -1358,17 +1374,21 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno,
 
 static int i7core_get_devices(struct pci_id_table *table)
 {
-       int i, rc;
+       int i, rc, last_bus;
        struct pci_dev *pdev = NULL;
        struct pci_id_descr *dev_descr;
 
+       last_bus = i7core_pci_lastbus();
+
        while (table && table->descr) {
                dev_descr = table->descr;
                for (i = 0; i < table->n_devs; i++) {
                        pdev = NULL;
                        do {
-                               rc = i7core_get_onedevice(&pdev, i, &dev_descr[i],
-                                                         table->n_devs);
+                               rc = i7core_get_onedevice(&pdev, i,
+                                                         &dev_descr[i],
+                                                         table->n_devs,
+                                                         last_bus);
                                if (rc < 0) {
                                        if (i == 0) {
                                                i = table->n_devs;
@@ -1927,21 +1947,26 @@ fail:
  *             0 for FOUND a device
  *             < 0 for error code
  */
+
+static int probed = 0;
+
 static int __devinit i7core_probe(struct pci_dev *pdev,
                                  const struct pci_device_id *id)
 {
-       int dev_idx = id->driver_data;
        int rc;
        struct i7core_dev *i7core_dev;
 
+       /* get the pci devices we want to reserve for our use */
+       mutex_lock(&i7core_edac_lock);
+
        /*
         * All memory controllers are allocated at the first pass.
         */
-       if (unlikely(dev_idx >= 1))
+       if (unlikely(probed >= 1)) {
+               mutex_unlock(&i7core_edac_lock);
                return -EINVAL;
-
-       /* get the pci devices we want to reserve for our use */
-       mutex_lock(&i7core_edac_lock);
+       }
+       probed++;
 
        rc = i7core_get_devices(pci_dev_table);
        if (unlikely(rc < 0))
@@ -2013,6 +2038,8 @@ static void __devexit i7core_remove(struct pci_dev *pdev)
                                      i7core_dev->socket);
                }
        }
+       probed--;
+
        mutex_unlock(&i7core_edac_lock);
 }
 
index 724038dab4caa72db78309def86ec448f259407d..7face915b963fe62a6940beccde71058a23111c4 100644 (file)
@@ -1,5 +1,5 @@
 #
-# GPIO infrastructure and expanders
+# platform-neutral GPIO infrastructure and expanders
 #
 
 config ARCH_WANT_OPTIONAL_GPIOLIB
index 51c3cdd41b5aac95514b41e58c105208ba278e60..e53dcff49b4f650765c4f1f1017a45664feb3ccc 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 08c4c926e65f58e1b28fabcb1bb30c3ac183f7b5..1f2cc6b09623cd8b3d2677ecf11277b678bba891 100644 (file)
@@ -146,7 +146,7 @@ static bool drm_fb_helper_connector_parse_command_line(struct drm_fb_helper_conn
                                cvt = 1;
                        break;
                case 'R':
-                       if (!cvt)
+                       if (cvt)
                                rb = 1;
                        break;
                case 'm':
@@ -1024,11 +1024,18 @@ static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_conne
        }
 
 create_mode:
-       mode = drm_cvt_mode(fb_helper_conn->connector->dev, cmdline_mode->xres,
-                           cmdline_mode->yres,
-                           cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60,
-                           cmdline_mode->rb, cmdline_mode->interlace,
-                           cmdline_mode->margins);
+       if (cmdline_mode->cvt)
+               mode = drm_cvt_mode(fb_helper_conn->connector->dev,
+                                   cmdline_mode->xres, cmdline_mode->yres,
+                                   cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60,
+                                   cmdline_mode->rb, cmdline_mode->interlace,
+                                   cmdline_mode->margins);
+       else
+               mode = drm_gtf_mode(fb_helper_conn->connector->dev,
+                                   cmdline_mode->xres, cmdline_mode->yres,
+                                   cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60,
+                                   cmdline_mode->interlace,
+                                   cmdline_mode->margins);
        drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
        list_add(&mode->head, &fb_helper_conn->connector->modes);
        return mode;
index 66c697bc9b2274abb8701ffa63a42b1782bb3297..56f66426207f0a1a293dcb073360985d328fd85e 100644 (file)
@@ -208,7 +208,7 @@ static enum drm_connector_status tfp410_detect(struct intel_dvo_device *dvo)
        uint8_t ctl2;
 
        if (tfp410_readb(dvo, TFP410_CTL_2, &ctl2)) {
-               if (ctl2 & TFP410_CTL_2_HTPLG)
+               if (ctl2 & TFP410_CTL_2_RSEN)
                        ret = connector_status_connected;
                else
                        ret = connector_status_disconnected;
index 52510ad8b25d3e89f7f920af0a65978512b28209..aee83fa178f6a6dc60c7273eaaae29b43dbe000d 100644 (file)
@@ -620,7 +620,7 @@ static int i915_sr_status(struct seq_file *m, void *unused)
        drm_i915_private_t *dev_priv = dev->dev_private;
        bool sr_enabled = false;
 
-       if (IS_I965G(dev) || IS_I945G(dev) || IS_I945GM(dev))
+       if (IS_I965GM(dev) || IS_I945G(dev) || IS_I945GM(dev))
                sr_enabled = I915_READ(FW_BLC_SELF) & FW_BLC_SELF_EN;
        else if (IS_I915GM(dev))
                sr_enabled = I915_READ(INSTPM) & INSTPM_SELF_EN;
index 59a2bf8592ece73672c403ef3744c4bdeb715c04..f00c5ae9556ccb47358ce1f5267dd9cc5cb17a21 100644 (file)
@@ -128,9 +128,11 @@ static int i915_dma_cleanup(struct drm_device * dev)
        if (dev->irq_enabled)
                drm_irq_uninstall(dev);
 
+       mutex_lock(&dev->struct_mutex);
        intel_cleanup_ring_buffer(dev, &dev_priv->render_ring);
        if (HAS_BSD(dev))
                intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring);
+       mutex_unlock(&dev->struct_mutex);
 
        /* Clear the HWS virtual address at teardown */
        if (I915_NEED_GFX_HWS(dev))
@@ -1229,7 +1231,7 @@ static void i915_warn_stolen(struct drm_device *dev)
 static void i915_setup_compression(struct drm_device *dev, int size)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_mm_node *compressed_fb, *compressed_llb;
+       struct drm_mm_node *compressed_fb, *uninitialized_var(compressed_llb);
        unsigned long cfb_base;
        unsigned long ll_base = 0;
 
@@ -1410,6 +1412,10 @@ static int i915_load_modeset_init(struct drm_device *dev,
        if (ret)
                goto cleanup_vga_client;
 
+       /* IIR "flip pending" bit means done if this bit is set */
+       if (IS_GEN3(dev) && (I915_READ(ECOSKPD) & ECO_FLIP_DONE))
+               dev_priv->flip_pending_is_done = true;
+
        intel_modeset_init(dev);
 
        ret = drm_irq_install(dev);
index 2765831598479b8d9e0bb72712d3ca71ce9a95e2..d147ab2f5bfcabfc8bc82cd5ccdea93064fa4cf0 100644 (file)
@@ -596,6 +596,7 @@ typedef struct drm_i915_private {
        struct drm_crtc *plane_to_crtc_mapping[2];
        struct drm_crtc *pipe_to_crtc_mapping[2];
        wait_queue_head_t pending_flip_queue;
+       bool flip_pending_is_done;
 
        /* Reclocking support */
        bool render_reclock_avail;
@@ -1076,7 +1077,7 @@ extern int intel_trans_dp_port_sel (struct drm_crtc *crtc);
        drm_i915_private_t *dev_priv = dev->dev_private;                \
        if (I915_VERBOSE)                                               \
                DRM_DEBUG("   BEGIN_LP_RING %x\n", (int)(n));           \
-       intel_ring_begin(dev, &dev_priv->render_ring, 4*(n));           \
+       intel_ring_begin(dev, &dev_priv->render_ring, (n));             \
 } while (0)
 
 
index 9ded3dae6c87105cdd7acaa65d5548aeb90dfee3..074385882ccfe721ff5630b9e825950c6479af7e 100644 (file)
@@ -2239,7 +2239,7 @@ i915_gem_object_get_pages(struct drm_gem_object *obj,
        mapping = inode->i_mapping;
        for (i = 0; i < page_count; i++) {
                page = read_cache_page_gfp(mapping, i,
-                                          mapping_gfp_mask (mapping) |
+                                          GFP_HIGHUSER |
                                           __GFP_COLD |
                                           gfpmask);
                if (IS_ERR(page))
index 2479be001e405c821345750d5b384ec41c79759c..dba53d4b9fb3a11b7b76194e0fa6aec97211e966 100644 (file)
@@ -940,22 +940,30 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
                if (HAS_BSD(dev) && (iir & I915_BSD_USER_INTERRUPT))
                        DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue);
 
-               if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT)
+               if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) {
                        intel_prepare_page_flip(dev, 0);
+                       if (dev_priv->flip_pending_is_done)
+                               intel_finish_page_flip_plane(dev, 0);
+               }
 
-               if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT)
+               if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT) {
                        intel_prepare_page_flip(dev, 1);
+                       if (dev_priv->flip_pending_is_done)
+                               intel_finish_page_flip_plane(dev, 1);
+               }
 
                if (pipea_stats & vblank_status) {
                        vblank++;
                        drm_handle_vblank(dev, 0);
-                       intel_finish_page_flip(dev, 0);
+                       if (!dev_priv->flip_pending_is_done)
+                               intel_finish_page_flip(dev, 0);
                }
 
                if (pipeb_stats & vblank_status) {
                        vblank++;
                        drm_handle_vblank(dev, 1);
-                       intel_finish_page_flip(dev, 1);
+                       if (!dev_priv->flip_pending_is_done)
+                               intel_finish_page_flip(dev, 1);
                }
 
                if ((pipea_stats & I915_LEGACY_BLC_EVENT_STATUS) ||
@@ -1387,29 +1395,10 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
        dev_priv->pipestat[1] = 0;
 
        if (I915_HAS_HOTPLUG(dev)) {
-               u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN);
-
-               /* Note HDMI and DP share bits */
-               if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS)
-                       hotplug_en |= HDMIB_HOTPLUG_INT_EN;
-               if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS)
-                       hotplug_en |= HDMIC_HOTPLUG_INT_EN;
-               if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS)
-                       hotplug_en |= HDMID_HOTPLUG_INT_EN;
-               if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS)
-                       hotplug_en |= SDVOC_HOTPLUG_INT_EN;
-               if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS)
-                       hotplug_en |= SDVOB_HOTPLUG_INT_EN;
-               if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS)
-                       hotplug_en |= CRT_HOTPLUG_INT_EN;
-               /* Ignore TV since it's buggy */
-
-               I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
-
                /* Enable in IER... */
                enable_mask |= I915_DISPLAY_PORT_INTERRUPT;
                /* and unmask in IMR */
-               i915_enable_irq(dev_priv, I915_DISPLAY_PORT_INTERRUPT);
+               dev_priv->irq_mask_reg &= ~I915_DISPLAY_PORT_INTERRUPT;
        }
 
        /*
@@ -1427,16 +1416,41 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
        }
        I915_WRITE(EMR, error_mask);
 
-       /* Disable pipe interrupt enables, clear pending pipe status */
-       I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff);
-       I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff);
-       /* Clear pending interrupt status */
-       I915_WRITE(IIR, I915_READ(IIR));
-
-       I915_WRITE(IER, enable_mask);
        I915_WRITE(IMR, dev_priv->irq_mask_reg);
+       I915_WRITE(IER, enable_mask);
        (void) I915_READ(IER);
 
+       if (I915_HAS_HOTPLUG(dev)) {
+               u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN);
+
+               /* Note HDMI and DP share bits */
+               if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS)
+                       hotplug_en |= HDMIB_HOTPLUG_INT_EN;
+               if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS)
+                       hotplug_en |= HDMIC_HOTPLUG_INT_EN;
+               if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS)
+                       hotplug_en |= HDMID_HOTPLUG_INT_EN;
+               if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS)
+                       hotplug_en |= SDVOC_HOTPLUG_INT_EN;
+               if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS)
+                       hotplug_en |= SDVOB_HOTPLUG_INT_EN;
+               if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) {
+                       hotplug_en |= CRT_HOTPLUG_INT_EN;
+
+                       /* Programming the CRT detection parameters tends
+                          to generate a spurious hotplug event about three
+                          seconds later.  So just do it once.
+                       */
+                       if (IS_G4X(dev))
+                               hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
+                       hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
+               }
+
+               /* Ignore TV since it's buggy */
+
+               I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
+       }
+
        opregion_enable_asle(dev);
 
        return 0;
index 64b0a3afd92bcd8cdb11c71ba455edbad156396e..150400f405346de04d5693bfedc91d36f0a85a2c 100644 (file)
 #define   MI_OVERLAY_OFF       (0x2<<21)
 #define MI_LOAD_SCAN_LINES_INCL MI_INSTR(0x12, 0)
 #define MI_DISPLAY_FLIP                MI_INSTR(0x14, 2)
+#define MI_DISPLAY_FLIP_I915   MI_INSTR(0x14, 1)
 #define   MI_DISPLAY_FLIP_PLANE(n) ((n) << 20)
 #define MI_STORE_DWORD_IMM     MI_INSTR(0x20, 1)
 #define   MI_MEM_VIRTUAL       (1 << 22) /* 965+ only */
 #define   CM0_RC_OP_FLUSH_DISABLE (1<<0)
 #define BB_ADDR                0x02140 /* 8 bytes */
 #define GFX_FLSH_CNTL  0x02170 /* 915+ only */
+#define ECOSKPD                0x021d0
+#define   ECO_GATING_CX_ONLY   (1<<3)
+#define   ECO_FLIP_DONE                (1<<0)
 
 /* GEN6 interrupt control */
 #define GEN6_RENDER_HWSTAM     0x2098
 #define CRT_HOTPLUG_DETECT_DELAY_2G            (1 << 4)
 #define CRT_HOTPLUG_DETECT_VOLTAGE_325MV       (0 << 2)
 #define CRT_HOTPLUG_DETECT_VOLTAGE_475MV       (1 << 2)
-#define CRT_HOTPLUG_MASK                       (0x3fc) /* Bits 9-2 */
 
 #define PORT_HOTPLUG_STAT      0x61114
 #define   HDMIB_HOTPLUG_INT_STATUS             (1 << 29)
index 22ff38455731ae00b5b5446d5472391935d6c5bf..ee0732b222a1a5e6e9e6fe0ae50c001867006298 100644 (file)
@@ -234,14 +234,8 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
        else
                tries = 1;
        hotplug_en = orig = I915_READ(PORT_HOTPLUG_EN);
-       hotplug_en &= CRT_HOTPLUG_MASK;
        hotplug_en |= CRT_HOTPLUG_FORCE_DETECT;
 
-       if (IS_G4X(dev))
-               hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
-
-       hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
-
        for (i = 0; i < tries ; i++) {
                unsigned long timeout;
                /* turn on the FORCE_DETECT */
index cc8131ff319f3f0d243a15c0ddd924c1a93b8147..68dcf36e2793f51fa42aeecb9b67037aa8515205 100644 (file)
@@ -2970,11 +2970,13 @@ static void i965_update_wm(struct drm_device *dev, int planea_clock,
                if (srwm < 0)
                        srwm = 1;
                srwm &= 0x3f;
-               I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN);
+               if (IS_I965GM(dev))
+                       I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN);
        } else {
                /* Turn off self refresh if both pipes are enabled */
-               I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF)
-                                       & ~FW_BLC_SELF_EN);
+               if (IS_I965GM(dev))
+                       I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF)
+                                  & ~FW_BLC_SELF_EN);
        }
 
        DRM_DEBUG_KMS("Setting FIFO watermarks - A: 8, B: 8, C: 8, SR %d\n",
@@ -4483,6 +4485,7 @@ static void intel_idle_update(struct work_struct *work)
        struct drm_device *dev = dev_priv->dev;
        struct drm_crtc *crtc;
        struct intel_crtc *intel_crtc;
+       int enabled = 0;
 
        if (!i915_powersave)
                return;
@@ -4491,21 +4494,22 @@ static void intel_idle_update(struct work_struct *work)
 
        i915_update_gfx_val(dev_priv);
 
-       if (IS_I945G(dev) || IS_I945GM(dev)) {
-               DRM_DEBUG_DRIVER("enable memory self refresh on 945\n");
-               I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN);
-       }
-
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                /* Skip inactive CRTCs */
                if (!crtc->fb)
                        continue;
 
+               enabled++;
                intel_crtc = to_intel_crtc(crtc);
                if (!intel_crtc->busy)
                        intel_decrease_pllclock(crtc);
        }
 
+       if ((enabled == 1) && (IS_I945G(dev) || IS_I945GM(dev))) {
+               DRM_DEBUG_DRIVER("enable memory self refresh on 945\n");
+               I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN);
+       }
+
        mutex_unlock(&dev->struct_mutex);
 }
 
@@ -4601,10 +4605,10 @@ static void intel_unpin_work_fn(struct work_struct *__work)
        kfree(work);
 }
 
-void intel_finish_page_flip(struct drm_device *dev, int pipe)
+static void do_intel_finish_page_flip(struct drm_device *dev,
+                                     struct drm_crtc *crtc)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
-       struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct intel_unpin_work *work;
        struct drm_i915_gem_object *obj_priv;
@@ -4648,6 +4652,22 @@ void intel_finish_page_flip(struct drm_device *dev, int pipe)
        schedule_work(&work->work);
 }
 
+void intel_finish_page_flip(struct drm_device *dev, int pipe)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
+
+       do_intel_finish_page_flip(dev, crtc);
+}
+
+void intel_finish_page_flip_plane(struct drm_device *dev, int plane)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_crtc *crtc = dev_priv->plane_to_crtc_mapping[plane];
+
+       do_intel_finish_page_flip(dev, crtc);
+}
+
 void intel_prepare_page_flip(struct drm_device *dev, int plane)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
@@ -4678,6 +4698,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
        unsigned long flags;
        int pipesrc_reg = (intel_crtc->pipe == 0) ? PIPEASRC : PIPEBSRC;
        int ret, pipesrc;
+       u32 flip_mask;
 
        work = kzalloc(sizeof *work, GFP_KERNEL);
        if (work == NULL)
@@ -4731,15 +4752,28 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
        atomic_inc(&obj_priv->pending_flip);
        work->pending_flip_obj = obj;
 
+       if (intel_crtc->plane)
+               flip_mask = I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT;
+       else
+               flip_mask = I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT;
+
+       /* Wait for any previous flip to finish */
+       if (IS_GEN3(dev))
+               while (I915_READ(ISR) & flip_mask)
+                       ;
+
        BEGIN_LP_RING(4);
-       OUT_RING(MI_DISPLAY_FLIP |
-                MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
-       OUT_RING(fb->pitch);
        if (IS_I965G(dev)) {
+               OUT_RING(MI_DISPLAY_FLIP |
+                        MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
+               OUT_RING(fb->pitch);
                OUT_RING(obj_priv->gtt_offset | obj_priv->tiling_mode);
                pipesrc = I915_READ(pipesrc_reg); 
                OUT_RING(pipesrc & 0x0fff0fff);
        } else {
+               OUT_RING(MI_DISPLAY_FLIP_I915 |
+                        MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
+               OUT_RING(fb->pitch);
                OUT_RING(obj_priv->gtt_offset);
                OUT_RING(MI_NOOP);
        }
index 49b54f05d3cfcb767b28c0caecc8523ea6deabed..1aac59e83bff0c45a0da94e1f083d40d9e30b396 100644 (file)
@@ -135,6 +135,12 @@ intel_dp_link_required(struct drm_device *dev,
                return pixel_clock * 3;
 }
 
+static int
+intel_dp_max_data_rate(int max_link_clock, int max_lanes)
+{
+       return (max_link_clock * max_lanes * 8) / 10;
+}
+
 static int
 intel_dp_mode_valid(struct drm_connector *connector,
                    struct drm_display_mode *mode)
@@ -144,8 +150,11 @@ intel_dp_mode_valid(struct drm_connector *connector,
        int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_encoder));
        int max_lanes = intel_dp_max_lane_count(intel_encoder);
 
-       if (intel_dp_link_required(connector->dev, intel_encoder, mode->clock)
-                       > max_link_clock * max_lanes)
+       /* only refuse the mode on non eDP since we have seen some wierd eDP panels
+          which are outside spec tolerances but somehow work by magic */
+       if (!IS_eDP(intel_encoder) &&
+           (intel_dp_link_required(connector->dev, intel_encoder, mode->clock)
+            > intel_dp_max_data_rate(max_link_clock, max_lanes)))
                return MODE_CLOCK_HIGH;
 
        if (mode->clock < 10000)
@@ -506,7 +515,7 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
 
        for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
                for (clock = 0; clock <= max_clock; clock++) {
-                       int link_avail = intel_dp_link_clock(bws[clock]) * lane_count;
+                       int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count);
 
                        if (intel_dp_link_required(encoder->dev, intel_encoder, mode->clock)
                                        <= link_avail) {
@@ -521,6 +530,18 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
                        }
                }
        }
+
+       if (IS_eDP(intel_encoder)) {
+               /* okay we failed just pick the highest */
+               dp_priv->lane_count = max_lane_count;
+               dp_priv->link_bw = bws[max_clock];
+               adjusted_mode->clock = intel_dp_link_clock(dp_priv->link_bw);
+               DRM_DEBUG_KMS("Force picking display port link bw %02x lane "
+                             "count %d clock %d\n",
+                             dp_priv->link_bw, dp_priv->lane_count,
+                             adjusted_mode->clock);
+               return true;
+       }
        return false;
 }
 
index df931f7876652e7af0b8f6f480fdbd05ce3596ae..72206f37c4fb847c8d32d80c5c893fd3a68a5faa 100644 (file)
@@ -224,6 +224,7 @@ extern void intel_fbdev_fini(struct drm_device *dev);
 
 extern void intel_prepare_page_flip(struct drm_device *dev, int plane);
 extern void intel_finish_page_flip(struct drm_device *dev, int pipe);
+extern void intel_finish_page_flip_plane(struct drm_device *dev, int plane);
 
 extern void intel_setup_overlay(struct drm_device *dev);
 extern void intel_cleanup_overlay(struct drm_device *dev);
index 6a1accd83aecd9171f719deca33a04e078534585..31df55f0a0a7950a0e59ebce556fc30cde35b891 100644 (file)
@@ -983,8 +983,8 @@ void intel_lvds_init(struct drm_device *dev)
 
        drm_connector_attach_property(&intel_connector->base,
                                      dev->mode_config.scaling_mode_property,
-                                     DRM_MODE_SCALE_FULLSCREEN);
-       lvds_priv->fitting_mode = DRM_MODE_SCALE_FULLSCREEN;
+                                     DRM_MODE_SCALE_ASPECT);
+       lvds_priv->fitting_mode = DRM_MODE_SCALE_ASPECT;
        /*
         * LVDS discovery:
         * 1) check for EDID on DDC
index cea4f1a8709ec775913fda1bab17d7868c944be4..26362f8495a8791ed8d0d75657faa4b6c1af346e 100644 (file)
@@ -94,7 +94,7 @@ render_ring_flush(struct drm_device *dev,
 #if WATCH_EXEC
                DRM_INFO("%s: queue flush %08x to ring\n", __func__, cmd);
 #endif
-               intel_ring_begin(dev, ring, 8);
+               intel_ring_begin(dev, ring, 2);
                intel_ring_emit(dev, ring, cmd);
                intel_ring_emit(dev, ring, MI_NOOP);
                intel_ring_advance(dev, ring);
@@ -358,7 +358,7 @@ bsd_ring_flush(struct drm_device *dev,
                u32     invalidate_domains,
                u32     flush_domains)
 {
-       intel_ring_begin(dev, ring, 8);
+       intel_ring_begin(dev, ring, 2);
        intel_ring_emit(dev, ring, MI_FLUSH);
        intel_ring_emit(dev, ring, MI_NOOP);
        intel_ring_advance(dev, ring);
@@ -687,6 +687,7 @@ int intel_wrap_ring_buffer(struct drm_device *dev,
                *virt++ = MI_NOOP;
 
        ring->tail = 0;
+       ring->space = ring->head - 8;
 
        return 0;
 }
@@ -721,8 +722,9 @@ int intel_wait_ring_buffer(struct drm_device *dev,
 }
 
 void intel_ring_begin(struct drm_device *dev,
-               struct intel_ring_buffer *ring, int n)
+               struct intel_ring_buffer *ring, int num_dwords)
 {
+       int n = 4*num_dwords;
        if (unlikely(ring->tail + n > ring->size))
                intel_wrap_ring_buffer(dev, ring);
        if (unlikely(ring->space < n))
@@ -752,7 +754,7 @@ void intel_fill_struct(struct drm_device *dev,
 {
        unsigned int *virt = ring->virtual_start + ring->tail;
        BUG_ON((len&~(4-1)) != 0);
-       intel_ring_begin(dev, ring, len);
+       intel_ring_begin(dev, ring, len/4);
        memcpy(virt, data, len);
        ring->tail += len;
        ring->tail &= ring->size - 1;
index f3f2827017ef39603bae514432f875a51472eec1..8c2d6478a2213d82637a4270b4215a676481896b 100644 (file)
@@ -498,7 +498,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
                if ((rdev->family == CHIP_RS600) ||
                    (rdev->family == CHIP_RS690) ||
                    (rdev->family == CHIP_RS740))
-                       pll->flags |= (RADEON_PLL_USE_FRAC_FB_DIV |
+                       pll->flags |= (/*RADEON_PLL_USE_FRAC_FB_DIV |*/
                                       RADEON_PLL_PREFER_CLOSEST_LOWER);
 
                if (ASIC_IS_DCE32(rdev) && mode->clock > 200000)        /* range limits??? */
index 4b6623df3b964fde76723aa8fb0f69bbdaef30a6..1caf625e472b607b92b2841f0dcf7fae44785cde 100644 (file)
@@ -607,7 +607,7 @@ static void evergreen_mc_program(struct radeon_device *rdev)
        WREG32(MC_VM_FB_LOCATION, tmp);
        WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8));
        WREG32(HDP_NONSURFACE_INFO, (2 << 7));
-       WREG32(HDP_NONSURFACE_SIZE, (rdev->mc.mc_vram_size - 1) | 0x3FF);
+       WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF);
        if (rdev->flags & RADEON_IS_AGP) {
                WREG32(MC_VM_AGP_TOP, rdev->mc.gtt_end >> 16);
                WREG32(MC_VM_AGP_BOT, rdev->mc.gtt_start >> 16);
@@ -1222,11 +1222,11 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
                ps_thread_count = 128;
 
        sq_thread_resource_mgmt = NUM_PS_THREADS(ps_thread_count);
-       sq_thread_resource_mgmt |= NUM_VS_THREADS(((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8;
-       sq_thread_resource_mgmt |= NUM_GS_THREADS(((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8;
-       sq_thread_resource_mgmt |= NUM_ES_THREADS(((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8;
-       sq_thread_resource_mgmt_2 = NUM_HS_THREADS(((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8;
-       sq_thread_resource_mgmt_2 |= NUM_LS_THREADS(((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8;
+       sq_thread_resource_mgmt |= NUM_VS_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8);
+       sq_thread_resource_mgmt |= NUM_GS_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8);
+       sq_thread_resource_mgmt |= NUM_ES_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8);
+       sq_thread_resource_mgmt_2 = NUM_HS_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8);
+       sq_thread_resource_mgmt_2 |= NUM_LS_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8);
 
        sq_stack_resource_mgmt_1 = NUM_PS_STACK_ENTRIES((rdev->config.evergreen.max_stack_entries * 1) / 6);
        sq_stack_resource_mgmt_1 |= NUM_VS_STACK_ENTRIES((rdev->config.evergreen.max_stack_entries * 1) / 6);
@@ -1260,6 +1260,9 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
        WREG32(VGT_GS_VERTEX_REUSE, 16);
        WREG32(PA_SC_LINE_STIPPLE_STATE, 0);
 
+       WREG32(VGT_VERTEX_REUSE_BLOCK_CNTL, 14);
+       WREG32(VGT_OUT_DEALLOC_CNTL, 16);
+
        WREG32(CB_PERF_CTR0_SEL_0, 0);
        WREG32(CB_PERF_CTR0_SEL_1, 0);
        WREG32(CB_PERF_CTR1_SEL_0, 0);
@@ -1269,6 +1272,26 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
        WREG32(CB_PERF_CTR3_SEL_0, 0);
        WREG32(CB_PERF_CTR3_SEL_1, 0);
 
+       /* clear render buffer base addresses */
+       WREG32(CB_COLOR0_BASE, 0);
+       WREG32(CB_COLOR1_BASE, 0);
+       WREG32(CB_COLOR2_BASE, 0);
+       WREG32(CB_COLOR3_BASE, 0);
+       WREG32(CB_COLOR4_BASE, 0);
+       WREG32(CB_COLOR5_BASE, 0);
+       WREG32(CB_COLOR6_BASE, 0);
+       WREG32(CB_COLOR7_BASE, 0);
+       WREG32(CB_COLOR8_BASE, 0);
+       WREG32(CB_COLOR9_BASE, 0);
+       WREG32(CB_COLOR10_BASE, 0);
+       WREG32(CB_COLOR11_BASE, 0);
+
+       /* set the shader const cache sizes to 0 */
+       for (i = SQ_ALU_CONST_BUFFER_SIZE_PS_0; i < 0x28200; i += 4)
+               WREG32(i, 0);
+       for (i = SQ_ALU_CONST_BUFFER_SIZE_HS_0; i < 0x29000; i += 4)
+               WREG32(i, 0);
+
        hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL);
        WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl);
 
index 64516b95089129abb1d52e893b6edf086ca9bfec..010963d4570fe1d3fcfa37926e4ad26d17d95148 100644 (file)
@@ -1197,7 +1197,7 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
                                        DRM_ERROR("bad SET_RESOURCE (tex)\n");
                                        return -EINVAL;
                                }
-                               ib[idx+1+(i*8)+3] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+                               ib[idx+1+(i*8)+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
                                if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
                                        ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
                                else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
@@ -1209,7 +1209,7 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
                                        DRM_ERROR("bad SET_RESOURCE (tex)\n");
                                        return -EINVAL;
                                }
-                               ib[idx+1+(i*8)+4] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+                               ib[idx+1+(i*8)+3] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
                                mipmap = reloc->robj;
                                r = evergreen_check_texture_resource(p,  idx+1+(i*8),
                                                texture, mipmap);
index 79683f6b4452907854d2a6fa9639bf04132a785c..a1cd621780e21bc5fdd7251c397dfc362d3c5ec3 100644 (file)
 #define SQ_GSVS_RING_OFFSET_2                          0x28930
 #define SQ_GSVS_RING_OFFSET_3                          0x28934
 
+#define SQ_ALU_CONST_BUFFER_SIZE_PS_0                  0x28140
+#define SQ_ALU_CONST_BUFFER_SIZE_HS_0                  0x28f80
+
 #define SQ_ALU_CONST_CACHE_PS_0                                0x28940
 #define SQ_ALU_CONST_CACHE_PS_1                                0x28944
 #define SQ_ALU_CONST_CACHE_PS_2                                0x28948
index cf89aa2eb28c07cb61054f43db647c5ec4ff9f59..3970e62eaab8f75582e0838e5770a7346731bff6 100644 (file)
@@ -1628,6 +1628,7 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
                case RADEON_TXFORMAT_RGB332:
                case RADEON_TXFORMAT_Y8:
                        track->textures[i].cpp = 1;
+                       track->textures[i].compress_format = R100_TRACK_COMP_NONE;
                        break;
                case RADEON_TXFORMAT_AI88:
                case RADEON_TXFORMAT_ARGB1555:
@@ -1639,12 +1640,14 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
                case RADEON_TXFORMAT_LDUDV655:
                case RADEON_TXFORMAT_DUDV88:
                        track->textures[i].cpp = 2;
+                       track->textures[i].compress_format = R100_TRACK_COMP_NONE;
                        break;
                case RADEON_TXFORMAT_ARGB8888:
                case RADEON_TXFORMAT_RGBA8888:
                case RADEON_TXFORMAT_SHADOW32:
                case RADEON_TXFORMAT_LDUDUV8888:
                        track->textures[i].cpp = 4;
+                       track->textures[i].compress_format = R100_TRACK_COMP_NONE;
                        break;
                case RADEON_TXFORMAT_DXT1:
                        track->textures[i].cpp = 1;
@@ -2604,12 +2607,6 @@ int r100_set_surface_reg(struct radeon_device *rdev, int reg,
        int surf_index = reg * 16;
        int flags = 0;
 
-       /* r100/r200 divide by 16 */
-       if (rdev->family < CHIP_R300)
-               flags = pitch / 16;
-       else
-               flags = pitch / 8;
-
        if (rdev->family <= CHIP_RS200) {
                if ((tiling_flags & (RADEON_TILING_MACRO|RADEON_TILING_MICRO))
                                 == (RADEON_TILING_MACRO|RADEON_TILING_MICRO))
@@ -2633,6 +2630,20 @@ int r100_set_surface_reg(struct radeon_device *rdev, int reg,
        if (tiling_flags & RADEON_TILING_SWAP_32BIT)
                flags |= RADEON_SURF_AP0_SWP_32BPP | RADEON_SURF_AP1_SWP_32BPP;
 
+       /* when we aren't tiling the pitch seems to needs to be furtherdivided down. - tested on power5 + rn50 server */
+       if (tiling_flags & (RADEON_TILING_SWAP_16BIT | RADEON_TILING_SWAP_32BIT)) {
+               if (!(tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO)))
+                       if (ASIC_IS_RN50(rdev))
+                               pitch /= 16;
+       }
+
+       /* r100/r200 divide by 16 */
+       if (rdev->family < CHIP_R300)
+               flags |= pitch / 16;
+       else
+               flags |= pitch / 8;
+
+
        DRM_DEBUG("writing surface %d %d %x %x\n", reg, flags, offset, offset+obj_size-1);
        WREG32(RADEON_SURFACE0_INFO + surf_index, flags);
        WREG32(RADEON_SURFACE0_LOWER_BOUND + surf_index, offset);
@@ -3147,33 +3158,6 @@ static inline void r100_cs_track_texture_print(struct r100_cs_track_texture *t)
        DRM_ERROR("compress format            %d\n", t->compress_format);
 }
 
-static int r100_cs_track_cube(struct radeon_device *rdev,
-                             struct r100_cs_track *track, unsigned idx)
-{
-       unsigned face, w, h;
-       struct radeon_bo *cube_robj;
-       unsigned long size;
-
-       for (face = 0; face < 5; face++) {
-               cube_robj = track->textures[idx].cube_info[face].robj;
-               w = track->textures[idx].cube_info[face].width;
-               h = track->textures[idx].cube_info[face].height;
-
-               size = w * h;
-               size *= track->textures[idx].cpp;
-
-               size += track->textures[idx].cube_info[face].offset;
-
-               if (size > radeon_bo_size(cube_robj)) {
-                       DRM_ERROR("Cube texture offset greater than object size %lu %lu\n",
-                                 size, radeon_bo_size(cube_robj));
-                       r100_cs_track_texture_print(&track->textures[idx]);
-                       return -1;
-               }
-       }
-       return 0;
-}
-
 static int r100_track_compress_size(int compress_format, int w, int h)
 {
        int block_width, block_height, block_bytes;
@@ -3204,6 +3188,37 @@ static int r100_track_compress_size(int compress_format, int w, int h)
        return sz;
 }
 
+static int r100_cs_track_cube(struct radeon_device *rdev,
+                             struct r100_cs_track *track, unsigned idx)
+{
+       unsigned face, w, h;
+       struct radeon_bo *cube_robj;
+       unsigned long size;
+       unsigned compress_format = track->textures[idx].compress_format;
+
+       for (face = 0; face < 5; face++) {
+               cube_robj = track->textures[idx].cube_info[face].robj;
+               w = track->textures[idx].cube_info[face].width;
+               h = track->textures[idx].cube_info[face].height;
+
+               if (compress_format) {
+                       size = r100_track_compress_size(compress_format, w, h);
+               } else
+                       size = w * h;
+               size *= track->textures[idx].cpp;
+
+               size += track->textures[idx].cube_info[face].offset;
+
+               if (size > radeon_bo_size(cube_robj)) {
+                       DRM_ERROR("Cube texture offset greater than object size %lu %lu\n",
+                                 size, radeon_bo_size(cube_robj));
+                       r100_cs_track_texture_print(&track->textures[idx]);
+                       return -1;
+               }
+       }
+       return 0;
+}
+
 static int r100_cs_track_texture_check(struct radeon_device *rdev,
                                       struct r100_cs_track *track)
 {
index 85617c3112127e09bd23442d6b84566ac99a29bd..0266d72e0a4cacaa8e52a79c85e6536e11b5df09 100644 (file)
@@ -415,6 +415,8 @@ int r200_packet0_check(struct radeon_cs_parser *p,
                /* 2D, 3D, CUBE */
                switch (tmp) {
                case 0:
+               case 3:
+               case 4:
                case 5:
                case 6:
                case 7:
@@ -450,6 +452,7 @@ int r200_packet0_check(struct radeon_cs_parser *p,
                case R200_TXFORMAT_RGB332:
                case R200_TXFORMAT_Y8:
                        track->textures[i].cpp = 1;
+                       track->textures[i].compress_format = R100_TRACK_COMP_NONE;
                        break;
                case R200_TXFORMAT_AI88:
                case R200_TXFORMAT_ARGB1555:
@@ -461,6 +464,7 @@ int r200_packet0_check(struct radeon_cs_parser *p,
                case R200_TXFORMAT_DVDU88:
                case R200_TXFORMAT_AVYU4444:
                        track->textures[i].cpp = 2;
+                       track->textures[i].compress_format = R100_TRACK_COMP_NONE;
                        break;
                case R200_TXFORMAT_ARGB8888:
                case R200_TXFORMAT_RGBA8888:
@@ -468,6 +472,7 @@ int r200_packet0_check(struct radeon_cs_parser *p,
                case R200_TXFORMAT_BGR111110:
                case R200_TXFORMAT_LDVDU8888:
                        track->textures[i].cpp = 4;
+                       track->textures[i].compress_format = R100_TRACK_COMP_NONE;
                        break;
                case R200_TXFORMAT_DXT1:
                        track->textures[i].cpp = 1;
index b2f9efe2897c4362d420f61f50090fe0aedc3839..7e81db5eb8041b1c66afe1ade046724abf235805 100644 (file)
@@ -881,6 +881,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
                case R300_TX_FORMAT_Y4X4:
                case R300_TX_FORMAT_Z3Y3X2:
                        track->textures[i].cpp = 1;
+                       track->textures[i].compress_format = R100_TRACK_COMP_NONE;
                        break;
                case R300_TX_FORMAT_X16:
                case R300_TX_FORMAT_Y8X8:
@@ -892,6 +893,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
                case R300_TX_FORMAT_B8G8_B8G8:
                case R300_TX_FORMAT_G8R8_G8B8:
                        track->textures[i].cpp = 2;
+                       track->textures[i].compress_format = R100_TRACK_COMP_NONE;
                        break;
                case R300_TX_FORMAT_Y16X16:
                case R300_TX_FORMAT_Z11Y11X10:
@@ -902,14 +904,17 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
                case R300_TX_FORMAT_FL_I32:
                case 0x1e:
                        track->textures[i].cpp = 4;
+                       track->textures[i].compress_format = R100_TRACK_COMP_NONE;
                        break;
                case R300_TX_FORMAT_W16Z16Y16X16:
                case R300_TX_FORMAT_FL_R16G16B16A16:
                case R300_TX_FORMAT_FL_I32A32:
                        track->textures[i].cpp = 8;
+                       track->textures[i].compress_format = R100_TRACK_COMP_NONE;
                        break;
                case R300_TX_FORMAT_FL_R32G32B32A32:
                        track->textures[i].cpp = 16;
+                       track->textures[i].compress_format = R100_TRACK_COMP_NONE;
                        break;
                case R300_TX_FORMAT_DXT1:
                        track->textures[i].cpp = 1;
index 0e91871f45be0a213a9a67ff25c18fd0244088e8..3d6645ce21518a640dd0981e38a67e223e86a49e 100644 (file)
@@ -130,9 +130,14 @@ void r600_pm_get_dynpm_state(struct radeon_device *rdev)
                                                        break;
                                                }
                                        }
-                               } else
-                                       rdev->pm.requested_power_state_index =
-                                               rdev->pm.current_power_state_index - 1;
+                               } else {
+                                       if (rdev->pm.current_power_state_index == 0)
+                                               rdev->pm.requested_power_state_index =
+                                                       rdev->pm.num_power_states - 1;
+                                       else
+                                               rdev->pm.requested_power_state_index =
+                                                       rdev->pm.current_power_state_index - 1;
+                               }
                        }
                        rdev->pm.requested_clock_mode_index = 0;
                        /* don't use the power state if crtcs are active and no display flag is set */
@@ -1097,7 +1102,7 @@ static void r600_mc_program(struct radeon_device *rdev)
        WREG32(MC_VM_FB_LOCATION, tmp);
        WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8));
        WREG32(HDP_NONSURFACE_INFO, (2 << 7));
-       WREG32(HDP_NONSURFACE_SIZE, rdev->mc.mc_vram_size | 0x3FF);
+       WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF);
        if (rdev->flags & RADEON_IS_AGP) {
                WREG32(MC_VM_AGP_TOP, rdev->mc.gtt_end >> 22);
                WREG32(MC_VM_AGP_BOT, rdev->mc.gtt_start >> 22);
@@ -1219,8 +1224,10 @@ int r600_mc_init(struct radeon_device *rdev)
        rdev->mc.visible_vram_size = rdev->mc.aper_size;
        r600_vram_gtt_location(rdev, &rdev->mc);
 
-       if (rdev->flags & RADEON_IS_IGP)
+       if (rdev->flags & RADEON_IS_IGP) {
+               rs690_pm_info(rdev);
                rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
+       }
        radeon_update_bandwidth_info(rdev);
        return 0;
 }
index 8e1d44ca26ec420eb062c8f21b836cab73aaf845..ab61aaa887bb449c486b59abccb89772b021f35a 100644 (file)
@@ -177,6 +177,7 @@ void radeon_pm_resume(struct radeon_device *rdev);
 void radeon_combios_get_power_modes(struct radeon_device *rdev);
 void radeon_atombios_get_power_modes(struct radeon_device *rdev);
 void radeon_atom_set_voltage(struct radeon_device *rdev, u16 level);
+void rs690_pm_info(struct radeon_device *rdev);
 
 /*
  * Fences.
@@ -619,7 +620,8 @@ enum radeon_dynpm_state {
        DYNPM_STATE_DISABLED,
        DYNPM_STATE_MINIMUM,
        DYNPM_STATE_PAUSED,
-       DYNPM_STATE_ACTIVE
+       DYNPM_STATE_ACTIVE,
+       DYNPM_STATE_SUSPENDED,
 };
 enum radeon_dynpm_action {
        DYNPM_ACTION_NONE,
index 87f7e2cc52d4ef81be592d50891769740d9bf4e8..646f96f97c77d8538919325be4bde664a7f3df8b 100644 (file)
@@ -780,6 +780,13 @@ int radeon_asic_init(struct radeon_device *rdev)
        case CHIP_R423:
        case CHIP_RV410:
                rdev->asic = &r420_asic;
+               /* handle macs */
+               if (rdev->bios == NULL) {
+                       rdev->asic->get_engine_clock = &radeon_legacy_get_engine_clock;
+                       rdev->asic->set_engine_clock = &radeon_legacy_set_engine_clock;
+                       rdev->asic->get_memory_clock = &radeon_legacy_get_memory_clock;
+                       rdev->asic->set_memory_clock = NULL;
+               }
                break;
        case CHIP_RS400:
        case CHIP_RS480:
index fbba938f80481a422418fc3f095b7eef3519c212..2c92137399995f17d9df664c2ae28aa9ad8bbefa 100644 (file)
@@ -48,6 +48,10 @@ static bool igp_read_bios_from_vram(struct radeon_device *rdev)
        resource_size_t vram_base;
        resource_size_t size = 256 * 1024; /* ??? */
 
+       if (!(rdev->flags & RADEON_IS_IGP))
+               if (!radeon_card_posted(rdev))
+                       return false;
+
        rdev->bios = NULL;
        vram_base = drm_get_resource_start(rdev->ddev, 0);
        bios = ioremap(vram_base, size);
index 1bee2f9e24a5ab1fee85e05f14a656ed24b8b94e..d1c1d8dd93ceb045257e35627f1fb429251a8d38 100644 (file)
@@ -1411,6 +1411,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                        rdev->mode_info.connector_table = CT_IMAC_G5_ISIGHT;
                } else
 #endif /* CONFIG_PPC_PMAC */
+#ifdef CONFIG_PPC64
+               if (ASIC_IS_RN50(rdev))
+                       rdev->mode_info.connector_table = CT_RN50_POWER;
+               else
+#endif
                        rdev->mode_info.connector_table = CT_GENERIC;
        }
 
@@ -1853,6 +1858,33 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                                            CONNECTOR_OBJECT_ID_SVIDEO,
                                            &hpd);
                break;
+       case CT_RN50_POWER:
+               DRM_INFO("Connector Table: %d (rn50-power)\n",
+                        rdev->mode_info.connector_table);
+               /* VGA - primary dac */
+               ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
+               hpd.hpd = RADEON_HPD_NONE;
+               radeon_add_legacy_encoder(dev,
+                                         radeon_get_encoder_id(dev,
+                                                               ATOM_DEVICE_CRT1_SUPPORT,
+                                                               1),
+                                         ATOM_DEVICE_CRT1_SUPPORT);
+               radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_CRT1_SUPPORT,
+                                           DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
+                                           CONNECTOR_OBJECT_ID_VGA,
+                                           &hpd);
+               ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC);
+               hpd.hpd = RADEON_HPD_NONE;
+               radeon_add_legacy_encoder(dev,
+                                         radeon_get_encoder_id(dev,
+                                                               ATOM_DEVICE_CRT2_SUPPORT,
+                                                               2),
+                                         ATOM_DEVICE_CRT2_SUPPORT);
+               radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT2_SUPPORT,
+                                           DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
+                                           CONNECTOR_OBJECT_ID_VGA,
+                                           &hpd);
+               break;
        default:
                DRM_INFO("Connector table: %d (invalid)\n",
                         rdev->mode_info.connector_table);
@@ -1906,15 +1938,6 @@ static bool radeon_apply_legacy_quirks(struct drm_device *dev,
                        return false;
        }
 
-       /* Some RV100 cards with 2 VGA ports show up with DVI+VGA */
-       if (dev->pdev->device == 0x5159 &&
-           dev->pdev->subsystem_vendor == 0x1002 &&
-           dev->pdev->subsystem_device == 0x013a) {
-               if (*legacy_connector == CONNECTOR_DVI_I_LEGACY)
-                       *legacy_connector = CONNECTOR_CRT_LEGACY;
-
-       }
-
        /* X300 card with extra non-existent DVI port */
        if (dev->pdev->device == 0x5B60 &&
            dev->pdev->subsystem_vendor == 0x17af &&
@@ -3019,6 +3042,14 @@ void radeon_combios_asic_init(struct drm_device *dev)
                combios_write_ram_size(dev);
        }
 
+       /* quirk for rs4xx HP nx6125 laptop to make it resume
+        * - it hangs on resume inside the dynclk 1 table.
+        */
+       if (rdev->family == CHIP_RS480 &&
+           rdev->pdev->subsystem_vendor == 0x103c &&
+           rdev->pdev->subsystem_device == 0x308b)
+               return;
+
        /* DYN CLK 1 */
        table = combios_get_table_offset(dev, COMBIOS_DYN_CLK_1_TABLE);
        if (table)
index b7023fff89eb258b00d6aee84e7632954fe00384..4eb67c0e0996e539b9ad46242b25ef0070e8dfeb 100644 (file)
@@ -194,7 +194,7 @@ unpin:
 fail:
        drm_gem_object_unreference_unlocked(obj);
 
-       return 0;
+       return ret;
 }
 
 int radeon_crtc_cursor_move(struct drm_crtc *crtc,
index f10faed21567f85feef0d1f097b219002d68b978..5f317317aba29dc972331f32994c0acae66e9840 100644 (file)
@@ -779,6 +779,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
 
 int radeon_resume_kms(struct drm_device *dev)
 {
+       struct drm_connector *connector;
        struct radeon_device *rdev = dev->dev_private;
 
        if (rdev->powered_down)
@@ -797,6 +798,12 @@ int radeon_resume_kms(struct drm_device *dev)
        radeon_resume(rdev);
        radeon_pm_resume(rdev);
        radeon_restore_bios_scratch_regs(rdev);
+
+       /* turn on display hw */
+       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+               drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
+       }
+
        radeon_fbdev_set_suspend(rdev, 0);
        release_console_sem();
 
index 1ebb100015b70b71f354ce8c4405b13455a02c8b..e0b30b264c2809997673f481bddec3a22b9d78a9 100644 (file)
@@ -1072,6 +1072,8 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
        if (is_dig) {
                switch (mode) {
                case DRM_MODE_DPMS_ON:
+                       if (!ASIC_IS_DCE4(rdev))
+                               atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
                        if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) {
                                struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
 
@@ -1079,8 +1081,6 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
                                if (ASIC_IS_DCE4(rdev))
                                        atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON);
                        }
-                       if (!ASIC_IS_DCE4(rdev))
-                               atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
                        break;
                case DRM_MODE_DPMS_STANDBY:
                case DRM_MODE_DPMS_SUSPEND:
index 5b07b8848e09b22fbeeda3b802af280ba852af1b..bad77f40a9dad73e375ef791cfe865604aac61b6 100644 (file)
@@ -928,16 +928,14 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder,
        if (ASIC_IS_R300(rdev)) {
                gpiopad_a = RREG32(RADEON_GPIOPAD_A) | 1;
                disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
-       }
-
-       if (rdev->family == CHIP_R200 || ASIC_IS_R300(rdev))
-               disp_tv_out_cntl = RREG32(RADEON_DISP_TV_OUT_CNTL);
-       else
+       } else if (rdev->family != CHIP_R200)
                disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG);
-
-       if (rdev->family == CHIP_R200)
+       else if (rdev->family == CHIP_R200)
                fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
 
+       if (rdev->family >= CHIP_R200)
+               disp_tv_out_cntl = RREG32(RADEON_DISP_TV_OUT_CNTL);
+
        if (is_tv) {
                uint32_t dac_cntl;
 
@@ -1002,15 +1000,13 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder,
        if (ASIC_IS_R300(rdev)) {
                WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
                WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
-       }
+       } else if (rdev->family != CHIP_R200)
+               WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
+       else if (rdev->family == CHIP_R200)
+               WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
 
        if (rdev->family >= CHIP_R200)
                WREG32(RADEON_DISP_TV_OUT_CNTL, disp_tv_out_cntl);
-       else
-               WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
-
-       if (rdev->family == CHIP_R200)
-               WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
 
        if (is_tv)
                radeon_legacy_tv_mode_set(encoder, mode, adjusted_mode);
index 67358baf28b2930c4dc999a2b6e63a7e5c9e8d98..95696aa57ac8c43048071ba93fd4254ec113ac92 100644 (file)
@@ -206,6 +206,7 @@ enum radeon_connector_table {
        CT_MINI_INTERNAL,
        CT_IMAC_G5_ISIGHT,
        CT_EMAC,
+       CT_RN50_POWER,
 };
 
 enum radeon_dvo_chip {
index 63f679a04b25a2a87997e1ea5e35e1adc0fed64a..115d26b762cc2b3db9301c86e66d97505f6fd291 100644 (file)
@@ -397,13 +397,20 @@ static ssize_t radeon_set_pm_method(struct device *dev,
                rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
                mutex_unlock(&rdev->pm.mutex);
        } else if (strncmp("profile", buf, strlen("profile")) == 0) {
+               bool flush_wq = false;
+
                mutex_lock(&rdev->pm.mutex);
-               rdev->pm.pm_method = PM_METHOD_PROFILE;
+               if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
+                       cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+                       flush_wq = true;
+               }
                /* disable dynpm */
                rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
                rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
-               cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+               rdev->pm.pm_method = PM_METHOD_PROFILE;
                mutex_unlock(&rdev->pm.mutex);
+               if (flush_wq)
+                       flush_workqueue(rdev->wq);
        } else {
                DRM_ERROR("invalid power method!\n");
                goto fail;
@@ -418,9 +425,18 @@ static DEVICE_ATTR(power_method, S_IRUGO | S_IWUSR, radeon_get_pm_method, radeon
 
 void radeon_pm_suspend(struct radeon_device *rdev)
 {
+       bool flush_wq = false;
+
        mutex_lock(&rdev->pm.mutex);
-       cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+       if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
+               cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+               if (rdev->pm.dynpm_state == DYNPM_STATE_ACTIVE)
+                       rdev->pm.dynpm_state = DYNPM_STATE_SUSPENDED;
+               flush_wq = true;
+       }
        mutex_unlock(&rdev->pm.mutex);
+       if (flush_wq)
+               flush_workqueue(rdev->wq);
 }
 
 void radeon_pm_resume(struct radeon_device *rdev)
@@ -432,6 +448,12 @@ void radeon_pm_resume(struct radeon_device *rdev)
        rdev->pm.current_sclk = rdev->clock.default_sclk;
        rdev->pm.current_mclk = rdev->clock.default_mclk;
        rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
+       if (rdev->pm.pm_method == PM_METHOD_DYNPM
+           && rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) {
+               rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE;
+               queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
+                                       msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
+       }
        mutex_unlock(&rdev->pm.mutex);
        radeon_pm_compute_clocks(rdev);
 }
@@ -486,6 +508,8 @@ int radeon_pm_init(struct radeon_device *rdev)
 void radeon_pm_fini(struct radeon_device *rdev)
 {
        if (rdev->pm.num_power_states > 1) {
+               bool flush_wq = false;
+
                mutex_lock(&rdev->pm.mutex);
                if (rdev->pm.pm_method == PM_METHOD_PROFILE) {
                        rdev->pm.profile = PM_PROFILE_DEFAULT;
@@ -493,13 +517,16 @@ void radeon_pm_fini(struct radeon_device *rdev)
                        radeon_pm_set_clocks(rdev);
                } else if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
                        /* cancel work */
-                       cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work);
+                       cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+                       flush_wq = true;
                        /* reset default clocks */
                        rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
                        rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
                        radeon_pm_set_clocks(rdev);
                }
                mutex_unlock(&rdev->pm.mutex);
+               if (flush_wq)
+                       flush_workqueue(rdev->wq);
 
                device_remove_file(rdev->dev, &dev_attr_power_profile);
                device_remove_file(rdev->dev, &dev_attr_power_method);
@@ -720,12 +747,12 @@ static void radeon_dynpm_idle_work_handler(struct work_struct *work)
                        radeon_pm_get_dynpm_state(rdev);
                        radeon_pm_set_clocks(rdev);
                }
+
+               queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
+                                       msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
        }
        mutex_unlock(&rdev->pm.mutex);
        ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
-
-       queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
-                                       msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
 }
 
 /*
index b5c757f68d3cc249fbe1ac6d40994c3b8ba4c551..f78fd592544d67a58e15016487d4d8b47ee38bf7 100644 (file)
@@ -80,8 +80,8 @@ evergreen 0x9400
 0x00028010 DB_RENDER_OVERRIDE2
 0x00028028 DB_STENCIL_CLEAR
 0x0002802C DB_DEPTH_CLEAR
-0x00028034 PA_SC_SCREEN_SCISSOR_BR
 0x00028030 PA_SC_SCREEN_SCISSOR_TL
+0x00028034 PA_SC_SCREEN_SCISSOR_BR
 0x0002805C DB_DEPTH_SLICE
 0x00028140 SQ_ALU_CONST_BUFFER_SIZE_PS_0
 0x00028144 SQ_ALU_CONST_BUFFER_SIZE_PS_1
@@ -460,8 +460,8 @@ evergreen 0x9400
 0x00028844 SQ_PGM_RESOURCES_PS
 0x00028848 SQ_PGM_RESOURCES_2_PS
 0x0002884C SQ_PGM_EXPORTS_PS
-0x0002885C SQ_PGM_RESOURCES_VS
-0x00028860 SQ_PGM_RESOURCES_2_VS
+0x00028860 SQ_PGM_RESOURCES_VS
+0x00028864 SQ_PGM_RESOURCES_2_VS
 0x00028878 SQ_PGM_RESOURCES_GS
 0x0002887C SQ_PGM_RESOURCES_2_GS
 0x00028890 SQ_PGM_RESOURCES_ES
@@ -469,8 +469,8 @@ evergreen 0x9400
 0x000288A8 SQ_PGM_RESOURCES_FS
 0x000288BC SQ_PGM_RESOURCES_HS
 0x000288C0 SQ_PGM_RESOURCES_2_HS
-0x000288D0 SQ_PGM_RESOURCES_LS
-0x000288D4 SQ_PGM_RESOURCES_2_LS
+0x000288D4 SQ_PGM_RESOURCES_LS
+0x000288D8 SQ_PGM_RESOURCES_2_LS
 0x000288E8 SQ_LDS_ALLOC
 0x000288EC SQ_LDS_ALLOC_PS
 0x000288F0 SQ_VTX_SEMANTIC_CLEAR
index bcc33195ebc2a2e9d2f4e441ed7e88632b5d04bb..f4f0a61bcdce3d188dd01a5737120c4e9a0d6432 100644 (file)
@@ -79,7 +79,13 @@ void rs690_pm_info(struct radeon_device *rdev)
                        tmp.full = dfixed_const(100);
                        rdev->pm.igp_sideport_mclk.full = dfixed_const(info->info.ulBootUpMemoryClock);
                        rdev->pm.igp_sideport_mclk.full = dfixed_div(rdev->pm.igp_sideport_mclk, tmp);
-                       rdev->pm.igp_system_mclk.full = dfixed_const(le16_to_cpu(info->info.usK8MemoryClock));
+                       if (info->info.usK8MemoryClock)
+                               rdev->pm.igp_system_mclk.full = dfixed_const(le16_to_cpu(info->info.usK8MemoryClock));
+                       else if (rdev->clock.default_mclk) {
+                               rdev->pm.igp_system_mclk.full = dfixed_const(rdev->clock.default_mclk);
+                               rdev->pm.igp_system_mclk.full = dfixed_div(rdev->pm.igp_system_mclk, tmp);
+                       } else
+                               rdev->pm.igp_system_mclk.full = dfixed_const(400);
                        rdev->pm.igp_ht_link_clk.full = dfixed_const(le16_to_cpu(info->info.usFSBClock));
                        rdev->pm.igp_ht_link_width.full = dfixed_const(info->info.ucHTLinkWidth);
                        break;
@@ -87,34 +93,31 @@ void rs690_pm_info(struct radeon_device *rdev)
                        tmp.full = dfixed_const(100);
                        rdev->pm.igp_sideport_mclk.full = dfixed_const(info->info_v2.ulBootUpSidePortClock);
                        rdev->pm.igp_sideport_mclk.full = dfixed_div(rdev->pm.igp_sideport_mclk, tmp);
-                       rdev->pm.igp_system_mclk.full = dfixed_const(info->info_v2.ulBootUpUMAClock);
+                       if (info->info_v2.ulBootUpUMAClock)
+                               rdev->pm.igp_system_mclk.full = dfixed_const(info->info_v2.ulBootUpUMAClock);
+                       else if (rdev->clock.default_mclk)
+                               rdev->pm.igp_system_mclk.full = dfixed_const(rdev->clock.default_mclk);
+                       else
+                               rdev->pm.igp_system_mclk.full = dfixed_const(66700);
                        rdev->pm.igp_system_mclk.full = dfixed_div(rdev->pm.igp_system_mclk, tmp);
                        rdev->pm.igp_ht_link_clk.full = dfixed_const(info->info_v2.ulHTLinkFreq);
                        rdev->pm.igp_ht_link_clk.full = dfixed_div(rdev->pm.igp_ht_link_clk, tmp);
                        rdev->pm.igp_ht_link_width.full = dfixed_const(le16_to_cpu(info->info_v2.usMinHTLinkWidth));
                        break;
                default:
-                       tmp.full = dfixed_const(100);
                        /* We assume the slower possible clock ie worst case */
-                       /* DDR 333Mhz */
-                       rdev->pm.igp_sideport_mclk.full = dfixed_const(333);
-                       /* FIXME: system clock ? */
-                       rdev->pm.igp_system_mclk.full = dfixed_const(100);
-                       rdev->pm.igp_system_mclk.full = dfixed_div(rdev->pm.igp_system_mclk, tmp);
-                       rdev->pm.igp_ht_link_clk.full = dfixed_const(200);
+                       rdev->pm.igp_sideport_mclk.full = dfixed_const(200);
+                       rdev->pm.igp_system_mclk.full = dfixed_const(200);
+                       rdev->pm.igp_ht_link_clk.full = dfixed_const(1000);
                        rdev->pm.igp_ht_link_width.full = dfixed_const(8);
                        DRM_ERROR("No integrated system info for your GPU, using safe default\n");
                        break;
                }
        } else {
-               tmp.full = dfixed_const(100);
                /* We assume the slower possible clock ie worst case */
-               /* DDR 333Mhz */
-               rdev->pm.igp_sideport_mclk.full = dfixed_const(333);
-               /* FIXME: system clock ? */
-               rdev->pm.igp_system_mclk.full = dfixed_const(100);
-               rdev->pm.igp_system_mclk.full = dfixed_div(rdev->pm.igp_system_mclk, tmp);
-               rdev->pm.igp_ht_link_clk.full = dfixed_const(200);
+               rdev->pm.igp_sideport_mclk.full = dfixed_const(200);
+               rdev->pm.igp_system_mclk.full = dfixed_const(200);
+               rdev->pm.igp_ht_link_clk.full = dfixed_const(1000);
                rdev->pm.igp_ht_link_width.full = dfixed_const(8);
                DRM_ERROR("No integrated system info for your GPU, using safe default\n");
        }
@@ -228,10 +231,6 @@ void rs690_crtc_bandwidth_compute(struct radeon_device *rdev,
        fixed20_12 a, b, c;
        fixed20_12 pclk, request_fifo_depth, tolerable_latency, estimated_width;
        fixed20_12 consumption_time, line_time, chunk_time, read_delay_latency;
-       /* FIXME: detect IGP with sideport memory, i don't think there is any
-        * such product available
-        */
-       bool sideport = false;
 
        if (!crtc->base.enabled) {
                /* FIXME: wouldn't it better to set priority mark to maximum */
@@ -300,7 +299,7 @@ void rs690_crtc_bandwidth_compute(struct radeon_device *rdev,
 
        /* Maximun bandwidth is the minimun bandwidth of all component */
        rdev->pm.max_bandwidth = rdev->pm.core_bandwidth;
-       if (sideport) {
+       if (rdev->mc.igp_sideport_enabled) {
                if (rdev->pm.max_bandwidth.full > rdev->pm.sideport_bandwidth.full &&
                        rdev->pm.sideport_bandwidth.full)
                        rdev->pm.max_bandwidth = rdev->pm.sideport_bandwidth;
index cec536c222c5314e696b1ca3acb6789dfdc8924e..b7fd82064922342d420cacb56a7ece8a00964393 100644 (file)
@@ -224,7 +224,7 @@ static void rv770_mc_program(struct radeon_device *rdev)
        WREG32(MC_VM_FB_LOCATION, tmp);
        WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8));
        WREG32(HDP_NONSURFACE_INFO, (2 << 7));
-       WREG32(HDP_NONSURFACE_SIZE, (rdev->mc.mc_vram_size - 1) | 0x3FF);
+       WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF);
        if (rdev->flags & RADEON_IS_AGP) {
                WREG32(MC_VM_AGP_TOP, rdev->mc.gtt_end >> 16);
                WREG32(MC_VM_AGP_BOT, rdev->mc.gtt_start >> 16);
index ef910694bd634807631dd0958831bfa8c44421df..2f047577b1e391d1d09a9ba4407c0bc3c4b5b4fc 100644 (file)
@@ -667,7 +667,7 @@ int ttm_get_pages(struct list_head *pages, int flags,
 {
        struct ttm_page_pool *pool = ttm_get_pool(flags, cstate);
        struct page *p = NULL;
-       int gfp_flags = 0;
+       int gfp_flags = GFP_USER;
        int r;
 
        /* set zero flag for page allocation if required */
index 9cca465436e39d07569db4a0a2535332ae2d5fb6..85064a9f649ed34acbfad8db3980afd42bb208ec 100644 (file)
@@ -9,19 +9,13 @@
  *
  */
 
-#include <linux/init.h>
-#include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/power_supply.h>
-#include <linux/i2c.h>
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
 #include <linux/gpio.h>
+#include <linux/i2c.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
-#include <asm/irq.h>
-#include <asm/mach/irq.h>
+#include <linux/power_supply.h>
+#include <linux/slab.h>
 #include <linux/z2_battery.h>
 
 #define        Z2_DEFAULT_NAME "Z2"
index de033b7ac21f68e67b423d711d998c06604fd90f..d827ce570a8c8eba9fee216f66a3bb3e1e184232 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 9eb62a256e9a675af529475d178c7925e6de5302..cd6cf575902e4aab43a2dc232c7358db93ff8a82 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 e2c000b80ca0e41b998be612c4f570116ad28357..212bc21e6d682f7b3e822856be86c1af6f916102 100644 (file)
@@ -225,9 +225,9 @@ static struct bat_attribute *mesh_attrs[] = {
        NULL,
 };
 
-static ssize_t transtable_local_read(struct kobject *kobj,
-                              struct bin_attribute *bin_attr,
-                              char *buff, loff_t off, size_t count)
+static ssize_t transtable_local_read(struct file *filp, struct kobject *kobj,
+                                 struct bin_attribute *bin_attr,
+                                 char *buff, loff_t off, size_t count)
 {
        struct device *dev = to_dev(kobj->parent);
        struct net_device *net_dev = to_net_dev(dev);
@@ -235,9 +235,9 @@ static ssize_t transtable_local_read(struct kobject *kobj,
        return hna_local_fill_buffer_text(net_dev, buff, count, off);
 }
 
-static ssize_t transtable_global_read(struct kobject *kobj,
-                              struct bin_attribute *bin_attr,
-                              char *buff, loff_t off, size_t count)
+static ssize_t transtable_global_read(struct file *filp, struct kobject *kobj,
+                                 struct bin_attribute *bin_attr,
+                                 char *buff, loff_t off, size_t count)
 {
        struct device *dev = to_dev(kobj->parent);
        struct net_device *net_dev = to_net_dev(dev);
@@ -245,9 +245,9 @@ static ssize_t transtable_global_read(struct kobject *kobj,
        return hna_global_fill_buffer_text(net_dev, buff, count, off);
 }
 
-static ssize_t originators_read(struct kobject *kobj,
-                              struct bin_attribute *bin_attr,
-                              char *buff, loff_t off, size_t count)
+static ssize_t originators_read(struct file *filp, struct kobject *kobj,
+                                 struct bin_attribute *bin_attr,
+                                 char *buff, loff_t off, size_t count)
 {
        struct device *dev = to_dev(kobj->parent);
        struct net_device *net_dev = to_net_dev(dev);
@@ -255,9 +255,9 @@ static ssize_t originators_read(struct kobject *kobj,
        return orig_fill_buffer_text(net_dev, buff, count, off);
 }
 
-static ssize_t vis_data_read(struct kobject *kobj,
-                            struct bin_attribute *bin_attr,
-                            char *buff, loff_t off, size_t count)
+static ssize_t vis_data_read(struct file *filp, struct kobject *kobj,
+                                 struct bin_attribute *bin_attr,
+                                 char *buff, loff_t off, size_t count)
 {
        struct device *dev = to_dev(kobj->parent);
        struct net_device *net_dev = to_net_dev(dev);
index 7eb6559e03158d07eada6eccddf882ddaa2ec537..32204b5572d0c8e78a34b89c69a04c6d11cb762c 100644 (file)
@@ -196,7 +196,7 @@ ssize_t bat_device_read(struct file *file, char __user *buf, size_t count,
        kfree(device_packet);
 
        if (error)
-               return error;
+               return -EFAULT;
 
        return sizeof(struct icmp_packet);
 }
index 36a254cd44136bba77257078cb7c7501069d3926..39d112b708e3711c6bf78b7ad966ceafcce810fb 100644 (file)
@@ -824,9 +824,12 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev,
                plx9050_interrupt_control(dev_private->lcr_io_base, true, true,
                                          false, true, true);
 
-               dev_private->scan_delay =
-                   (async_cmd->scan_begin_arg / (async_cmd->convert_arg *
-                                                 async_cmd->chanlist_len)) - 1;
+               if (async_cmd->scan_begin_src == TRIG_TIMER) {
+                       dev_private->scan_delay =
+                               (async_cmd->scan_begin_arg /
+                                (async_cmd->convert_arg *
+                                 async_cmd->chanlist_len)) - 1;
+               }
 
                break;
 
index 81829d6fd2878bb07f2ca53caf2c11f050aee533..c374bee250687597a8c196e8a8823b44f2ea3aaa 100644 (file)
@@ -52,7 +52,6 @@ Please report success/failure with other different cards to
 #include "8255.h"
 
 #define PCI_VENDOR_ID_CB       0x1307  /*  PCI vendor number of ComputerBoards */
-#define N_BOARDS       10      /*  Number of boards in cb_pcidda_boards */
 #define EEPROM_SIZE    128     /*  number of entries in eeprom */
 #define MAX_AO_CHANNELS 8      /*  maximum number of ao channels for supported boards */
 
@@ -307,7 +306,7 @@ static int cb_pcidda_attach(struct comedi_device *dev,
                                        continue;
                                }
                        }
-                       for (index = 0; index < N_BOARDS; index++) {
+                       for (index = 0; index < ARRAY_SIZE(cb_pcidda_boards); index++) {
                                if (cb_pcidda_boards[index].device_id ==
                                    pcidev->device) {
                                        goto found;
index 3f53b4d1e4cffcf09552871b30f5c9d6f98ce8a3..12db555a3a5d59b1348c4f3616e246991f7c3246 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/slab.h>
 #include <linux/list.h>
 #include <linux/module.h>
+#include <linux/completion.h>
 #include "osd.h"
 #include "logging.h"
 #include "vmbus_private.h"
@@ -293,6 +294,25 @@ void FreeVmbusChannel(struct vmbus_channel *Channel)
                              Channel);
 }
 
+
+DECLARE_COMPLETION(hv_channel_ready);
+
+/*
+ * Count initialized channels, and ensure all channels are ready when hv_vmbus
+ * module loading completes.
+ */
+static void count_hv_channel(void)
+{
+       static int counter;
+       unsigned long flags;
+
+       spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
+       if (++counter == MAX_MSG_TYPES)
+               complete(&hv_channel_ready);
+       spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags);
+}
+
+
 /*
  * VmbusChannelProcessOffer - Process the offer by creating a channel/device
  * associated with this offer
@@ -373,22 +393,21 @@ static void VmbusChannelProcessOffer(void *context)
                 * can cleanup properly
                 */
                newChannel->State = CHANNEL_OPEN_STATE;
-               cnt = 0;
 
-               while (cnt != MAX_MSG_TYPES) {
+               /* Open IC channels */
+               for (cnt = 0; cnt < MAX_MSG_TYPES; cnt++) {
                        if (memcmp(&newChannel->OfferMsg.Offer.InterfaceType,
                                   &hv_cb_utils[cnt].data,
-                                  sizeof(struct hv_guid)) == 0) {
+                                  sizeof(struct hv_guid)) == 0 &&
+                               VmbusChannelOpen(newChannel, 2 * PAGE_SIZE,
+                                                2 * PAGE_SIZE, NULL, 0,
+                                                hv_cb_utils[cnt].callback,
+                                                newChannel) == 0) {
+                               hv_cb_utils[cnt].channel = newChannel;
                                DPRINT_INFO(VMBUS, "%s",
-                                           hv_cb_utils[cnt].log_msg);
-
-                               if (VmbusChannelOpen(newChannel, 2 * PAGE_SIZE,
-                                                   2 * PAGE_SIZE, NULL, 0,
-                                                   hv_cb_utils[cnt].callback,
-                                                   newChannel) == 0)
-                                       hv_cb_utils[cnt].channel = newChannel;
+                                               hv_cb_utils[cnt].log_msg);
+                               count_hv_channel();
                        }
-                       cnt++;
                }
        }
        DPRINT_EXIT(VMBUS);
index 8a49aafea37a5c7a7f2597e53134530c88331f11..2adc9b48ca9cf5aea96de4cc672f62327945af83 100644 (file)
@@ -24,6 +24,8 @@
 #include <linux/slab.h>
 #include <linux/sysctl.h>
 #include <linux/reboot.h>
+#include <linux/dmi.h>
+#include <linux/pci.h>
 
 #include "logging.h"
 #include "osd.h"
@@ -251,10 +253,36 @@ static void heartbeat_onchannelcallback(void *context)
        DPRINT_EXIT(VMBUS);
 }
 
+static const struct pci_device_id __initconst
+hv_utils_pci_table[] __maybe_unused = {
+       { PCI_DEVICE(0x1414, 0x5353) }, /* Hyper-V emulated VGA controller */
+       { 0 }
+};
+MODULE_DEVICE_TABLE(pci, hv_utils_pci_table);
+
+
+static const struct dmi_system_id __initconst
+hv_utils_dmi_table[] __maybe_unused  = {
+       {
+               .ident = "Hyper-V",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"),
+                       DMI_MATCH(DMI_BOARD_NAME, "Virtual Machine"),
+               },
+       },
+       { },
+};
+MODULE_DEVICE_TABLE(dmi, hv_utils_dmi_table);
+
+
 static int __init init_hyperv_utils(void)
 {
        printk(KERN_INFO "Registering HyperV Utility Driver\n");
 
+       if (!dmi_check_system(hv_utils_dmi_table))
+               return -ENODEV;
+
        hv_cb_utils[HV_SHUTDOWN_MSG].channel->OnChannelCallback =
                &shutdown_onchannelcallback;
        hv_cb_utils[HV_SHUTDOWN_MSG].callback = &shutdown_onchannelcallback;
index 0c6ee0f487f3538384e0d4f2931b2f496b6a01e8..3c14b2926e0018e1e8ef157df37fc770a6d440b3 100644 (file)
@@ -74,4 +74,6 @@ int vmbus_child_driver_register(struct driver_context *driver_ctx);
 void vmbus_child_driver_unregister(struct driver_context *driver_ctx);
 void vmbus_get_interface(struct vmbus_channel_interface *interface);
 
+extern struct completion hv_channel_ready;
+
 #endif /* _VMBUS_H_ */
index c21731a12ca7a7a8e8a9929369b2f99833c5e2f2..22c80ece6388c5e72661864105f4d35ebf7e1824 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/pci.h>
 #include <linux/dmi.h>
 #include <linux/slab.h>
+#include <linux/completion.h>
 #include "version_info.h"
 #include "osd.h"
 #include "logging.h"
@@ -356,6 +357,8 @@ static int vmbus_bus_init(int (*drv_init)(struct hv_driver *drv))
 
        vmbus_drv_obj->GetChannelOffers();
 
+       wait_for_completion(&hv_channel_ready);
+
 cleanup:
        DPRINT_EXIT(VMBUS_DRV);
 
index 1db00975a594ec8e859ab81db32a1db9acac22c5..abba22f921bec49b8f4d58123f33c8e01947380e 100644 (file)
@@ -817,9 +817,9 @@ static int mrstouch_remove(struct spi_device *spi)
        free_irq(mrstouchdevp->irq, mrstouchdevp);
        input_unregister_device(mrstouchdevp->input);
        input_free_device(mrstouchdevp->input);
-       kfree(mrstouchdevp);
        if (mrstouchdevp->pendet_thrd)
                kthread_stop(mrstouchdevp->pendet_thrd);
+       kfree(mrstouchdevp);
        return 0;
 }
 
index b740662d095a5281a2ffd8933fe1473952fd64ae..674769d2b59b0e7c35b8fc9b58d02cca48a23fe2 100644 (file)
@@ -77,6 +77,7 @@ struct usb_device_id rtusb_usb_id[] = {
        {USB_DEVICE(0x083A, 0x7522)},   /* Arcadyan */
        {USB_DEVICE(0x0CDE, 0x0022)},   /* ZCOM */
        {USB_DEVICE(0x0586, 0x3416)},   /* Zyxel */
+       {USB_DEVICE(0x0586, 0x341a)},   /* Zyxel NWD-270N */
        {USB_DEVICE(0x0CDE, 0x0025)},   /* Zyxel */
        {USB_DEVICE(0x1740, 0x9701)},   /* EnGenius */
        {USB_DEVICE(0x1740, 0x9702)},   /* EnGenius */
index dacefea78113414e16fdbe966c41e4334e47d9f4..49ab9fa9ffa784833e08b170d009046c7dd7370a 100644 (file)
@@ -66,8 +66,6 @@ static int hwseqnum = 0;
 static int hwwep = 0;
 static int channels = 0x3fff;
 
-#define eqMacAddr(a, b)                (((a)[0] == (b)[0] && (a)[1] == (b)[1] && (a)[2] == (b)[2] && (a)[3] == (b)[3] && (a)[4] == (b)[4] && (a)[5] == (b)[5]) ? 1 : 0)
-#define cpMacAddr(des, src)            ((des)[0] = (src)[0], (des)[1] = (src)[1], (des)[2] = (src)[2], (des)[3] = (src)[3], (des)[4] = (src)[4], (des)[5] = (src)[5])
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(pci, rtl8180_pci_id_tbl);
 MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>");
index 447d6474a70c3ee3962920e38766307734188c3d..1b6890611fb6dc822156e6ffbee719fb156712c3 100644 (file)
@@ -112,28 +112,29 @@ u32 rt_global_debug_component = \
 #define CAM_CONTENT_COUNT 8
 
 static const struct usb_device_id rtl8192_usb_id_tbl[] = {
-       /* Realtek */
-       {USB_DEVICE(0x0bda, 0x8171)},
-       {USB_DEVICE(0x0bda, 0x8192)},
-       {USB_DEVICE(0x0bda, 0x8709)},
-       /* Corega */
-       {USB_DEVICE(0x07aa, 0x0043)},
-       /* Belkin */
-       {USB_DEVICE(0x050d, 0x805E)},
-       {USB_DEVICE(0x050d, 0x815F)}, /* Belkin F5D8053 v6 */
-       /* Sitecom */
-       {USB_DEVICE(0x0df6, 0x0031)},
-       {USB_DEVICE(0x0df6, 0x004b)},   /* WL-349 */
-       /* EnGenius */
-       {USB_DEVICE(0x1740, 0x9201)},
-       /* Dlink */
-       {USB_DEVICE(0x2001, 0x3301)},
-       /* Zinwell */
-       {USB_DEVICE(0x5a57, 0x0290)},
-       /* Guillemot */
-       {USB_DEVICE(0x06f8, 0xe031)},
-       //92SU
+       {USB_DEVICE(0x0bda, 0x8171)}, /* Realtek */
        {USB_DEVICE(0x0bda, 0x8172)},
+       {USB_DEVICE(0x0bda, 0x8173)},
+       {USB_DEVICE(0x0bda, 0x8174)},
+       {USB_DEVICE(0x0bda, 0x8712)},
+       {USB_DEVICE(0x0bda, 0x8713)},
+       {USB_DEVICE(0x07aa, 0x0047)},
+       {USB_DEVICE(0x07d1, 0x3303)},
+       {USB_DEVICE(0x07d1, 0x3302)},
+       {USB_DEVICE(0x07d1, 0x3300)},
+       {USB_DEVICE(0x1740, 0x9603)},
+       {USB_DEVICE(0x1740, 0x9605)},
+       {USB_DEVICE(0x050d, 0x815F)},
+       {USB_DEVICE(0x06f8, 0xe031)},
+       {USB_DEVICE(0x7392, 0x7611)},
+       {USB_DEVICE(0x7392, 0x7612)},
+       {USB_DEVICE(0x7392, 0x7622)},
+       {USB_DEVICE(0x0DF6, 0x0045)},
+       {USB_DEVICE(0x0E66, 0x0015)},
+       {USB_DEVICE(0x0E66, 0x0016)},
+       {USB_DEVICE(0x0b05, 0x1786)},
+       /* these are not in the official list */
+       {USB_DEVICE(0x0df6, 0x004b)}, /* WL-349 */
        {}
 };
 
index 2bede271a2f0302924ea8f2155b5848429073041..f38472c2e75cc78847c191883b28e781d712805a 100644 (file)
@@ -121,6 +121,8 @@ static const struct usb_device_id rtl8192_usb_id_tbl[] = {
        {USB_DEVICE(0x2001, 0x3301)},
        /* Zinwell */
        {USB_DEVICE(0x5a57, 0x0290)},
+       /* LG */
+       {USB_DEVICE(0x043e, 0x7a01)},
        {}
 };
 
index 52408164036f3eda94b422d3b14898a26584c5f2..6a499f0eb5948426813f6a53acda1f5c6f243bd2 100644 (file)
@@ -378,47 +378,67 @@ int usbip_thread(void *param)
        complete_and_exit(&ut->thread_done, 0);
 }
 
+static void stop_rx_thread(struct usbip_device *ud)
+{
+       if (ud->tcp_rx.thread != NULL) {
+               send_sig(SIGKILL, ud->tcp_rx.thread, 1);
+               wait_for_completion(&ud->tcp_rx.thread_done);
+               usbip_udbg("rx_thread for ud %p has finished\n", ud);
+       }
+}
+
+static void stop_tx_thread(struct usbip_device *ud)
+{
+       if (ud->tcp_tx.thread != NULL) {
+               send_sig(SIGKILL, ud->tcp_tx.thread, 1);
+               wait_for_completion(&ud->tcp_tx.thread_done);
+               usbip_udbg("tx_thread for ud %p has finished\n", ud);
+       }
+}
+
 int usbip_start_threads(struct usbip_device *ud)
 {
        /*
         * threads are invoked per one device (per one connection).
         */
        struct task_struct *th;
+       int err = 0;
 
        th = kthread_run(usbip_thread, (void *)&ud->tcp_rx, "usbip");
        if (IS_ERR(th)) {
                printk(KERN_WARNING
                        "Unable to start control thread\n");
-               return PTR_ERR(th);
+               err = PTR_ERR(th);
+               goto ust_exit;
        }
+
        th = kthread_run(usbip_thread, (void *)&ud->tcp_tx, "usbip");
        if (IS_ERR(th)) {
                printk(KERN_WARNING
                        "Unable to start control thread\n");
-               return PTR_ERR(th);
+               err = PTR_ERR(th);
+               goto tx_thread_err;
        }
 
        /* confirm threads are starting */
        wait_for_completion(&ud->tcp_rx.thread_done);
        wait_for_completion(&ud->tcp_tx.thread_done);
+
        return 0;
+
+tx_thread_err:
+       stop_rx_thread(ud);
+
+ust_exit:
+       return err;
 }
 EXPORT_SYMBOL_GPL(usbip_start_threads);
 
 void usbip_stop_threads(struct usbip_device *ud)
 {
        /* kill threads related to this sdev, if v.c. exists */
-       if (ud->tcp_rx.thread != NULL) {
-               send_sig(SIGKILL, ud->tcp_rx.thread, 1);
-               wait_for_completion(&ud->tcp_rx.thread_done);
-               usbip_udbg("rx_thread for ud %p has finished\n", ud);
-       }
-
-       if (ud->tcp_tx.thread != NULL) {
-               send_sig(SIGKILL, ud->tcp_tx.thread, 1);
-               wait_for_completion(&ud->tcp_tx.thread_done);
-               usbip_udbg("tx_thread for ud %p has finished\n", ud);
-       }
+       stop_rx_thread(ud);
+       stop_tx_thread(ud);
 }
 EXPORT_SYMBOL_GPL(usbip_stop_threads);
 
index 48c44c8fdb28e9e3470f72086f6eb40a2451cf2e..26cf5486edd61462028176c952afddf3e81f9b54 100644 (file)
@@ -62,6 +62,7 @@
 /*******************************************************************************
  *  include files
  ******************************************************************************/
+#include <linux/string.h>
 #include <wl_version.h>
 
 #include <debug.h>
index 6d96d03cf4909877f89936f1571b6efadfad3665..fa658c38001e6e7e6bce3cfd68dfa5c54f3996d7 100644 (file)
@@ -2,6 +2,6 @@
 extern void register_wlags_sysfs(struct net_device *);
 extern void unregister_wlags_sysfs(struct net_device *);
 #else
-static void register_wlags_sysfs(struct net_device *) { return; };
-static void unregister_wlags_sysfs(struct net_device *) { return; };
+static inline void register_wlags_sysfs(struct net_device *net) { }
+static inline void unregister_wlags_sysfs(struct net_device *net) { }
 #endif
index de98a94d18537835fafad621fe213c78bba00a61..a6bd53ace03565a6a1131168b240c56f4974ecb4 100644 (file)
@@ -1272,8 +1272,7 @@ static int usb_resume_both(struct usb_device *udev, pm_message_t msg)
 
 static void choose_wakeup(struct usb_device *udev, pm_message_t msg)
 {
-       int                     w, i;
-       struct usb_interface    *intf;
+       int     w;
 
        /* Remote wakeup is needed only when we actually go to sleep.
         * For things like FREEZE and QUIESCE, if the device is already
@@ -1285,16 +1284,10 @@ static void choose_wakeup(struct usb_device *udev, pm_message_t msg)
                return;
        }
 
-       /* If remote wakeup is permitted, see whether any interface drivers
+       /* Enable remote wakeup if it is allowed, even if no interface drivers
         * actually want it.
         */
-       w = 0;
-       if (device_may_wakeup(&udev->dev) && udev->actconfig) {
-               for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
-                       intf = udev->actconfig->interface[i];
-                       w |= intf->needs_remote_wakeup;
-               }
-       }
+       w = device_may_wakeup(&udev->dev);
 
        /* If the device is autosuspended with the wrong wakeup setting,
         * autoresume now so the setting can be changed.
index a73e08fdab36336fee6f14bacef1c7dd1ec58764..fd4c36ea5e4688971afc9c2f32e3668429d0ae63 100644 (file)
@@ -416,8 +416,11 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
                        /* A length of zero means transfer the whole sg list */
                        len = length;
                        if (len == 0) {
-                               for_each_sg(sg, sg, nents, i)
-                                       len += sg->length;
+                               struct scatterlist      *sg2;
+                               int                     j;
+
+                               for_each_sg(sg, sg2, nents, j)
+                                       len += sg2->length;
                        }
                } else {
                        /*
index 38226e9a371d2d39dcb932a64144372545e75542..95dd4662d6a83acb3153433713c3e48889500f69 100644 (file)
@@ -469,8 +469,7 @@ static int eem_unwrap(struct gether *port,
                                crc = get_unaligned_le32(skb->data + len
                                                        - ETH_FCS_LEN);
                                crc2 = ~crc32_le(~0,
-                                               skb->data,
-                                               skb->len - ETH_FCS_LEN);
+                                               skb->data, len - ETH_FCS_LEN);
                        } else {
                                crc = get_unaligned_be32(skb->data + len
                                                        - ETH_FCS_LEN);
index 7d05a0be5c600c0bc6e3b2beaae8e25298aa7ea2..4ce899c9b1653b2cfd747e65a17b919d0adeae2c 100644 (file)
@@ -321,8 +321,8 @@ struct fsg_dev;
 /* Data shared by all the FSG instances. */
 struct fsg_common {
        struct usb_gadget       *gadget;
-       struct fsg_dev          *fsg;
-       struct fsg_dev          *prev_fsg;
+       struct fsg_dev          *fsg, *new_fsg;
+       wait_queue_head_t       fsg_wait;
 
        /* filesem protects: backing files in use */
        struct rw_semaphore     filesem;
@@ -351,7 +351,6 @@ struct fsg_common {
        enum fsg_state          state;          /* For exception handling */
        unsigned int            exception_req_tag;
 
-       u8                      config, new_config;
        enum data_direction     data_dir;
        u32                     data_size;
        u32                     data_size_from_cmnd;
@@ -595,7 +594,7 @@ static int fsg_setup(struct usb_function *f,
        u16                     w_value = le16_to_cpu(ctrl->wValue);
        u16                     w_length = le16_to_cpu(ctrl->wLength);
 
-       if (!fsg->common->config)
+       if (!fsg_is_set(fsg->common))
                return -EOPNOTSUPP;
 
        switch (ctrl->bRequest) {
@@ -2303,24 +2302,20 @@ static int alloc_request(struct fsg_common *common, struct usb_ep *ep,
        return -ENOMEM;
 }
 
-/*
- * Reset interface setting and re-init endpoint state (toggle etc).
- * Call with altsetting < 0 to disable the interface.  The only other
- * available altsetting is 0, which enables the interface.
- */
-static int do_set_interface(struct fsg_common *common, int altsetting)
+/* Reset interface setting and re-init endpoint state (toggle etc). */
+static int do_set_interface(struct fsg_common *common, struct fsg_dev *new_fsg)
 {
-       int     rc = 0;
-       int     i;
-       const struct usb_endpoint_descriptor    *d;
+       const struct usb_endpoint_descriptor *d;
+       struct fsg_dev *fsg;
+       int i, rc = 0;
 
        if (common->running)
                DBG(common, "reset interface\n");
 
 reset:
        /* Deallocate the requests */
-       if (common->prev_fsg) {
-               struct fsg_dev *fsg = common->prev_fsg;
+       if (common->fsg) {
+               fsg = common->fsg;
 
                for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
                        struct fsg_buffhd *bh = &common->buffhds[i];
@@ -2345,88 +2340,53 @@ reset:
                        fsg->bulk_out_enabled = 0;
                }
 
-               common->prev_fsg = 0;
+               common->fsg = NULL;
+               wake_up(&common->fsg_wait);
        }
 
        common->running = 0;
-       if (altsetting < 0 || rc != 0)
+       if (!new_fsg || rc)
                return rc;
 
-       DBG(common, "set interface %d\n", altsetting);
+       common->fsg = new_fsg;
+       fsg = common->fsg;
 
-       if (fsg_is_set(common)) {
-               struct fsg_dev *fsg = common->fsg;
-               common->prev_fsg = common->fsg;
+       /* Enable the endpoints */
+       d = fsg_ep_desc(common->gadget,
+                       &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc);
+       rc = enable_endpoint(common, fsg->bulk_in, d);
+       if (rc)
+               goto reset;
+       fsg->bulk_in_enabled = 1;
+
+       d = fsg_ep_desc(common->gadget,
+                       &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc);
+       rc = enable_endpoint(common, fsg->bulk_out, d);
+       if (rc)
+               goto reset;
+       fsg->bulk_out_enabled = 1;
+       common->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize);
+       clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
 
-               /* Enable the endpoints */
-               d = fsg_ep_desc(common->gadget,
-                               &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc);
-               rc = enable_endpoint(common, fsg->bulk_in, d);
+       /* Allocate the requests */
+       for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
+               struct fsg_buffhd       *bh = &common->buffhds[i];
+
+               rc = alloc_request(common, fsg->bulk_in, &bh->inreq);
                if (rc)
                        goto reset;
-               fsg->bulk_in_enabled = 1;
-
-               d = fsg_ep_desc(common->gadget,
-                               &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc);
-               rc = enable_endpoint(common, fsg->bulk_out, d);
+               rc = alloc_request(common, fsg->bulk_out, &bh->outreq);
                if (rc)
                        goto reset;
-               fsg->bulk_out_enabled = 1;
-               common->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize);
-               clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
-
-               /* Allocate the requests */
-               for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
-                       struct fsg_buffhd       *bh = &common->buffhds[i];
-
-                       rc = alloc_request(common, fsg->bulk_in, &bh->inreq);
-                       if (rc)
-                               goto reset;
-                       rc = alloc_request(common, fsg->bulk_out, &bh->outreq);
-                       if (rc)
-                               goto reset;
-                       bh->inreq->buf = bh->outreq->buf = bh->buf;
-                       bh->inreq->context = bh->outreq->context = bh;
-                       bh->inreq->complete = bulk_in_complete;
-                       bh->outreq->complete = bulk_out_complete;
-               }
-
-               common->running = 1;
-               for (i = 0; i < common->nluns; ++i)
-                       common->luns[i].unit_attention_data = SS_RESET_OCCURRED;
-               return rc;
-       } else {
-               return -EIO;
-       }
-}
-
-
-/*
- * Change our operational configuration.  This code must agree with the code
- * that returns config descriptors, and with interface altsetting code.
- *
- * It's also responsible for power management interactions.  Some
- * configurations might not work with our current power sources.
- * For now we just assume the gadget is always self-powered.
- */
-static int do_set_config(struct fsg_common *common, u8 new_config)
-{
-       int     rc = 0;
-
-       /* Disable the single interface */
-       if (common->config != 0) {
-               DBG(common, "reset config\n");
-               common->config = 0;
-               rc = do_set_interface(common, -1);
+               bh->inreq->buf = bh->outreq->buf = bh->buf;
+               bh->inreq->context = bh->outreq->context = bh;
+               bh->inreq->complete = bulk_in_complete;
+               bh->outreq->complete = bulk_out_complete;
        }
 
-       /* Enable the interface */
-       if (new_config != 0) {
-               common->config = new_config;
-               rc = do_set_interface(common, 0);
-               if (rc != 0)
-                       common->config = 0;     /* Reset on errors */
-       }
+       common->running = 1;
+       for (i = 0; i < common->nluns; ++i)
+               common->luns[i].unit_attention_data = SS_RESET_OCCURRED;
        return rc;
 }
 
@@ -2437,9 +2397,7 @@ static int do_set_config(struct fsg_common *common, u8 new_config)
 static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 {
        struct fsg_dev *fsg = fsg_from_func(f);
-       fsg->common->prev_fsg = fsg->common->fsg;
-       fsg->common->fsg = fsg;
-       fsg->common->new_config = 1;
+       fsg->common->new_fsg = fsg;
        raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
        return 0;
 }
@@ -2447,9 +2405,7 @@ static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 static void fsg_disable(struct usb_function *f)
 {
        struct fsg_dev *fsg = fsg_from_func(f);
-       fsg->common->prev_fsg = fsg->common->fsg;
-       fsg->common->fsg = fsg;
-       fsg->common->new_config = 0;
+       fsg->common->new_fsg = NULL;
        raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
 }
 
@@ -2459,19 +2415,17 @@ static void fsg_disable(struct usb_function *f)
 static void handle_exception(struct fsg_common *common)
 {
        siginfo_t               info;
-       int                     sig;
        int                     i;
        struct fsg_buffhd       *bh;
        enum fsg_state          old_state;
-       u8                      new_config;
        struct fsg_lun          *curlun;
        unsigned int            exception_req_tag;
-       int                     rc;
 
        /* Clear the existing signals.  Anything but SIGUSR1 is converted
         * into a high-priority EXIT exception. */
        for (;;) {
-               sig = dequeue_signal_lock(current, &current->blocked, &info);
+               int sig =
+                       dequeue_signal_lock(current, &current->blocked, &info);
                if (!sig)
                        break;
                if (sig != SIGUSR1) {
@@ -2482,7 +2436,7 @@ static void handle_exception(struct fsg_common *common)
        }
 
        /* Cancel all the pending transfers */
-       if (fsg_is_set(common)) {
+       if (likely(common->fsg)) {
                for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
                        bh = &common->buffhds[i];
                        if (bh->inreq_busy)
@@ -2523,7 +2477,6 @@ static void handle_exception(struct fsg_common *common)
        common->next_buffhd_to_fill = &common->buffhds[0];
        common->next_buffhd_to_drain = &common->buffhds[0];
        exception_req_tag = common->exception_req_tag;
-       new_config = common->new_config;
        old_state = common->state;
 
        if (old_state == FSG_STATE_ABORT_BULK_OUT)
@@ -2573,12 +2526,12 @@ static void handle_exception(struct fsg_common *common)
                break;
 
        case FSG_STATE_CONFIG_CHANGE:
-               rc = do_set_config(common, new_config);
+               do_set_interface(common, common->new_fsg);
                break;
 
        case FSG_STATE_EXIT:
        case FSG_STATE_TERMINATED:
-               do_set_config(common, 0);               /* Free resources */
+               do_set_interface(common, NULL);         /* Free resources */
                spin_lock_irq(&common->lock);
                common->state = FSG_STATE_TERMINATED;   /* Stop the thread */
                spin_unlock_irq(&common->lock);
@@ -2863,6 +2816,7 @@ buffhds_first_it:
                goto error_release;
        }
        init_completion(&common->thread_notifier);
+       init_waitqueue_head(&common->fsg_wait);
 #undef OR
 
 
@@ -2957,9 +2911,17 @@ static void fsg_common_release(struct kref *ref)
 static void fsg_unbind(struct usb_configuration *c, struct usb_function *f)
 {
        struct fsg_dev          *fsg = fsg_from_func(f);
+       struct fsg_common       *common = fsg->common;
 
        DBG(fsg, "unbind\n");
-       fsg_common_put(fsg->common);
+       if (fsg->common->fsg == fsg) {
+               fsg->common->new_fsg = NULL;
+               raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
+               /* FIXME: make interruptible or killable somehow? */
+               wait_event(common->fsg_wait, common->fsg != fsg);
+       }
+
+       fsg_common_put(common);
        usb_free_descriptors(fsg->function.descriptors);
        usb_free_descriptors(fsg->function.hs_descriptors);
        kfree(fsg);
@@ -2970,7 +2932,6 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
 {
        struct fsg_dev          *fsg = fsg_from_func(f);
        struct usb_gadget       *gadget = c->cdev->gadget;
-       int                     rc;
        int                     i;
        struct usb_ep           *ep;
 
@@ -2996,6 +2957,11 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
        ep->driver_data = fsg->common;  /* claim the endpoint */
        fsg->bulk_out = ep;
 
+       /* Copy descriptors */
+       f->descriptors = usb_copy_descriptors(fsg_fs_function);
+       if (unlikely(!f->descriptors))
+               return -ENOMEM;
+
        if (gadget_is_dualspeed(gadget)) {
                /* Assume endpoint addresses are the same for both speeds */
                fsg_hs_bulk_in_desc.bEndpointAddress =
@@ -3003,16 +2969,17 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
                fsg_hs_bulk_out_desc.bEndpointAddress =
                        fsg_fs_bulk_out_desc.bEndpointAddress;
                f->hs_descriptors = usb_copy_descriptors(fsg_hs_function);
-               if (unlikely(!f->hs_descriptors))
+               if (unlikely(!f->hs_descriptors)) {
+                       usb_free_descriptors(f->descriptors);
                        return -ENOMEM;
+               }
        }
 
        return 0;
 
 autoconf_fail:
        ERROR(fsg, "unable to autoconfigure all endpoints\n");
-       rc = -ENOTSUPP;
-       return rc;
+       return -ENOTSUPP;
 }
 
 
@@ -3036,11 +3003,6 @@ static int fsg_add(struct usb_composite_dev *cdev,
 
        fsg->function.name        = FSG_DRIVER_DESC;
        fsg->function.strings     = fsg_strings_array;
-       fsg->function.descriptors = usb_copy_descriptors(fsg_fs_function);
-       if (unlikely(!fsg->function.descriptors)) {
-               rc = -ENOMEM;
-               goto error_free_fsg;
-       }
        fsg->function.bind        = fsg_bind;
        fsg->function.unbind      = fsg_unbind;
        fsg->function.setup       = fsg_setup;
@@ -3056,19 +3018,9 @@ static int fsg_add(struct usb_composite_dev *cdev,
 
        rc = usb_add_function(c, &fsg->function);
        if (unlikely(rc))
-               goto error_free_all;
-
-       fsg_common_get(fsg->common);
-       return 0;
-
-error_free_all:
-       usb_free_descriptors(fsg->function.descriptors);
-       /* fsg_bind() might have copied those; or maybe not? who cares
-        * -- free it just in case. */
-       usb_free_descriptors(fsg->function.hs_descriptors);
-error_free_fsg:
-       kfree(fsg);
-
+               kfree(fsg);
+       else
+               fsg_common_get(fsg->common);
        return rc;
 }
 
index 4b0e4a040d6f7a1c134404ef253c3756caf85388..d1af253a910591fabacf1669a66749b5dbc7e1f5 100644 (file)
@@ -392,6 +392,17 @@ static int __gfs_do_config(struct usb_configuration *c,
        if (unlikely(ret < 0))
                return ret;
 
+       /* After previous do_configs there may be some invalid
+        * pointers in c->interface array.  This happens every time
+        * a user space function with fewer interfaces than a user
+        * space function that was run before the new one is run.  The
+        * compasit's set_config() assumes that if there is no more
+        * then MAX_CONFIG_INTERFACES interfaces in a configuration
+        * then there is a NULL pointer after the last interface in
+        * c->interface array.  We need to make sure this is true. */
+       if (c->next_interface_id < ARRAY_SIZE(c->interface))
+               c->interface[c->next_interface_id] = NULL;
+
        return 0;
 }
 
index 43abf55d8c60fcbc7029d4a0d4545188b9ab4308..4c3ac5c422373e6494db8ff82c03cdb208d130ea 100644 (file)
@@ -82,7 +82,7 @@ static struct class *usb_gadget_class;
 struct printer_dev {
        spinlock_t              lock;           /* lock this structure */
        /* lock buffer lists during read/write calls */
-       spinlock_t              lock_printer_io;
+       struct mutex            lock_printer_io;
        struct usb_gadget       *gadget;
        struct usb_request      *req;           /* for control responses */
        u8                      config;
@@ -567,7 +567,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
 
        DBG(dev, "printer_read trying to read %d bytes\n", (int)len);
 
-       spin_lock(&dev->lock_printer_io);
+       mutex_lock(&dev->lock_printer_io);
        spin_lock_irqsave(&dev->lock, flags);
 
        /* We will use this flag later to check if a printer reset happened
@@ -601,7 +601,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
                 * call or not.
                 */
                if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) {
-                       spin_unlock(&dev->lock_printer_io);
+                       mutex_unlock(&dev->lock_printer_io);
                        return -EAGAIN;
                }
 
@@ -648,7 +648,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
                if (dev->reset_printer) {
                        list_add(&current_rx_req->list, &dev->rx_reqs);
                        spin_unlock_irqrestore(&dev->lock, flags);
-                       spin_unlock(&dev->lock_printer_io);
+                       mutex_unlock(&dev->lock_printer_io);
                        return -EAGAIN;
                }
 
@@ -673,7 +673,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
        dev->current_rx_buf = current_rx_buf;
 
        spin_unlock_irqrestore(&dev->lock, flags);
-       spin_unlock(&dev->lock_printer_io);
+       mutex_unlock(&dev->lock_printer_io);
 
        DBG(dev, "printer_read returned %d bytes\n", (int)bytes_copied);
 
@@ -697,7 +697,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
        if (len == 0)
                return -EINVAL;
 
-       spin_lock(&dev->lock_printer_io);
+       mutex_lock(&dev->lock_printer_io);
        spin_lock_irqsave(&dev->lock, flags);
 
        /* Check if a printer reset happens while we have interrupts on */
@@ -713,7 +713,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
                 * a NON-Blocking call or not.
                 */
                if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) {
-                       spin_unlock(&dev->lock_printer_io);
+                       mutex_unlock(&dev->lock_printer_io);
                        return -EAGAIN;
                }
 
@@ -752,7 +752,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
 
                if (copy_from_user(req->buf, buf, size)) {
                        list_add(&req->list, &dev->tx_reqs);
-                       spin_unlock(&dev->lock_printer_io);
+                       mutex_unlock(&dev->lock_printer_io);
                        return bytes_copied;
                }
 
@@ -766,14 +766,14 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
                if (dev->reset_printer) {
                        list_add(&req->list, &dev->tx_reqs);
                        spin_unlock_irqrestore(&dev->lock, flags);
-                       spin_unlock(&dev->lock_printer_io);
+                       mutex_unlock(&dev->lock_printer_io);
                        return -EAGAIN;
                }
 
                if (usb_ep_queue(dev->in_ep, req, GFP_ATOMIC)) {
                        list_add(&req->list, &dev->tx_reqs);
                        spin_unlock_irqrestore(&dev->lock, flags);
-                       spin_unlock(&dev->lock_printer_io);
+                       mutex_unlock(&dev->lock_printer_io);
                        return -EAGAIN;
                }
 
@@ -782,7 +782,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
        }
 
        spin_unlock_irqrestore(&dev->lock, flags);
-       spin_unlock(&dev->lock_printer_io);
+       mutex_unlock(&dev->lock_printer_io);
 
        DBG(dev, "printer_write sent %d bytes\n", (int)bytes_copied);
 
@@ -820,11 +820,11 @@ printer_poll(struct file *fd, poll_table *wait)
        unsigned long           flags;
        int                     status = 0;
 
-       spin_lock(&dev->lock_printer_io);
+       mutex_lock(&dev->lock_printer_io);
        spin_lock_irqsave(&dev->lock, flags);
        setup_rx_reqs(dev);
        spin_unlock_irqrestore(&dev->lock, flags);
-       spin_unlock(&dev->lock_printer_io);
+       mutex_unlock(&dev->lock_printer_io);
 
        poll_wait(fd, &dev->rx_wait, wait);
        poll_wait(fd, &dev->tx_wait, wait);
@@ -1461,7 +1461,7 @@ autoconf_fail:
        }
 
        spin_lock_init(&dev->lock);
-       spin_lock_init(&dev->lock_printer_io);
+       mutex_init(&dev->lock_printer_io);
        INIT_LIST_HEAD(&dev->tx_reqs);
        INIT_LIST_HEAD(&dev->tx_reqs_active);
        INIT_LIST_HEAD(&dev->rx_reqs);
@@ -1594,7 +1594,7 @@ cleanup(void)
 {
        int status;
 
-       spin_lock(&usb_printer_gadget.lock_printer_io);
+       mutex_lock(&usb_printer_gadget.lock_printer_io);
        class_destroy(usb_gadget_class);
        unregister_chrdev_region(g_printer_devno, 2);
 
@@ -1602,6 +1602,6 @@ cleanup(void)
        if (status)
                ERROR(dev, "usb_gadget_unregister_driver %x\n", status);
 
-       spin_unlock(&usb_printer_gadget.lock_printer_io);
+       mutex_unlock(&usb_printer_gadget.lock_printer_io);
 }
 module_exit(cleanup);
index d5f4c1d45c9703add01e29e582e5f705e87cc83f..e724a051bfdd11bcd520ae90ff0b0c448883d13f 100644 (file)
@@ -1700,9 +1700,13 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
        if (!driver || driver != udc->driver || !driver->unbind)
                return -EINVAL;
 
-       dprintk(DEBUG_NORMAL,"usb_gadget_register_driver() '%s'\n",
+       dprintk(DEBUG_NORMAL, "usb_gadget_unregister_driver() '%s'\n",
                driver->driver.name);
 
+       /* report disconnect */
+       if (driver->disconnect)
+               driver->disconnect(&udc->gadget);
+
        driver->unbind(&udc->gadget);
 
        device_del(&udc->gadget.dev);
index 16bdf77f582a02526f2b60750e26dbfb2e425228..3e8dcb5455e3a4912f7bc0fc525b69c524cade7f 100644 (file)
@@ -536,17 +536,11 @@ recycle:
                list_move(&req->list, &port->read_pool);
        }
 
-       /* Push from tty to ldisc; this is immediate with low_latency, and
-        * may trigger callbacks to this driver ... so drop the spinlock.
+       /* Push from tty to ldisc; without low_latency set this is handled by
+        * a workqueue, so we won't get callbacks and can hold port_lock
         */
        if (tty && do_push) {
-               spin_unlock_irq(&port->port_lock);
                tty_flip_buffer_push(tty);
-               wake_up_interruptible(&tty->read_wait);
-               spin_lock_irq(&port->port_lock);
-
-               /* tty may have been closed */
-               tty = port->port_tty;
        }
 
 
@@ -784,11 +778,6 @@ static int gs_open(struct tty_struct *tty, struct file *file)
        port->open_count = 1;
        port->openclose = false;
 
-       /* low_latency means ldiscs work in tasklet context, without
-        * needing a workqueue schedule ... easier to keep up.
-        */
-       tty->low_latency = 1;
-
        /* if connected, start the I/O stream */
        if (port->port_usb) {
                struct gserial  *gser = port->port_usb;
@@ -1195,6 +1184,7 @@ void gserial_cleanup(void)
        n_ports = 0;
 
        tty_unregister_driver(gs_tty_driver);
+       put_tty_driver(gs_tty_driver);
        gs_tty_driver = NULL;
 
        pr_debug("%s: cleaned up ttyGS* support\n", __func__);
index 544ccfd7056ed5ff13d7a3daea6178d22e9efbd6..bd4027745aa7039e5cfcdd6b1bf4057ad8569d85 100644 (file)
@@ -207,10 +207,17 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
        /* Initialize the transceiver */
        if (pdata->otg) {
                pdata->otg->io_priv = hcd->regs + ULPI_VIEWPORT_OFFSET;
-               if (otg_init(pdata->otg) != 0)
-                       dev_err(dev, "unable to init transceiver\n");
-               else if (otg_set_vbus(pdata->otg, 1) != 0)
+               ret = otg_init(pdata->otg);
+               if (ret) {
+                       dev_err(dev, "unable to init transceiver, probably missing\n");
+                       ret = -ENODEV;
+                       goto err_add;
+               }
+               ret = otg_set_vbus(pdata->otg, 1);
+               if (ret) {
                        dev_err(dev, "unable to enable vbus on transceiver\n");
+                       goto err_add;
+               }
        }
 
        priv->hcd = hcd;
index 20a0dfe0fe368c7f6284f82df2080e19b69935a8..0587ad4ce5c2948500dbd339b5d03f322b905fb6 100644 (file)
@@ -2224,12 +2224,9 @@ static void remove_debug_file(struct isp1362_hcd *isp1362_hcd)
 
 /*-------------------------------------------------------------------------*/
 
-static void isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd)
+static void __isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd)
 {
        int tmp = 20;
-       unsigned long flags;
-
-       spin_lock_irqsave(&isp1362_hcd->lock, flags);
 
        isp1362_write_reg16(isp1362_hcd, HCSWRES, HCSWRES_MAGIC);
        isp1362_write_reg32(isp1362_hcd, HCCMDSTAT, OHCI_HCR);
@@ -2240,6 +2237,14 @@ static void isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd)
        }
        if (!tmp)
                pr_err("Software reset timeout\n");
+}
+
+static void isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&isp1362_hcd->lock, flags);
+       __isp1362_sw_reset(isp1362_hcd);
        spin_unlock_irqrestore(&isp1362_hcd->lock, flags);
 }
 
@@ -2418,7 +2423,7 @@ static void isp1362_hc_stop(struct usb_hcd *hcd)
        if (isp1362_hcd->board && isp1362_hcd->board->reset)
                isp1362_hcd->board->reset(hcd->self.controller, 1);
        else
-               isp1362_sw_reset(isp1362_hcd);
+               __isp1362_sw_reset(isp1362_hcd);
 
        if (isp1362_hcd->board && isp1362_hcd->board->clock)
                isp1362_hcd->board->clock(hcd->self.controller, 0);
index 1a2bb4ce638fefe0c1fa6ff2151c32f5fe685528..77be3c24a4279d0aca3cc268164cf20960e135f5 100644 (file)
@@ -1065,7 +1065,7 @@ static void r8a66597_usb_connect(struct r8a66597 *r8a66597, int port)
        else if (speed == LSMODE)
                rh->port |= USB_PORT_STAT_LOW_SPEED;
 
-       rh->port &= USB_PORT_STAT_RESET;
+       rh->port &= ~USB_PORT_STAT_RESET;
        rh->port |= USB_PORT_STAT_ENABLE;
 }
 
index 9012098add6baefada9cd6155d57be8f9708afd7..94e6934edb09c0e3a06dd696a96c3d825719ede6 100644 (file)
@@ -182,8 +182,12 @@ static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer
  * set, but other sections talk about dealing with the chain bit set.  This was
  * fixed in the 0.96 specification errata, but we have to assume that all 0.95
  * xHCI hardware can't handle the chain bit being cleared on a link TRB.
+ *
+ * @more_trbs_coming:  Will you enqueue more TRBs before calling
+ *                     prepare_transfer()?
  */
-static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer)
+static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring,
+               bool consumer, bool more_trbs_coming)
 {
        u32 chain;
        union xhci_trb *next;
@@ -199,15 +203,28 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer
        while (last_trb(xhci, ring, ring->enq_seg, next)) {
                if (!consumer) {
                        if (ring != xhci->event_ring) {
-                               if (chain) {
-                                       next->link.control |= TRB_CHAIN;
-
-                                       /* Give this link TRB to the hardware */
-                                       wmb();
-                                       next->link.control ^= TRB_CYCLE;
-                               } else {
+                               /*
+                                * If the caller doesn't plan on enqueueing more
+                                * TDs before ringing the doorbell, then we
+                                * don't want to give the link TRB to the
+                                * hardware just yet.  We'll give the link TRB
+                                * back in prepare_ring() just before we enqueue
+                                * the TD at the top of the ring.
+                                */
+                               if (!chain && !more_trbs_coming)
                                        break;
+
+                               /* If we're not dealing with 0.95 hardware,
+                                * carry over the chain bit of the previous TRB
+                                * (which may mean the chain bit is cleared).
+                                */
+                               if (!xhci_link_trb_quirk(xhci)) {
+                                       next->link.control &= ~TRB_CHAIN;
+                                       next->link.control |= chain;
                                }
+                               /* Give this link TRB to the hardware */
+                               wmb();
+                               next->link.control ^= TRB_CYCLE;
                        }
                        /* Toggle the cycle bit after the last ring segment. */
                        if (last_trb_on_last_seg(xhci, ring, ring->enq_seg, next)) {
@@ -1707,9 +1724,12 @@ void xhci_handle_event(struct xhci_hcd *xhci)
 /*
  * Generic function for queueing a TRB on a ring.
  * The caller must have checked to make sure there's room on the ring.
+ *
+ * @more_trbs_coming:  Will you enqueue more TRBs before calling
+ *                     prepare_transfer()?
  */
 static void queue_trb(struct xhci_hcd *xhci, struct xhci_ring *ring,
-               bool consumer,
+               bool consumer, bool more_trbs_coming,
                u32 field1, u32 field2, u32 field3, u32 field4)
 {
        struct xhci_generic_trb *trb;
@@ -1719,7 +1739,7 @@ static void queue_trb(struct xhci_hcd *xhci, struct xhci_ring *ring,
        trb->field[1] = field2;
        trb->field[2] = field3;
        trb->field[3] = field4;
-       inc_enq(xhci, ring, consumer);
+       inc_enq(xhci, ring, consumer, more_trbs_coming);
 }
 
 /*
@@ -1988,6 +2008,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
        int trb_buff_len, this_sg_len, running_total;
        bool first_trb;
        u64 addr;
+       bool more_trbs_coming;
 
        struct xhci_generic_trb *start_trb;
        int start_cycle;
@@ -2073,7 +2094,11 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                length_field = TRB_LEN(trb_buff_len) |
                        remainder |
                        TRB_INTR_TARGET(0);
-               queue_trb(xhci, ep_ring, false,
+               if (num_trbs > 1)
+                       more_trbs_coming = true;
+               else
+                       more_trbs_coming = false;
+               queue_trb(xhci, ep_ring, false, more_trbs_coming,
                                lower_32_bits(addr),
                                upper_32_bits(addr),
                                length_field,
@@ -2124,6 +2149,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
        int num_trbs;
        struct xhci_generic_trb *start_trb;
        bool first_trb;
+       bool more_trbs_coming;
        int start_cycle;
        u32 field, length_field;
 
@@ -2212,7 +2238,11 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                length_field = TRB_LEN(trb_buff_len) |
                        remainder |
                        TRB_INTR_TARGET(0);
-               queue_trb(xhci, ep_ring, false,
+               if (num_trbs > 1)
+                       more_trbs_coming = true;
+               else
+                       more_trbs_coming = false;
+               queue_trb(xhci, ep_ring, false, more_trbs_coming,
                                lower_32_bits(addr),
                                upper_32_bits(addr),
                                length_field,
@@ -2291,7 +2321,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
        /* Queue setup TRB - see section 6.4.1.2.1 */
        /* FIXME better way to translate setup_packet into two u32 fields? */
        setup = (struct usb_ctrlrequest *) urb->setup_packet;
-       queue_trb(xhci, ep_ring, false,
+       queue_trb(xhci, ep_ring, false, true,
                        /* FIXME endianness is probably going to bite my ass here. */
                        setup->bRequestType | setup->bRequest << 8 | setup->wValue << 16,
                        setup->wIndex | setup->wLength << 16,
@@ -2307,7 +2337,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
        if (urb->transfer_buffer_length > 0) {
                if (setup->bRequestType & USB_DIR_IN)
                        field |= TRB_DIR_IN;
-               queue_trb(xhci, ep_ring, false,
+               queue_trb(xhci, ep_ring, false, true,
                                lower_32_bits(urb->transfer_dma),
                                upper_32_bits(urb->transfer_dma),
                                length_field,
@@ -2324,7 +2354,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                field = 0;
        else
                field = TRB_DIR_IN;
-       queue_trb(xhci, ep_ring, false,
+       queue_trb(xhci, ep_ring, false, false,
                        0,
                        0,
                        TRB_INTR_TARGET(0),
@@ -2361,7 +2391,7 @@ static int queue_command(struct xhci_hcd *xhci, u32 field1, u32 field2,
                                        "unfailable commands failed.\n");
                return -ENOMEM;
        }
-       queue_trb(xhci, xhci->cmd_ring, false, field1, field2, field3,
+       queue_trb(xhci, xhci->cmd_ring, false, false, field1, field2, field3,
                        field4 | xhci->cmd_ring->cycle_state);
        return 0;
 }
index fad70bc835558a501e0f06a615237e07be4197e0..3b795c56221f8c30f757fe9420eea7424dc2d804 100644 (file)
@@ -219,8 +219,8 @@ static int musb_ulpi_write(struct otg_transceiver *otg,
        return 0;
 }
 #else
-#define musb_ulpi_read(a, b)           NULL
-#define musb_ulpi_write(a, b, c)       NULL
+#define musb_ulpi_read         NULL
+#define musb_ulpi_write                NULL
 #endif
 
 static struct otg_io_access_ops musb_ulpi_access = {
@@ -451,10 +451,6 @@ void musb_hnp_stop(struct musb *musb)
  * @param power
  */
 
-#define STAGE0_MASK (MUSB_INTR_RESUME | MUSB_INTR_SESSREQ \
-               | MUSB_INTR_VBUSERROR | MUSB_INTR_CONNECT \
-               | MUSB_INTR_RESET)
-
 static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
                                u8 devctl, u8 power)
 {
@@ -642,7 +638,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
                handled = IRQ_HANDLED;
        }
 
-
+#endif
        if (int_usb & MUSB_INTR_SUSPEND) {
                DBG(1, "SUSPEND (%s) devctl %02x power %02x\n",
                                otg_state_string(musb), devctl, power);
@@ -705,6 +701,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
                }
        }
 
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
        if (int_usb & MUSB_INTR_CONNECT) {
                struct usb_hcd *hcd = musb_to_hcd(musb);
                void __iomem *mbase = musb->mregs;
@@ -1597,7 +1594,7 @@ irqreturn_t musb_interrupt(struct musb *musb)
        /* the core can interrupt us for multiple reasons; docs have
         * a generic interrupt flowchart to follow
         */
-       if (musb->int_usb & STAGE0_MASK)
+       if (musb->int_usb)
                retval |= musb_stage0_irq(musb, musb->int_usb,
                                devctl, power);
 
index b22d02dea7d361698e830efa3919df3802a5b3b4..91d67794e3503eeeb982c8c85e537e48c7d15394 100644 (file)
@@ -470,7 +470,8 @@ struct musb_csr_regs {
 
 struct musb_context_registers {
 
-#ifdef CONFIG_PM
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \
+    defined(CONFIG_ARCH_OMAP4)
        u32 otg_sysconfig, otg_forcestandby;
 #endif
        u8 power;
@@ -484,7 +485,8 @@ struct musb_context_registers {
        struct musb_csr_regs index_regs[MUSB_C_NUM_EPS];
 };
 
-#ifdef CONFIG_PM
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \
+    defined(CONFIG_ARCH_OMAP4)
 extern void musb_platform_save_context(struct musb *musb,
                struct musb_context_registers *musb_context);
 extern void musb_platform_restore_context(struct musb *musb,
index 1008044a3bbc38efc580ae72211fd7a33b29d4d3..dc66e4376d4906a4454b90a393851cd72631aefa 100644 (file)
@@ -132,18 +132,9 @@ static void configure_channel(struct dma_channel *channel,
        if (mode) {
                csr |= 1 << MUSB_HSDMA_MODE1_SHIFT;
                BUG_ON(len < packet_sz);
-
-               if (packet_sz >= 64) {
-                       csr |= MUSB_HSDMA_BURSTMODE_INCR16
-                                       << MUSB_HSDMA_BURSTMODE_SHIFT;
-               } else if (packet_sz >= 32) {
-                       csr |= MUSB_HSDMA_BURSTMODE_INCR8
-                                       << MUSB_HSDMA_BURSTMODE_SHIFT;
-               } else if (packet_sz >= 16) {
-                       csr |= MUSB_HSDMA_BURSTMODE_INCR4
-                                       << MUSB_HSDMA_BURSTMODE_SHIFT;
-               }
        }
+       csr |= MUSB_HSDMA_BURSTMODE_INCR16
+                               << MUSB_HSDMA_BURSTMODE_SHIFT;
 
        csr |= (musb_channel->epnum << MUSB_HSDMA_ENDPOINT_SHIFT)
                | (1 << MUSB_HSDMA_ENABLE_SHIFT)
index b1b346932946d447dcf11b1ddcb952edd49acaab..d331b222ad214cdd43e815761eb08a3c300e8196 100644 (file)
@@ -59,12 +59,17 @@ static int ulpi_set_flags(struct otg_transceiver *otg)
 
 static int ulpi_init(struct otg_transceiver *otg)
 {
-       int i, vid, pid;
-
-       vid = (otg_io_read(otg, ULPI_VENDOR_ID_HIGH) << 8) |
-              otg_io_read(otg, ULPI_VENDOR_ID_LOW);
-       pid = (otg_io_read(otg, ULPI_PRODUCT_ID_HIGH) << 8) |
-              otg_io_read(otg, ULPI_PRODUCT_ID_LOW);
+       int i, vid, pid, ret;
+       u32 ulpi_id = 0;
+
+       for (i = 0; i < 4; i++) {
+               ret = otg_io_read(otg, ULPI_PRODUCT_ID_HIGH - i);
+               if (ret < 0)
+                       return ret;
+               ulpi_id = (ulpi_id << 8) | ret;
+       }
+       vid = ulpi_id & 0xffff;
+       pid = ulpi_id >> 16;
 
        pr_info("ULPI transceiver vendor/product ID 0x%04x/0x%04x\n", vid, pid);
 
index 79dd1ae195e56263610c63c1d3da6e7bb71b1de5..da7e334b0407a3ef0e210a56dcc02ea3f2a14db8 100644 (file)
@@ -653,7 +653,6 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) },
        { USB_DEVICE(EVOLUTION_VID, EVO_HYBRID_PID) },
        { USB_DEVICE(EVOLUTION_VID, EVO_RCM4_PID) },
-       { USB_DEVICE(CONTEC_VID, CONTEC_COM1USBH_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_ARTEMIS_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16C_PID) },
index 94d86c3febcb8e0ad67ba11b105822e8d25ba17a..bbc159a1df45d330f926a6e003dadece3c1b4daa 100644 (file)
 #define CONTEC_VID             0x06CE  /* Vendor ID */
 #define CONTEC_COM1USBH_PID    0x8311  /* COM-1(USB)H */
 
-/*
- * Contec products (http://www.contec.com)
- * Submitted by Daniel Sangorrin
- */
-#define CONTEC_VID             0x06CE  /* Vendor ID */
-#define CONTEC_COM1USBH_PID    0x8311  /* COM-1(USB)H */
-
 /*
  * Definitions for B&B Electronics products.
  */
index 04bb759536bb81f6e41ecc2b4537e5e2e0b2790f..93d72eb8cafc8deaa36a52e2632a6cee3429ce66 100644 (file)
@@ -139,6 +139,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
                                        "Could not set interface, error %d\n",
                                        retval);
                                retval = -ENODEV;
+                               kfree(data);
                        }
                        return retval;
                }
@@ -155,6 +156,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
                                        "Could not set interface, error %d\n",
                                        retval);
                                retval = -ENODEV;
+                               kfree(data);
                        }
                        return retval;
                }
@@ -163,6 +165,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
        default:
                dev_err(&serial->dev->dev,
                        "unknown number of interfaces: %d\n", nintf);
+               kfree(data);
                return -ENODEV;
        }
 
index 76e7dac6f25901843da1717d6fb55a3c721a8e16..70b1d9d51c9601e2c4c338f58d29f7d4f59214dd 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 1a18da86d3fa3cbde2b899831ec136a178527340..39bdbedf43b481253e7eb3586d15050c83abb94c 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 d4cde79ea15e61362a34736179520053d68383bc..81687ed26ba9ed55d761b550d1df59b59ce371a9 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 b6ab27ccf214fc8c406a9ef70e91d7930af0eaec..811384bec8de8d486a9aa7355d49b0195995e97a 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 d96047b4a633a86cb7ae711cb29362ac6cda061a..c8c78ba078271163f567c26045afff6cf0b5cd71 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 51e11bf5708f2430cca213485d597ff070f228af..9d175d623aabc5e7c99a83e75e6c970a340465c6 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 1d1088f48bc2dfe713d53a9af0fa4d51e1161428..0609607d395591ad5b23ee52283ad25c85e2bc10 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 46d4b5d72bd33d2e01b9c5e731e8842e616f70f9..cb6306e638435e27a3d883dd84e7fe172029b87f 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 5c35bc7a499e19c97b0f8eba3a91a8224a46ffe4..938119ab8dcbc28f3f9853bc0808d6d70cd51d55 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 bbd69bdb0fa8cc9ccba41fec291fa13af43f796f..fcc498ec9b337afdcb96582fce07734c9a3cb46d 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 076ca50e99336fad10e256ddc3d103ae93fd527a..c8ff0d1ae5d3e04f7f14d8a8b63df33a87b16a35 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 846b75aeb2abe2b260a8efda2a15a73a2b8c18ab..e7839ee49e43656d0d1edfa7011ce8d9eb0e97b2 100644 (file)
@@ -128,13 +128,12 @@ xfs_nfs_get_inode(
                return ERR_PTR(-ESTALE);
 
        /*
-        * The XFS_IGET_BULKSTAT means that an invalid inode number is just
-        * fine and not an indication of a corrupted filesystem.  Because
-        * clients can send any kind of invalid file handle, e.g. after
-        * a restore on the server we have to deal with this case gracefully.
+        * The XFS_IGET_UNTRUSTED means that an invalid inode number is just
+        * fine and not an indication of a corrupted filesystem as clients can
+        * send invalid file handles and we have to handle it gracefully..
         */
-       error = xfs_iget(mp, NULL, ino, XFS_IGET_BULKSTAT,
-                        XFS_ILOCK_SHARED, &ip, 0);
+       error = xfs_iget(mp, NULL, ino, XFS_IGET_UNTRUSTED,
+                        XFS_ILOCK_SHARED, &ip);
        if (error) {
                /*
                 * EINVAL means the inode cluster doesn't exist anymore.
index 699b60cbab9c0da98deb5ca1f1b5839ee726d4b2..e59a8106283069b24bb9fb4b5f0ea5bec92d8ede 100644 (file)
@@ -679,10 +679,9 @@ xfs_ioc_bulkstat(
                error = xfs_bulkstat_single(mp, &inlast,
                                                bulkreq.ubuffer, &done);
        else    /* XFS_IOC_FSBULKSTAT */
-               error = xfs_bulkstat(mp, &inlast, &count,
-                       (bulkstat_one_pf)xfs_bulkstat_one, NULL,
-                       sizeof(xfs_bstat_t), bulkreq.ubuffer,
-                       BULKSTAT_FG_QUICK, &done);
+               error = xfs_bulkstat(mp, &inlast, &count, xfs_bulkstat_one,
+                                    sizeof(xfs_bstat_t), bulkreq.ubuffer,
+                                    &done);
 
        if (error)
                return -error;
index 9287135e9bfcedf7ab0f563d5c14bfe9d309e8e5..52ed49e6465cff0eee12844c13b169583cc1411c 100644 (file)
@@ -237,15 +237,12 @@ xfs_bulkstat_one_compat(
        xfs_ino_t       ino,            /* inode number to get data for */
        void            __user *buffer, /* buffer to place output in */
        int             ubsize,         /* size of buffer */
-       void            *private_data,  /* my private data */
-       xfs_daddr_t     bno,            /* starting bno of inode cluster */
        int             *ubused,        /* bytes used by me */
-       void            *dibuff,        /* on-disk inode buffer */
        int             *stat)          /* BULKSTAT_RV_... */
 {
        return xfs_bulkstat_one_int(mp, ino, buffer, ubsize,
-                                   xfs_bulkstat_one_fmt_compat, bno,
-                                   ubused, dibuff, stat);
+                                   xfs_bulkstat_one_fmt_compat,
+                                   ubused, stat);
 }
 
 /* copied from xfs_ioctl.c */
@@ -298,13 +295,11 @@ xfs_compat_ioc_bulkstat(
                int res;
 
                error = xfs_bulkstat_one_compat(mp, inlast, bulkreq.ubuffer,
-                               sizeof(compat_xfs_bstat_t),
-                               NULL, 0, NULL, NULL, &res);
+                               sizeof(compat_xfs_bstat_t), 0, &res);
        } else if (cmd == XFS_IOC_FSBULKSTAT_32) {
                error = xfs_bulkstat(mp, &inlast, &count,
-                       xfs_bulkstat_one_compat, NULL,
-                       sizeof(compat_xfs_bstat_t), bulkreq.ubuffer,
-                       BULKSTAT_FG_QUICK, &done);
+                       xfs_bulkstat_one_compat, sizeof(compat_xfs_bstat_t),
+                       bulkreq.ubuffer, &done);
        } else
                error = XFS_ERROR(EINVAL);
        if (error)
index 2d8b7bc792c9df93bc505705bec4f957b082866a..8c117ff2e3ab00d8939f7ec596063988faae283f 100644 (file)
@@ -1632,10 +1632,7 @@ xfs_qm_dqusage_adjust(
        xfs_ino_t       ino,            /* inode number to get data for */
        void            __user *buffer, /* not used */
        int             ubsize,         /* not used */
-       void            *private_data,  /* not used */
-       xfs_daddr_t     bno,            /* starting block of inode cluster */
        int             *ubused,        /* not used */
-       void            *dip,           /* on-disk inode pointer (not used) */
        int             *res)           /* result code value */
 {
        xfs_inode_t     *ip;
@@ -1660,7 +1657,7 @@ xfs_qm_dqusage_adjust(
         * the case in all other instances. It's OK that we do this because
         * quotacheck is done only at mount time.
         */
-       if ((error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_EXCL, &ip, bno))) {
+       if ((error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_EXCL, &ip))) {
                *res = BULKSTAT_RV_NOTHING;
                return error;
        }
@@ -1796,12 +1793,13 @@ xfs_qm_quotacheck(
                 * Iterate thru all the inodes in the file system,
                 * adjusting the corresponding dquot counters in core.
                 */
-               if ((error = xfs_bulkstat(mp, &lastino, &count,
-                                    xfs_qm_dqusage_adjust, NULL,
-                                    structsz, NULL, BULKSTAT_FG_IGET, &done)))
+               error = xfs_bulkstat(mp, &lastino, &count,
+                                    xfs_qm_dqusage_adjust,
+                                    structsz, NULL, &done);
+               if (error)
                        break;
 
-       } while (! done);
+       } while (!done);
 
        /*
         * We've made all the changes that we need to make incore.
@@ -1889,14 +1887,14 @@ xfs_qm_init_quotainos(
                    mp->m_sb.sb_uquotino != NULLFSINO) {
                        ASSERT(mp->m_sb.sb_uquotino > 0);
                        if ((error = xfs_iget(mp, NULL, mp->m_sb.sb_uquotino,
-                                            0, 0, &uip, 0)))
+                                            0, 0, &uip)))
                                return XFS_ERROR(error);
                }
                if (XFS_IS_OQUOTA_ON(mp) &&
                    mp->m_sb.sb_gquotino != NULLFSINO) {
                        ASSERT(mp->m_sb.sb_gquotino > 0);
                        if ((error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
-                                            0, 0, &gip, 0))) {
+                                            0, 0, &gip))) {
                                if (uip)
                                        IRELE(uip);
                                return XFS_ERROR(error);
index 92b002f1805fdc85c237ea295728a6bc44dd8986..b4487764e923b7c493aac813e9161764a0f0ccfb 100644 (file)
@@ -262,7 +262,7 @@ xfs_qm_scall_trunc_qfiles(
        }
 
        if ((flags & XFS_DQ_USER) && mp->m_sb.sb_uquotino != NULLFSINO) {
-               error = xfs_iget(mp, NULL, mp->m_sb.sb_uquotino, 0, 0, &qip, 0);
+               error = xfs_iget(mp, NULL, mp->m_sb.sb_uquotino, 0, 0, &qip);
                if (!error) {
                        error = xfs_truncate_file(mp, qip);
                        IRELE(qip);
@@ -271,7 +271,7 @@ xfs_qm_scall_trunc_qfiles(
 
        if ((flags & (XFS_DQ_GROUP|XFS_DQ_PROJ)) &&
            mp->m_sb.sb_gquotino != NULLFSINO) {
-               error2 = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 0, 0, &qip, 0);
+               error2 = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 0, 0, &qip);
                if (!error2) {
                        error2 = xfs_truncate_file(mp, qip);
                        IRELE(qip);
@@ -417,12 +417,12 @@ xfs_qm_scall_getqstat(
        }
        if (!uip && mp->m_sb.sb_uquotino != NULLFSINO) {
                if (xfs_iget(mp, NULL, mp->m_sb.sb_uquotino,
-                                       0, 0, &uip, 0) == 0)
+                                       0, 0, &uip) == 0)
                        tempuqip = B_TRUE;
        }
        if (!gip && mp->m_sb.sb_gquotino != NULLFSINO) {
                if (xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
-                                       0, 0, &gip, 0) == 0)
+                                       0, 0, &gip) == 0)
                        tempgqip = B_TRUE;
        }
        if (uip) {
@@ -1109,10 +1109,7 @@ xfs_qm_internalqcheck_adjust(
        xfs_ino_t       ino,            /* inode number to get data for */
        void            __user *buffer, /* not used */
        int             ubsize,         /* not used */
-       void            *private_data,  /* not used */
-       xfs_daddr_t     bno,            /* starting block of inode cluster */
        int             *ubused,        /* not used */
-       void            *dip,           /* not used */
        int             *res)           /* bulkstat result code */
 {
        xfs_inode_t             *ip;
@@ -1134,7 +1131,7 @@ xfs_qm_internalqcheck_adjust(
        ipreleased = B_FALSE;
  again:
        lock_flags = XFS_ILOCK_SHARED;
-       if ((error = xfs_iget(mp, NULL, ino, 0, lock_flags, &ip, bno))) {
+       if ((error = xfs_iget(mp, NULL, ino, 0, lock_flags, &ip))) {
                *res = BULKSTAT_RV_NOTHING;
                return (error);
        }
@@ -1205,15 +1202,15 @@ xfs_qm_internalqcheck(
                 * Iterate thru all the inodes in the file system,
                 * adjusting the corresponding dquot counters
                 */
-               if ((error = xfs_bulkstat(mp, &lastino, &count,
-                                xfs_qm_internalqcheck_adjust, NULL,
-                                0, NULL, BULKSTAT_FG_IGET, &done))) {
+               error = xfs_bulkstat(mp, &lastino, &count,
+                                xfs_qm_internalqcheck_adjust,
+                                0, NULL, &done);
+               if (error) {
+                       cmn_err(CE_DEBUG, "Bulkstat returned error 0x%x", error);
                        break;
                }
-       } while (! done);
-       if (error) {
-               cmn_err(CE_DEBUG, "Bulkstat returned error 0x%x", error);
-       }
+       } while (!done);
+
        cmn_err(CE_DEBUG, "Checking results against system dquots");
        for (i = 0; i < qmtest_hashmask; i++) {
                xfs_dqtest_t    *d, *n;
index 5bba29a07812cb761a9094e2ca1448491e99fc27..7f159d2a429a97e8a71e0fd57298ec499519c064 100644 (file)
@@ -69,7 +69,9 @@ xfs_swapext(
                goto out;
        }
 
-       if (!(file->f_mode & FMODE_WRITE) || (file->f_flags & O_APPEND)) {
+       if (!(file->f_mode & FMODE_WRITE) ||
+           !(file->f_mode & FMODE_READ) ||
+           (file->f_flags & O_APPEND)) {
                error = XFS_ERROR(EBADF);
                goto out_put_file;
        }
@@ -81,6 +83,7 @@ xfs_swapext(
        }
 
        if (!(tmp_file->f_mode & FMODE_WRITE) ||
+           !(tmp_file->f_mode & FMODE_READ) ||
            (tmp_file->f_flags & O_APPEND)) {
                error = XFS_ERROR(EBADF);
                goto out_put_tmp_file;
index 9d884c127bb980c9c24b934113be222a4fc1093d..c7142a064c48d7b052d9ac0225f33562d0552386 100644 (file)
@@ -1203,6 +1203,63 @@ error0:
        return error;
 }
 
+STATIC int
+xfs_imap_lookup(
+       struct xfs_mount        *mp,
+       struct xfs_trans        *tp,
+       xfs_agnumber_t          agno,
+       xfs_agino_t             agino,
+       xfs_agblock_t           agbno,
+       xfs_agblock_t           *chunk_agbno,
+       xfs_agblock_t           *offset_agbno,
+       int                     flags)
+{
+       struct xfs_inobt_rec_incore rec;
+       struct xfs_btree_cur    *cur;
+       struct xfs_buf          *agbp;
+       xfs_agino_t             startino;
+       int                     error;
+       int                     i;
+
+       error = xfs_ialloc_read_agi(mp, tp, agno, &agbp);
+       if (error) {
+               xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: "
+                               "xfs_ialloc_read_agi() returned "
+                               "error %d, agno %d",
+                               error, agno);
+               return error;
+       }
+
+       /*
+        * derive and lookup the exact inode record for the given agino. If the
+        * record cannot be found, then it's an invalid inode number and we
+        * should abort.
+        */
+       cur = xfs_inobt_init_cursor(mp, tp, agbp, agno);
+       startino = agino & ~(XFS_IALLOC_INODES(mp) - 1);
+       error = xfs_inobt_lookup(cur, startino, XFS_LOOKUP_EQ, &i);
+       if (!error) {
+               if (i)
+                       error = xfs_inobt_get_rec(cur, &rec, &i);
+               if (!error && i == 0)
+                       error = EINVAL;
+       }
+
+       xfs_trans_brelse(tp, agbp);
+       xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
+       if (error)
+               return error;
+
+       /* for untrusted inodes check it is allocated first */
+       if ((flags & XFS_IGET_UNTRUSTED) &&
+           (rec.ir_free & XFS_INOBT_MASK(agino - rec.ir_startino)))
+               return EINVAL;
+
+       *chunk_agbno = XFS_AGINO_TO_AGBNO(mp, rec.ir_startino);
+       *offset_agbno = agbno - *chunk_agbno;
+       return 0;
+}
+
 /*
  * Return the location of the inode in imap, for mapping it into a buffer.
  */
@@ -1235,8 +1292,11 @@ xfs_imap(
        if (agno >= mp->m_sb.sb_agcount || agbno >= mp->m_sb.sb_agblocks ||
            ino != XFS_AGINO_TO_INO(mp, agno, agino)) {
 #ifdef DEBUG
-               /* no diagnostics for bulkstat, ino comes from userspace */
-               if (flags & XFS_IGET_BULKSTAT)
+               /*
+                * Don't output diagnostic information for untrusted inodes
+                * as they can be invalid without implying corruption.
+                */
+               if (flags & XFS_IGET_UNTRUSTED)
                        return XFS_ERROR(EINVAL);
                if (agno >= mp->m_sb.sb_agcount) {
                        xfs_fs_cmn_err(CE_ALERT, mp,
@@ -1263,6 +1323,23 @@ xfs_imap(
                return XFS_ERROR(EINVAL);
        }
 
+       blks_per_cluster = XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_blocklog;
+
+       /*
+        * For bulkstat and handle lookups, we have an untrusted inode number
+        * that we have to verify is valid. We cannot do this just by reading
+        * the inode buffer as it may have been unlinked and removed leaving
+        * inodes in stale state on disk. Hence we have to do a btree lookup
+        * in all cases where an untrusted inode number is passed.
+        */
+       if (flags & XFS_IGET_UNTRUSTED) {
+               error = xfs_imap_lookup(mp, tp, agno, agino, agbno,
+                                       &chunk_agbno, &offset_agbno, flags);
+               if (error)
+                       return error;
+               goto out_map;
+       }
+
        /*
         * If the inode cluster size is the same as the blocksize or
         * smaller we get to the buffer by simple arithmetics.
@@ -1277,24 +1354,6 @@ xfs_imap(
                return 0;
        }
 
-       blks_per_cluster = XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_blocklog;
-
-       /*
-        * If we get a block number passed from bulkstat we can use it to
-        * find the buffer easily.
-        */
-       if (imap->im_blkno) {
-               offset = XFS_INO_TO_OFFSET(mp, ino);
-               ASSERT(offset < mp->m_sb.sb_inopblock);
-
-               cluster_agbno = xfs_daddr_to_agbno(mp, imap->im_blkno);
-               offset += (agbno - cluster_agbno) * mp->m_sb.sb_inopblock;
-
-               imap->im_len = XFS_FSB_TO_BB(mp, blks_per_cluster);
-               imap->im_boffset = (ushort)(offset << mp->m_sb.sb_inodelog);
-               return 0;
-       }
-
        /*
         * If the inode chunks are aligned then use simple maths to
         * find the location. Otherwise we have to do a btree
@@ -1304,50 +1363,13 @@ xfs_imap(
                offset_agbno = agbno & mp->m_inoalign_mask;
                chunk_agbno = agbno - offset_agbno;
        } else {
-               xfs_btree_cur_t *cur;   /* inode btree cursor */
-               xfs_inobt_rec_incore_t chunk_rec;
-               xfs_buf_t       *agbp;  /* agi buffer */
-               int             i;      /* temp state */
-
-               error = xfs_ialloc_read_agi(mp, tp, agno, &agbp);
-               if (error) {
-                       xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: "
-                                       "xfs_ialloc_read_agi() returned "
-                                       "error %d, agno %d",
-                                       error, agno);
-                       return error;
-               }
-
-               cur = xfs_inobt_init_cursor(mp, tp, agbp, agno);
-               error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &i);
-               if (error) {
-                       xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: "
-                                       "xfs_inobt_lookup() failed");
-                       goto error0;
-               }
-
-               error = xfs_inobt_get_rec(cur, &chunk_rec, &i);
-               if (error) {
-                       xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: "
-                                       "xfs_inobt_get_rec() failed");
-                       goto error0;
-               }
-               if (i == 0) {
-#ifdef DEBUG
-                       xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: "
-                                       "xfs_inobt_get_rec() failed");
-#endif /* DEBUG */
-                       error = XFS_ERROR(EINVAL);
-               }
- error0:
-               xfs_trans_brelse(tp, agbp);
-               xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
+               error = xfs_imap_lookup(mp, tp, agno, agino, agbno,
+                                       &chunk_agbno, &offset_agbno, flags);
                if (error)
                        return error;
-               chunk_agbno = XFS_AGINO_TO_AGBNO(mp, chunk_rec.ir_startino);
-               offset_agbno = agbno - chunk_agbno;
        }
 
+out_map:
        ASSERT(agbno >= chunk_agbno);
        cluster_agbno = chunk_agbno +
                ((offset_agbno / blks_per_cluster) * blks_per_cluster);
index 75df75f43d48bf94f0e463aad56df8dc7f73dbfb..8f8b91be2c996dce5b75901038c507bb4b9ef1da 100644 (file)
@@ -259,7 +259,6 @@ xfs_iget_cache_miss(
        xfs_trans_t             *tp,
        xfs_ino_t               ino,
        struct xfs_inode        **ipp,
-       xfs_daddr_t             bno,
        int                     flags,
        int                     lock_flags)
 {
@@ -272,7 +271,7 @@ xfs_iget_cache_miss(
        if (!ip)
                return ENOMEM;
 
-       error = xfs_iread(mp, tp, ip, bno, flags);
+       error = xfs_iread(mp, tp, ip, flags);
        if (error)
                goto out_destroy;
 
@@ -358,8 +357,6 @@ out_destroy:
  *        within the file system for the inode being requested.
  * lock_flags -- flags indicating how to lock the inode.  See the comment
  *              for xfs_ilock() for a list of valid values.
- * bno -- the block number starting the buffer containing the inode,
- *       if known (as by bulkstat), else 0.
  */
 int
 xfs_iget(
@@ -368,8 +365,7 @@ xfs_iget(
        xfs_ino_t       ino,
        uint            flags,
        uint            lock_flags,
-       xfs_inode_t     **ipp,
-       xfs_daddr_t     bno)
+       xfs_inode_t     **ipp)
 {
        xfs_inode_t     *ip;
        int             error;
@@ -397,7 +393,7 @@ again:
                read_unlock(&pag->pag_ici_lock);
                XFS_STATS_INC(xs_ig_missed);
 
-               error = xfs_iget_cache_miss(mp, pag, tp, ino, &ip, bno,
+               error = xfs_iget_cache_miss(mp, pag, tp, ino, &ip,
                                                        flags, lock_flags);
                if (error)
                        goto out_error_or_again;
index d53c39de7d05930413bfb66b82a33fe6e76c813e..b76a829d7e200d4ead1b9e4406faf93f1e4093e0 100644 (file)
@@ -177,7 +177,7 @@ xfs_imap_to_bp(
                if (unlikely(XFS_TEST_ERROR(!di_ok, mp,
                                                XFS_ERRTAG_ITOBP_INOTOBP,
                                                XFS_RANDOM_ITOBP_INOTOBP))) {
-                       if (iget_flags & XFS_IGET_BULKSTAT) {
+                       if (iget_flags & XFS_IGET_UNTRUSTED) {
                                xfs_trans_brelse(tp, bp);
                                return XFS_ERROR(EINVAL);
                        }
@@ -787,7 +787,6 @@ xfs_iread(
        xfs_mount_t     *mp,
        xfs_trans_t     *tp,
        xfs_inode_t     *ip,
-       xfs_daddr_t     bno,
        uint            iget_flags)
 {
        xfs_buf_t       *bp;
@@ -797,11 +796,9 @@ xfs_iread(
        /*
         * Fill in the location information in the in-core inode.
         */
-       ip->i_imap.im_blkno = bno;
        error = xfs_imap(mp, tp, ip->i_ino, &ip->i_imap, iget_flags);
        if (error)
                return error;
-       ASSERT(bno == 0 || bno == ip->i_imap.im_blkno);
 
        /*
         * Get pointers to the on-disk inode and the buffer containing it.
index 9965e40a4615d8c09001ffe800c7e750ab8bece7..78550df13cd664ee4811447f836e9d0f8dc31405 100644 (file)
@@ -442,7 +442,7 @@ static inline void xfs_ifunlock(xfs_inode_t *ip)
  * xfs_iget.c prototypes.
  */
 int            xfs_iget(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
-                        uint, uint, xfs_inode_t **, xfs_daddr_t);
+                        uint, uint, xfs_inode_t **);
 void           xfs_iput(xfs_inode_t *, uint);
 void           xfs_iput_new(xfs_inode_t *, uint);
 void           xfs_ilock(xfs_inode_t *, uint);
@@ -500,7 +500,7 @@ do { \
  * Flags for xfs_iget()
  */
 #define XFS_IGET_CREATE                0x1
-#define XFS_IGET_BULKSTAT      0x2
+#define XFS_IGET_UNTRUSTED     0x2
 
 int            xfs_inotobp(struct xfs_mount *, struct xfs_trans *,
                            xfs_ino_t, struct xfs_dinode **,
@@ -509,7 +509,7 @@ int         xfs_itobp(struct xfs_mount *, struct xfs_trans *,
                          struct xfs_inode *, struct xfs_dinode **,
                          struct xfs_buf **, uint);
 int            xfs_iread(struct xfs_mount *, struct xfs_trans *,
-                         struct xfs_inode *, xfs_daddr_t, uint);
+                         struct xfs_inode *, uint);
 void           xfs_dinode_to_disk(struct xfs_dinode *,
                                   struct xfs_icdinode *);
 void           xfs_idestroy_fork(struct xfs_inode *, int);
index b1b801e4a28e41643d93b6c5438e01718c665bed..2b86f86105125c3869a641b68bc73b984ce69e79 100644 (file)
@@ -49,24 +49,40 @@ xfs_internal_inum(
                 (ino == mp->m_sb.sb_uquotino || ino == mp->m_sb.sb_gquotino)));
 }
 
-STATIC int
-xfs_bulkstat_one_iget(
-       xfs_mount_t     *mp,            /* mount point for filesystem */
-       xfs_ino_t       ino,            /* inode number to get data for */
-       xfs_daddr_t     bno,            /* starting bno of inode cluster */
-       xfs_bstat_t     *buf,           /* return buffer */
-       int             *stat)          /* BULKSTAT_RV_... */
+/*
+ * Return stat information for one inode.
+ * Return 0 if ok, else errno.
+ */
+int
+xfs_bulkstat_one_int(
+       struct xfs_mount        *mp,            /* mount point for filesystem */
+       xfs_ino_t               ino,            /* inode to get data for */
+       void __user             *buffer,        /* buffer to place output in */
+       int                     ubsize,         /* size of buffer */
+       bulkstat_one_fmt_pf     formatter,      /* formatter, copy to user */
+       int                     *ubused,        /* bytes used by me */
+       int                     *stat)          /* BULKSTAT_RV_... */
 {
-       xfs_icdinode_t  *dic;   /* dinode core info pointer */
-       xfs_inode_t     *ip;            /* incore inode pointer */
-       struct inode    *inode;
-       int             error;
+       struct xfs_icdinode     *dic;           /* dinode core info pointer */
+       struct xfs_inode        *ip;            /* incore inode pointer */
+       struct inode            *inode;
+       struct xfs_bstat        *buf;           /* return buffer */
+       int                     error = 0;      /* error value */
+
+       *stat = BULKSTAT_RV_NOTHING;
+
+       if (!buffer || xfs_internal_inum(mp, ino))
+               return XFS_ERROR(EINVAL);
+
+       buf = kmem_alloc(sizeof(*buf), KM_SLEEP | KM_MAYFAIL);
+       if (!buf)
+               return XFS_ERROR(ENOMEM);
 
        error = xfs_iget(mp, NULL, ino,
-                        XFS_IGET_BULKSTAT, XFS_ILOCK_SHARED, &ip, bno);
+                        XFS_IGET_UNTRUSTED, XFS_ILOCK_SHARED, &ip);
        if (error) {
                *stat = BULKSTAT_RV_NOTHING;
-               return error;
+               goto out_free;
        }
 
        ASSERT(ip != NULL);
@@ -127,77 +143,16 @@ xfs_bulkstat_one_iget(
                buf->bs_blocks = dic->di_nblocks + ip->i_delayed_blks;
                break;
        }
-
        xfs_iput(ip, XFS_ILOCK_SHARED);
-       return error;
-}
 
-STATIC void
-xfs_bulkstat_one_dinode(
-       xfs_mount_t     *mp,            /* mount point for filesystem */
-       xfs_ino_t       ino,            /* inode number to get data for */
-       xfs_dinode_t    *dic,           /* dinode inode pointer */
-       xfs_bstat_t     *buf)           /* return buffer */
-{
-       /*
-        * The inode format changed when we moved the link count and
-        * made it 32 bits long.  If this is an old format inode,
-        * convert it in memory to look like a new one.  If it gets
-        * flushed to disk we will convert back before flushing or
-        * logging it.  We zero out the new projid field and the old link
-        * count field.  We'll handle clearing the pad field (the remains
-        * of the old uuid field) when we actually convert the inode to
-        * the new format. We don't change the version number so that we
-        * can distinguish this from a real new format inode.
-        */
-       if (dic->di_version == 1) {
-               buf->bs_nlink = be16_to_cpu(dic->di_onlink);
-               buf->bs_projid = 0;
-       } else {
-               buf->bs_nlink = be32_to_cpu(dic->di_nlink);
-               buf->bs_projid = be16_to_cpu(dic->di_projid);
-       }
+       error = formatter(buffer, ubsize, ubused, buf);
 
-       buf->bs_ino = ino;
-       buf->bs_mode = be16_to_cpu(dic->di_mode);
-       buf->bs_uid = be32_to_cpu(dic->di_uid);
-       buf->bs_gid = be32_to_cpu(dic->di_gid);
-       buf->bs_size = be64_to_cpu(dic->di_size);
-       buf->bs_atime.tv_sec = be32_to_cpu(dic->di_atime.t_sec);
-       buf->bs_atime.tv_nsec = be32_to_cpu(dic->di_atime.t_nsec);
-       buf->bs_mtime.tv_sec = be32_to_cpu(dic->di_mtime.t_sec);
-       buf->bs_mtime.tv_nsec = be32_to_cpu(dic->di_mtime.t_nsec);
-       buf->bs_ctime.tv_sec = be32_to_cpu(dic->di_ctime.t_sec);
-       buf->bs_ctime.tv_nsec = be32_to_cpu(dic->di_ctime.t_nsec);
-       buf->bs_xflags = xfs_dic2xflags(dic);
-       buf->bs_extsize = be32_to_cpu(dic->di_extsize) << mp->m_sb.sb_blocklog;
-       buf->bs_extents = be32_to_cpu(dic->di_nextents);
-       buf->bs_gen = be32_to_cpu(dic->di_gen);
-       memset(buf->bs_pad, 0, sizeof(buf->bs_pad));
-       buf->bs_dmevmask = be32_to_cpu(dic->di_dmevmask);
-       buf->bs_dmstate = be16_to_cpu(dic->di_dmstate);
-       buf->bs_aextents = be16_to_cpu(dic->di_anextents);
-       buf->bs_forkoff = XFS_DFORK_BOFF(dic);
+       if (!error)
+               *stat = BULKSTAT_RV_DIDONE;
 
-       switch (dic->di_format) {
-       case XFS_DINODE_FMT_DEV:
-               buf->bs_rdev = xfs_dinode_get_rdev(dic);
-               buf->bs_blksize = BLKDEV_IOSIZE;
-               buf->bs_blocks = 0;
-               break;
-       case XFS_DINODE_FMT_LOCAL:
-       case XFS_DINODE_FMT_UUID:
-               buf->bs_rdev = 0;
-               buf->bs_blksize = mp->m_sb.sb_blocksize;
-               buf->bs_blocks = 0;
-               break;
-       case XFS_DINODE_FMT_EXTENTS:
-       case XFS_DINODE_FMT_BTREE:
-               buf->bs_rdev = 0;
-               buf->bs_blksize = mp->m_sb.sb_blocksize;
-               buf->bs_blocks = be64_to_cpu(dic->di_nblocks);
-               break;
-       }
+ out_free:
+       kmem_free(buf);
+       return error;
 }
 
 /* Return 0 on success or positive error */
@@ -217,118 +172,17 @@ xfs_bulkstat_one_fmt(
        return 0;
 }
 
-/*
- * Return stat information for one inode.
- * Return 0 if ok, else errno.
- */
-int                                    /* error status */
-xfs_bulkstat_one_int(
-       xfs_mount_t     *mp,            /* mount point for filesystem */
-       xfs_ino_t       ino,            /* inode number to get data for */
-       void            __user *buffer, /* buffer to place output in */
-       int             ubsize,         /* size of buffer */
-       bulkstat_one_fmt_pf formatter,  /* formatter, copy to user */
-       xfs_daddr_t     bno,            /* starting bno of inode cluster */
-       int             *ubused,        /* bytes used by me */
-       void            *dibuff,        /* on-disk inode buffer */
-       int             *stat)          /* BULKSTAT_RV_... */
-{
-       xfs_bstat_t     *buf;           /* return buffer */
-       int             error = 0;      /* error value */
-       xfs_dinode_t    *dip;           /* dinode inode pointer */
-
-       dip = (xfs_dinode_t *)dibuff;
-       *stat = BULKSTAT_RV_NOTHING;
-
-       if (!buffer || xfs_internal_inum(mp, ino))
-               return XFS_ERROR(EINVAL);
-
-       buf = kmem_alloc(sizeof(*buf), KM_SLEEP);
-
-       if (dip == NULL) {
-               /* We're not being passed a pointer to a dinode.  This happens
-                * if BULKSTAT_FG_IGET is selected.  Do the iget.
-                */
-               error = xfs_bulkstat_one_iget(mp, ino, bno, buf, stat);
-               if (error)
-                       goto out_free;
-       } else {
-               xfs_bulkstat_one_dinode(mp, ino, dip, buf);
-       }
-
-       error = formatter(buffer, ubsize, ubused, buf);
-       if (error)
-               goto out_free;
-
-       *stat = BULKSTAT_RV_DIDONE;
-
- out_free:
-       kmem_free(buf);
-       return error;
-}
-
 int
 xfs_bulkstat_one(
        xfs_mount_t     *mp,            /* mount point for filesystem */
        xfs_ino_t       ino,            /* inode number to get data for */
        void            __user *buffer, /* buffer to place output in */
        int             ubsize,         /* size of buffer */
-       void            *private_data,  /* my private data */
-       xfs_daddr_t     bno,            /* starting bno of inode cluster */
        int             *ubused,        /* bytes used by me */
-       void            *dibuff,        /* on-disk inode buffer */
        int             *stat)          /* BULKSTAT_RV_... */
 {
        return xfs_bulkstat_one_int(mp, ino, buffer, ubsize,
-                                   xfs_bulkstat_one_fmt, bno,
-                                   ubused, dibuff, stat);
-}
-
-/*
- * Test to see whether we can use the ondisk inode directly, based
- * on the given bulkstat flags, filling in dipp accordingly.
- * Returns zero if the inode is dodgey.
- */
-STATIC int
-xfs_bulkstat_use_dinode(
-       xfs_mount_t     *mp,
-       int             flags,
-       xfs_buf_t       *bp,
-       int             clustidx,
-       xfs_dinode_t    **dipp)
-{
-       xfs_dinode_t    *dip;
-       unsigned int    aformat;
-
-       *dipp = NULL;
-       if (!bp || (flags & BULKSTAT_FG_IGET))
-               return 1;
-       dip = (xfs_dinode_t *)
-                       xfs_buf_offset(bp, clustidx << mp->m_sb.sb_inodelog);
-       /*
-        * Check the buffer containing the on-disk inode for di_mode == 0.
-        * This is to prevent xfs_bulkstat from picking up just reclaimed
-        * inodes that have their in-core state initialized but not flushed
-        * to disk yet. This is a temporary hack that would require a proper
-        * fix in the future.
-        */
-       if (be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC ||
-           !XFS_DINODE_GOOD_VERSION(dip->di_version) ||
-           !dip->di_mode)
-               return 0;
-       if (flags & BULKSTAT_FG_QUICK) {
-               *dipp = dip;
-               return 1;
-       }
-       /* BULKSTAT_FG_INLINE: if attr fork is local, or not there, use it */
-       aformat = dip->di_aformat;
-       if ((XFS_DFORK_Q(dip) == 0) ||
-           (aformat == XFS_DINODE_FMT_LOCAL) ||
-           (aformat == XFS_DINODE_FMT_EXTENTS && !dip->di_anextents)) {
-               *dipp = dip;
-               return 1;
-       }
-       return 1;
+                                   xfs_bulkstat_one_fmt, ubused, stat);
 }
 
 #define XFS_BULKSTAT_UBLEFT(ubleft)    ((ubleft) >= statstruct_size)
@@ -342,10 +196,8 @@ xfs_bulkstat(
        xfs_ino_t               *lastinop, /* last inode returned */
        int                     *ubcountp, /* size of buffer/count returned */
        bulkstat_one_pf         formatter, /* func that'd fill a single buf */
-       void                    *private_data,/* private data for formatter */
        size_t                  statstruct_size, /* sizeof struct filling */
        char                    __user *ubuffer, /* buffer with inode stats */
-       int                     flags,  /* defined in xfs_itable.h */
        int                     *done)  /* 1 if there are more stats to get */
 {
        xfs_agblock_t           agbno=0;/* allocation group block number */
@@ -380,14 +232,12 @@ xfs_bulkstat(
        int                     ubelem; /* spaces used in user's buffer */
        int                     ubused; /* bytes used by formatter */
        xfs_buf_t               *bp;    /* ptr to on-disk inode cluster buf */
-       xfs_dinode_t            *dip;   /* ptr into bp for specific inode */
 
        /*
         * Get the last inode value, see if there's nothing to do.
         */
        ino = (xfs_ino_t)*lastinop;
        lastino = ino;
-       dip = NULL;
        agno = XFS_INO_TO_AGNO(mp, ino);
        agino = XFS_INO_TO_AGINO(mp, ino);
        if (agno >= mp->m_sb.sb_agcount ||
@@ -612,37 +462,6 @@ xfs_bulkstat(
                                                        irbp->ir_startino) +
                                                ((chunkidx & nimask) >>
                                                 mp->m_sb.sb_inopblog);
-
-                                       if (flags & (BULKSTAT_FG_QUICK |
-                                                    BULKSTAT_FG_INLINE)) {
-                                               int offset;
-
-                                               ino = XFS_AGINO_TO_INO(mp, agno,
-                                                                      agino);
-                                               bno = XFS_AGB_TO_DADDR(mp, agno,
-                                                                      agbno);
-
-                                               /*
-                                                * Get the inode cluster buffer
-                                                */
-                                               if (bp)
-                                                       xfs_buf_relse(bp);
-
-                                               error = xfs_inotobp(mp, NULL, ino, &dip,
-                                                                   &bp, &offset,
-                                                                   XFS_IGET_BULKSTAT);
-
-                                               if (!error)
-                                                       clustidx = offset / mp->m_sb.sb_inodesize;
-                                               if (XFS_TEST_ERROR(error != 0,
-                                                                  mp, XFS_ERRTAG_BULKSTAT_READ_CHUNK,
-                                                                  XFS_RANDOM_BULKSTAT_READ_CHUNK)) {
-                                                       bp = NULL;
-                                                       ubleft = 0;
-                                                       rval = error;
-                                                       break;
-                                               }
-                                       }
                                }
                                ino = XFS_AGINO_TO_INO(mp, agno, agino);
                                bno = XFS_AGB_TO_DADDR(mp, agno, agbno);
@@ -658,35 +477,13 @@ xfs_bulkstat(
                                 * when the chunk is used up.
                                 */
                                irbp->ir_freecount++;
-                               if (!xfs_bulkstat_use_dinode(mp, flags, bp,
-                                                            clustidx, &dip)) {
-                                       lastino = ino;
-                                       continue;
-                               }
-                               /*
-                                * If we need to do an iget, cannot hold bp.
-                                * Drop it, until starting the next cluster.
-                                */
-                               if ((flags & BULKSTAT_FG_INLINE) && !dip) {
-                                       if (bp)
-                                               xfs_buf_relse(bp);
-                                       bp = NULL;
-                               }
 
                                /*
                                 * Get the inode and fill in a single buffer.
-                                * BULKSTAT_FG_QUICK uses dip to fill it in.
-                                * BULKSTAT_FG_IGET uses igets.
-                                * BULKSTAT_FG_INLINE uses dip if we have an
-                                * inline attr fork, else igets.
-                                * See: xfs_bulkstat_one & xfs_dm_bulkstat_one.
-                                * This is also used to count inodes/blks, etc
-                                * in xfs_qm_quotacheck.
                                 */
                                ubused = statstruct_size;
-                               error = formatter(mp, ino, ubufp,
-                                               ubleft, private_data,
-                                               bno, &ubused, dip, &fmterror);
+                               error = formatter(mp, ino, ubufp, ubleft,
+                                                 &ubused, &fmterror);
                                if (fmterror == BULKSTAT_RV_NOTHING) {
                                        if (error && error != ENOENT &&
                                                error != EINVAL) {
@@ -778,8 +575,7 @@ xfs_bulkstat_single(
         */
 
        ino = (xfs_ino_t)*lastinop;
-       error = xfs_bulkstat_one(mp, ino, buffer, sizeof(xfs_bstat_t),
-                                NULL, 0, NULL, NULL, &res);
+       error = xfs_bulkstat_one(mp, ino, buffer, sizeof(xfs_bstat_t), 0, &res);
        if (error) {
                /*
                 * Special case way failed, do it the "long" way
@@ -788,8 +584,7 @@ xfs_bulkstat_single(
                (*lastinop)--;
                count = 1;
                if (xfs_bulkstat(mp, lastinop, &count, xfs_bulkstat_one,
-                               NULL, sizeof(xfs_bstat_t), buffer,
-                               BULKSTAT_FG_IGET, done))
+                               sizeof(xfs_bstat_t), buffer, done))
                        return error;
                if (count == 0 || (xfs_ino_t)*lastinop != ino)
                        return error == EFSCORRUPTED ?
index 20792bf459468b84b6bb960d7328888a1ab35df8..97295d91d1703c21cbeacacc876f9eded07aeb38 100644 (file)
@@ -27,10 +27,7 @@ typedef int (*bulkstat_one_pf)(struct xfs_mount      *mp,
                               xfs_ino_t        ino,
                               void             __user *buffer,
                               int              ubsize,
-                              void             *private_data,
-                              xfs_daddr_t      bno,
                               int              *ubused,
-                              void             *dip,
                               int              *stat);
 
 /*
@@ -40,13 +37,6 @@ typedef int (*bulkstat_one_pf)(struct xfs_mount      *mp,
 #define BULKSTAT_RV_DIDONE     1
 #define BULKSTAT_RV_GIVEUP     2
 
-/*
- * Values for bulkstat flag argument.
- */
-#define BULKSTAT_FG_IGET       0x1     /* Go through the buffer cache */
-#define BULKSTAT_FG_QUICK      0x2     /* No iget, walk the dinode cluster */
-#define BULKSTAT_FG_INLINE     0x4     /* No iget if inline attrs */
-
 /*
  * Return stat information in bulk (by-inode) for the filesystem.
  */
@@ -56,10 +46,8 @@ xfs_bulkstat(
        xfs_ino_t       *lastino,       /* last inode returned */
        int             *count,         /* size of buffer/count returned */
        bulkstat_one_pf formatter,      /* func that'd fill a single buf */
-       void            *private_data,  /* private data for formatter */
        size_t          statstruct_size,/* sizeof struct that we're filling */
        char            __user *ubuffer,/* buffer with inode stats */
-       int             flags,          /* flag to control access method */
        int             *done);         /* 1 if there are more stats to get */
 
 int
@@ -82,9 +70,7 @@ xfs_bulkstat_one_int(
        void                    __user *buffer,
        int                     ubsize,
        bulkstat_one_fmt_pf     formatter,
-       xfs_daddr_t             bno,
        int                     *ubused,
-       void                    *dibuff,
        int                     *stat);
 
 int
@@ -93,10 +79,7 @@ xfs_bulkstat_one(
        xfs_ino_t               ino,
        void                    __user *buffer,
        int                     ubsize,
-       void                    *private_data,
-       xfs_daddr_t             bno,
        int                     *ubused,
-       void                    *dibuff,
        int                     *stat);
 
 typedef int (*inumbers_fmt_pf)(
index ed0684cc50eeb51f15549d899f3979c40eb9c6af..9ac5cfab27b96da77ac033559229090a3c52490a 100644 (file)
@@ -3198,7 +3198,7 @@ xlog_recover_process_one_iunlink(
        int                             error;
 
        ino = XFS_AGINO_TO_INO(mp, agno, agino);
-       error = xfs_iget(mp, NULL, ino, 0, 0, &ip, 0);
+       error = xfs_iget(mp, NULL, ino, 0, 0, &ip);
        if (error)
                goto fail;
 
index d59f4e8bedcf2bfaadf2151c829605646c80e745..69f62d8b2816c52389f4947c9d86b3958ccf57a6 100644 (file)
@@ -1300,7 +1300,7 @@ xfs_mountfs(
         * Get and sanity-check the root inode.
         * Save the pointer to it in the mount structure.
         */
-       error = xfs_iget(mp, NULL, sbp->sb_rootino, 0, XFS_ILOCK_EXCL, &rip, 0);
+       error = xfs_iget(mp, NULL, sbp->sb_rootino, 0, XFS_ILOCK_EXCL, &rip);
        if (error) {
                cmn_err(CE_WARN, "XFS: failed to read root inode");
                goto out_log_dealloc;
index 16445518506df427988c64a1e53934f7cab4da18..a2d32ce335aa681c3beab111f4c844873353f6af 100644 (file)
@@ -2277,12 +2277,12 @@ xfs_rtmount_inodes(
        sbp = &mp->m_sb;
        if (sbp->sb_rbmino == NULLFSINO)
                return 0;
-       error = xfs_iget(mp, NULL, sbp->sb_rbmino, 0, 0, &mp->m_rbmip, 0);
+       error = xfs_iget(mp, NULL, sbp->sb_rbmino, 0, 0, &mp->m_rbmip);
        if (error)
                return error;
        ASSERT(mp->m_rbmip != NULL);
        ASSERT(sbp->sb_rsumino != NULLFSINO);
-       error = xfs_iget(mp, NULL, sbp->sb_rsumino, 0, 0, &mp->m_rsumip, 0);
+       error = xfs_iget(mp, NULL, sbp->sb_rsumino, 0, 0, &mp->m_rsumip);
        if (error) {
                IRELE(mp->m_rbmip);
                return error;
index 785ff101da0a66368a7c06587dd13b3c3eae2f70..2559dfec946bb990afe7e44af28ae43204d6474a 100644 (file)
@@ -62,7 +62,7 @@ xfs_trans_iget(
 {
        int                     error;
 
-       error = xfs_iget(mp, tp, ino, flags, lock_flags, ipp, 0);
+       error = xfs_iget(mp, tp, ino, flags, lock_flags, ipp);
        if (!error && tp)
                xfs_trans_ijoin(tp, *ipp, lock_flags);
        return error;
index a06bd62504fc7e1388abcf8aeac0000996c92a64..c1646838898f45120767046f0b62d43cca92dd54 100644 (file)
@@ -1269,7 +1269,7 @@ xfs_lookup(
        if (error)
                goto out;
 
-       error = xfs_iget(dp->i_mount, NULL, inum, 0, 0, ipp, 0);
+       error = xfs_iget(dp->i_mount, NULL, inum, 0, 0, ipp);
        if (error)
                goto out_free_name;
 
index 9101ed64f803c64d3158df9aa134d8d4ffd26789..09ea4a1e95058ec4c73a20204c2bdbd8e1895388 100644 (file)
@@ -79,7 +79,6 @@ struct agp_memory {
        u32 physical;
        bool is_bound;
        bool is_flushed;
-       bool vmalloc_flag;
        /* list of agp_memory mapped to the aperture */
        struct list_head mapped_list;
        /* DMA-mapped addresses */
index aee5f6ce166e9cc1f186e5e76cab77bb536edfd5..9ae2889096b695cbeb7dfbc086ed4bb7484c1c40 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 73dcf804bc940e6738f5f0f553f3cf2045f78fd7..0da5b187f1245e8c33fd659420f5e4dca82b9ead 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 94dea3ffbfa19576e2cd8bb59b56658465101b49..fcfa5b9a4317af2b272d06073d7af51019ebf321 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 30da4ae489724197a220a83a6e39d1cba0a264c4..b8d2516668aa067d43d7c6c6e5301f3688469658 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 b3cd4de9432b68007342098ad7dbb662cbc1fce0..52c0da4bdd18fe5969fbf9c583652c0f7f00ba07 100644 (file)
@@ -40,7 +40,7 @@ int ddebug_add_module(struct _ddebug *tab, unsigned int n,
                                const char *modname);
 
 #if defined(CONFIG_DYNAMIC_DEBUG)
-extern int ddebug_remove_module(char *mod_name);
+extern int ddebug_remove_module(const char *mod_name);
 
 #define __dynamic_dbg_enabled(dd)  ({       \
        int __ret = 0;                                                       \
@@ -73,7 +73,7 @@ extern int ddebug_remove_module(char *mod_name);
 
 #else
 
-static inline int ddebug_remove_module(char *mod)
+static inline int ddebug_remove_module(const char *mod)
 {
        return 0;
 }
index 907ace3a64c8abef33aff5a1d7e3bc3c72337a54..8e5a9dfb76bf6425934a09427b8f16df82e937be 100644 (file)
@@ -786,8 +786,6 @@ struct fb_tile_ops {
 #define FBINFO_MISC_USEREVENT          0x10000 /* event request
                                                  from userspace */
 #define FBINFO_MISC_TILEBLITTING       0x20000 /* use tile blitting */
-#define FBINFO_MISC_FIRMWARE           0x40000 /* a replaceable firmware
-                                                 inited framebuffer */
 
 /* A driver may set this flag to indicate that it does want a set_par to be
  * called every time when fbcon_switch is executed. The advantage is that with
@@ -801,6 +799,8 @@ struct fb_tile_ops {
  */
 #define FBINFO_MISC_ALWAYS_SETPAR   0x40000
 
+/* where the fb is a firmware driver, and can be replaced with a proper one */
+#define FBINFO_MISC_FIRMWARE        0x80000
 /*
  * Host and GPU endianness differ.
  */
index 8392884a2977cda6a5f004fed2511ad51a140aa5..5d57a3a1fa1b1b9143a5e80381ac7668b51bb677 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 4eb467910a45a34e2638c9fddb8a92cc09b50177..3bedcc149c843bfec71e29c2b6e319a4d052c70b 100644 (file)
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE       0x0759
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_SMBUS     0x07D8
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP79_SMBUS     0x0AA2
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA     0x0D85
 
 #define PCI_VENDOR_ID_IMS              0x10e0
 #define PCI_DEVICE_ID_IMS_TT128                0x9128
index f118809c953ff137b2a97e0d9e674b2836ee331a..747fcaedddb70d6cb0a49b43c0d2f2a6f23a693f 100644 (file)
@@ -139,7 +139,7 @@ extern int nr_processes(void);
 extern unsigned long nr_running(void);
 extern unsigned long nr_uninterruptible(void);
 extern unsigned long nr_iowait(void);
-extern unsigned long nr_iowait_cpu(void);
+extern unsigned long nr_iowait_cpu(int cpu);
 extern unsigned long this_cpu_load(void);
 
 
index e407a05adc2937bc444be42b2a982bc4419103ef..4ab5124a29520d6cf35614ab58ab302cf3253939 100644 (file)
@@ -422,18 +422,26 @@ static void __init setup_command_line(char *command_line)
  * gcc-3.4 accidentally inlines this function, so use noinline.
  */
 
+static __initdata DECLARE_COMPLETION(kthreadd_done);
+
 static noinline void __init_refok rest_init(void)
        __releases(kernel_lock)
 {
        int pid;
 
        rcu_scheduler_starting();
+       /*
+        * We need to spawn init first so that it obtains pid 1, however
+        * the init task will end up wanting to create kthreads, which, if
+        * we schedule it before we create kthreadd, will OOPS.
+        */
        kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
        numa_default_policy();
        pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);
        rcu_read_lock();
        kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns);
        rcu_read_unlock();
+       complete(&kthreadd_done);
        unlock_kernel();
 
        /*
@@ -849,6 +857,10 @@ static noinline int init_post(void)
 
 static int __init kernel_init(void * unused)
 {
+       /*
+        * Wait until kthreadd is all set-up.
+        */
+       wait_for_completion(&kthreadd_done);
        lock_kernel();
 
        /*
index e7a35f1039e785464b318d3713557e9d2db6a591..6a3a5fa1526d87d16b362e20d7d62e6809285c18 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 474a84715eaca2936b51ad5a6c46fb4774751c5b..131b1703936f6dbe71cf84c2ff572efef6c47e70 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 8c6b42840dd19fa942919aa8e052bf400911a2a4..5d2d28197c827a840d98357c11c1e16b3dce92a2 100644 (file)
@@ -2062,6 +2062,12 @@ static void dynamic_debug_setup(struct _ddebug *debug, unsigned int num)
 #endif
 }
 
+static void dynamic_debug_remove(struct _ddebug *debug)
+{
+       if (debug)
+               ddebug_remove_module(debug->modname);
+}
+
 static void *module_alloc_update_bounds(unsigned long size)
 {
        void *ret = module_alloc(size);
@@ -2124,6 +2130,8 @@ static noinline struct module *load_module(void __user *umod,
        void *ptr = NULL; /* Stops spurious gcc warning */
        unsigned long symoffs, stroffs, *strmap;
        void __percpu *percpu;
+       struct _ddebug *debug = NULL;
+       unsigned int num_debug = 0;
 
        mm_segment_t old_fs;
 
@@ -2476,15 +2484,9 @@ static noinline struct module *load_module(void __user *umod,
        kfree(strmap);
        strmap = NULL;
 
-       if (!mod->taints) {
-               struct _ddebug *debug;
-               unsigned int num_debug;
-
+       if (!mod->taints)
                debug = section_objs(hdr, sechdrs, secstrings, "__verbose",
                                     sizeof(*debug), &num_debug);
-               if (debug)
-                       dynamic_debug_setup(debug, num_debug);
-       }
 
        err = module_finalize(hdr, sechdrs, mod);
        if (err < 0)
@@ -2526,10 +2528,13 @@ static noinline struct module *load_module(void __user *umod,
                goto unlock;
        }
 
+       if (debug)
+               dynamic_debug_setup(debug, num_debug);
+
        /* Find duplicate symbols */
        err = verify_export_symbols(mod);
        if (err < 0)
-               goto unlock;
+               goto ddebug;
 
        list_add_rcu(&mod->list, &modules);
        mutex_unlock(&module_mutex);
@@ -2557,6 +2562,8 @@ static noinline struct module *load_module(void __user *umod,
        mutex_lock(&module_mutex);
        /* Unlink carefully: kallsyms could be walking list. */
        list_del_rcu(&mod->list);
+ ddebug:
+       dynamic_debug_remove(debug);
  unlock:
        mutex_unlock(&module_mutex);
        synchronize_sched();
index 8c473adbf2230b78cad7b87dd4b3b453a1d4ec21..265cf3a2b5d898e89d714535c04af312831d79c8 100644 (file)
@@ -2873,9 +2873,9 @@ unsigned long nr_iowait(void)
        return sum;
 }
 
-unsigned long nr_iowait_cpu(void)
+unsigned long nr_iowait_cpu(int cpu)
 {
-       struct rq *this = this_rq();
+       struct rq *this = cpu_rq(cpu);
        return atomic_read(&this->nr_iowait);
 }
 
index 783fbadf22029561bdee188968ab83d1023b6fa6..813993b5fb61048f24f876a7247e4f8ac2c861a2 100644 (file)
@@ -154,14 +154,14 @@ static void tick_nohz_update_jiffies(ktime_t now)
  * Updates the per cpu time idle statistics counters
  */
 static void
-update_ts_time_stats(struct tick_sched *ts, ktime_t now, u64 *last_update_time)
+update_ts_time_stats(int cpu, struct tick_sched *ts, ktime_t now, u64 *last_update_time)
 {
        ktime_t delta;
 
        if (ts->idle_active) {
                delta = ktime_sub(now, ts->idle_entrytime);
                ts->idle_sleeptime = ktime_add(ts->idle_sleeptime, delta);
-               if (nr_iowait_cpu() > 0)
+               if (nr_iowait_cpu(cpu) > 0)
                        ts->iowait_sleeptime = ktime_add(ts->iowait_sleeptime, delta);
                ts->idle_entrytime = now;
        }
@@ -175,19 +175,19 @@ static void tick_nohz_stop_idle(int cpu, ktime_t now)
 {
        struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
 
-       update_ts_time_stats(ts, now, NULL);
+       update_ts_time_stats(cpu, ts, now, NULL);
        ts->idle_active = 0;
 
        sched_clock_idle_wakeup_event(0);
 }
 
-static ktime_t tick_nohz_start_idle(struct tick_sched *ts)
+static ktime_t tick_nohz_start_idle(int cpu, struct tick_sched *ts)
 {
        ktime_t now;
 
        now = ktime_get();
 
-       update_ts_time_stats(ts, now, NULL);
+       update_ts_time_stats(cpu, ts, now, NULL);
 
        ts->idle_entrytime = now;
        ts->idle_active = 1;
@@ -216,7 +216,7 @@ u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time)
        if (!tick_nohz_enabled)
                return -1;
 
-       update_ts_time_stats(ts, ktime_get(), last_update_time);
+       update_ts_time_stats(cpu, ts, ktime_get(), last_update_time);
 
        return ktime_to_us(ts->idle_sleeptime);
 }
@@ -242,7 +242,7 @@ u64 get_cpu_iowait_time_us(int cpu, u64 *last_update_time)
        if (!tick_nohz_enabled)
                return -1;
 
-       update_ts_time_stats(ts, ktime_get(), last_update_time);
+       update_ts_time_stats(cpu, ts, ktime_get(), last_update_time);
 
        return ktime_to_us(ts->iowait_sleeptime);
 }
@@ -284,7 +284,7 @@ void tick_nohz_stop_sched_tick(int inidle)
         */
        ts->inidle = 1;
 
-       now = tick_nohz_start_idle(ts);
+       now = tick_nohz_start_idle(cpu, ts);
 
        /*
         * If this cpu is offline and it is the one which updates
index 3df8eb17a607932bf8091e89c796c338c323c29b..02afc25337284329d23a998e636240d5a41d337d 100644 (file)
@@ -692,7 +692,7 @@ static void ddebug_table_free(struct ddebug_table *dt)
  * Called in response to a module being unloaded.  Removes
  * any ddebug_table's which point at the module.
  */
-int ddebug_remove_module(char *mod_name)
+int ddebug_remove_module(const char *mod_name)
 {
        struct ddebug_table *dt, *nextdt;
        int ret = -ENOENT;
index 736c3b06398e522a7ad3d0ee846d77163436a334..1923f1490e72618b36756b326bbd2e280d71bd49 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 c6ece0a5759595bf1ddbbe4a95e4b76713ea4b06..20a8193a7af8ed275667e682fd22101a0e40bb93 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 5d6fb339de038945424733d5128846a1a1a7e352..5bc0a96beb51b550b69389998fc3e09053ee5a2f 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 bbd396ac9546f5b0625c34facbc0b6d33fe2163a..54f28bd493d3f6a04f437d6294d54a322daa4603 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 18513b0191db2cfeb2e208e2ddf66c96af6089e1..cea12744a6712541ae42e1ec6c27d2e2d0054cf1 100644 (file)
@@ -44,7 +44,7 @@ rpm-pkg rpm: $(objtree)/kernel.spec FORCE
        fi
        $(MAKE) clean
        $(PREV) ln -sf $(srctree) $(KERNELPATH)
-       $(CONFIG_SHELL) $(srctree)/scripts/setlocalversion > $(objtree)/.scmversion
+       $(CONFIG_SHELL) $(srctree)/scripts/setlocalversion --scm-only > $(objtree)/.scmversion
        $(PREV) tar -cz $(RCS_TAR_IGNORE) -f $(KERNELPATH).tar.gz $(KERNELPATH)/.
        $(PREV) rm $(KERNELPATH)
        rm -f $(objtree)/.scmversion
index 46989b88d7345d233ce5d734e2ed9845784df4d0..d6a866ed1835c8f1ee4524c6bb26df554c83c6e1 100755 (executable)
 #
 
 usage() {
-       echo "Usage: $0 [srctree]" >&2
+       echo "Usage: $0 [--scm-only] [srctree]" >&2
        exit 1
 }
 
-cd "${1:-.}" || usage
+scm_only=false
+srctree=.
+if test "$1" = "--scm-only"; then
+       scm_only=true
+       shift
+fi
+if test $# -gt 0; then
+       srctree=$1
+       shift
+fi
+if test $# -gt 0 -o ! -d "$srctree"; then
+       usage
+fi
 
-# Check for git and a git repo.
-if head=`git rev-parse --verify --short HEAD 2>/dev/null`; then
+scm_version()
+{
+       local short=false
 
-       # If we are at a tagged commit (like "v2.6.30-rc6"), we ignore it,
-       # because this version is defined in the top level Makefile.
-       if [ -z "`git describe --exact-match 2>/dev/null`" ]; then
+       cd "$srctree"
+       if test -e .scmversion; then
+               cat "$_"
+               return
+       fi
+       if test "$1" = "--short"; then
+               short=true
+       fi
 
-               # If we are past a tagged commit (like "v2.6.30-rc5-302-g72357d5"),
-               # we pretty print it.
-               if atag="`git describe 2>/dev/null`"; then
-                       echo "$atag" | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}'
+       # Check for git and a git repo.
+       if head=`git rev-parse --verify --short HEAD 2>/dev/null`; then
+
+               # If we are at a tagged commit (like "v2.6.30-rc6"), we ignore
+               # it, because this version is defined in the top level Makefile.
+               if [ -z "`git describe --exact-match 2>/dev/null`" ]; then
+
+                       # If only the short version is requested, don't bother
+                       # running further git commands
+                       if $short; then
+                               echo "+"
+                               return
+                       fi
+                       # If we are past a tagged commit (like
+                       # "v2.6.30-rc5-302-g72357d5"), we pretty print it.
+                       if atag="`git describe 2>/dev/null`"; then
+                               echo "$atag" | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}'
+
+                       # If we don't have a tag at all we print -g{commitish}.
+                       else
+                               printf '%s%s' -g $head
+                       fi
+               fi
 
-               # If we don't have a tag at all we print -g{commitish}.
-               else
-                       printf '%s%s' -g $head
+               # Is this git on svn?
+               if git config --get svn-remote.svn.url >/dev/null; then
+                       printf -- '-svn%s' "`git svn find-rev $head`"
                fi
-       fi
 
-       # Is this git on svn?
-       if git config --get svn-remote.svn.url >/dev/null; then
-               printf -- '-svn%s' "`git svn find-rev $head`"
-       fi
+               # Update index only on r/w media
+               [ -w . ] && git update-index --refresh --unmerged > /dev/null
 
-       # Update index only on r/w media
-       [ -w . ] && git update-index --refresh --unmerged > /dev/null
+               # Check for uncommitted changes
+               if git diff-index --name-only HEAD | grep -v "^scripts/package" \
+                   | read dummy; then
+                       printf '%s' -dirty
+               fi
 
-       # Check for uncommitted changes
-       if git diff-index --name-only HEAD | grep -v "^scripts/package" \
-           | read dummy; then
-               printf '%s' -dirty
+               # All done with git
+               return
        fi
 
-       # All done with git
-       exit
-fi
+       # Check for mercurial and a mercurial repo.
+       if hgid=`hg id 2>/dev/null`; then
+               tag=`printf '%s' "$hgid" | cut -d' ' -f2`
+
+               # Do we have an untagged version?
+               if [ -z "$tag" -o "$tag" = tip ]; then
+                       id=`printf '%s' "$hgid" | sed 's/[+ ].*//'`
+                       printf '%s%s' -hg "$id"
+               fi
 
-# Check for mercurial and a mercurial repo.
-if hgid=`hg id 2>/dev/null`; then
-       tag=`printf '%s' "$hgid" | cut -d' ' -f2`
+               # Are there uncommitted changes?
+               # These are represented by + after the changeset id.
+               case "$hgid" in
+                       *+|*+\ *) printf '%s' -dirty ;;
+               esac
 
-       # Do we have an untagged version?
-       if [ -z "$tag" -o "$tag" = tip ]; then
-               id=`printf '%s' "$hgid" | sed 's/[+ ].*//'`
-               printf '%s%s' -hg "$id"
+               # All done with mercurial
+               return
        fi
 
-       # Are there uncommitted changes?
-       # These are represented by + after the changeset id.
-       case "$hgid" in
-               *+|*+\ *) printf '%s' -dirty ;;
-       esac
+       # Check for svn and a svn repo.
+       if rev=`svn info 2>/dev/null | grep '^Last Changed Rev'`; then
+               rev=`echo $rev | awk '{print $NF}'`
+               printf -- '-svn%s' "$rev"
 
-       # All done with mercurial
+               # All done with svn
+               return
+       fi
+}
+
+collect_files()
+{
+       local file res
+
+       for file; do
+               case "$file" in
+               *\~*)
+                       continue
+                       ;;
+               esac
+               if test -e "$file"; then
+                       res="$res$(cat "$file")"
+               fi
+       done
+       echo "$res"
+}
+
+if $scm_only; then
+       scm_version
        exit
 fi
 
-# Check for svn and a svn repo.
-if rev=`svn info 2>/dev/null | grep '^Last Changed Rev'`; then
-       rev=`echo $rev | awk '{print $NF}'`
-       printf -- '-svn%s' "$rev"
+if test -e include/config/auto.conf; then
+       source "$_"
+else
+       echo "Error: kernelrelease not valid - run 'make prepare' to update it"
+       exit 1
+fi
 
-       # All done with svn
-       exit
+# localversion* files in the build and source directory
+res="$(collect_files localversion*)"
+if test ! "$srctree" -ef .; then
+       res="$res$(collect_files "$srctree"/localversion*)"
+fi
+
+# CONFIG_LOCALVERSION and LOCALVERSION (if set)
+res="${res}${CONFIG_LOCALVERSION}${LOCALVERSION}"
+
+# scm version string if not at a tagged commit
+if test "$CONFIG_LOCALVERSION_AUTO" = "y"; then
+       # full scm version string
+       res="$res$(scm_version)"
+else
+       # apped a plus sign if the repository is not in a clean tagged
+       # state and  LOCALVERSION= is not specified
+       if test "${LOCALVERSION+set}" != "set"; then
+               scm=$(scm_version --short)
+               res="$res${scm:++}"
+       fi
 fi
+
+echo "$res"
index 1f7ecd47f49942809d19b0be3f65d9fb1f904ebc..9a448b47400c8ec2305c4d0153d885fe4962a612 100644 (file)
@@ -7,6 +7,15 @@
 #include "util.h"
 #include "debug.h"
 
+/* Skip "." and ".." directories */
+static int filter(const struct dirent *dir)
+{
+       if (dir->d_name[0] == '.')
+               return 0;
+       else
+               return 1;
+}
+
 int find_all_tid(int pid, pid_t ** all_tid)
 {
        char name[256];
@@ -16,7 +25,7 @@ int find_all_tid(int pid, pid_t ** all_tid)
        int i;
 
        sprintf(name, "/proc/%d/task", pid);
-       items = scandir(name, &namelist, NULL, NULL);
+       items = scandir(name, &namelist, filter, NULL);
        if (items <= 0)
                 return -ENOENT;
        *all_tid = malloc(sizeof(pid_t) * items);