Merge tag 'fixes-3.15-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 25 Apr 2014 20:02:02 +0000 (13:02 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 25 Apr 2014 20:02:02 +0000 (13:02 -0700)
Pull ARM SoC fixes from Arnd Bergmann:
 "Since we didn't get around to collect fixes in time for -rc2 over the
  easter vacation, this one is unfortunately a bit larger than we'd like
  for an -rc3 merge.

  A large set of the changes is in the device tree sources, so I'm
  splitting out the description between code changes and DT changes.
  Aside from omap and versatile express, the actual code bugs are and
  trivial.  Here is an overview:

  imx:
   - fix video clock settings
   - fix one clock refcounting bug

  omap:
   - update defconfig for renamed USB PHY driver
   - fix error handling in gpmc
   - fix N900 video initialization regression
   - fix reression in hwmod code from missing braces
   - fix am43xx and omap3 clocks
   - remove bogus write to voltage control register

  pxa:
   - fix build regression from 3.13 header cleanup

  rockchip:
   - fix a misleading printk string

  shmobile:
   - fix incorrect sound setting on multiple machines

  spear:
   - remove incorrect __init section annotation

  tegra:
   - remove a stale Kconfig entry

  u300:
   - update defconfig

  ux500:
   - enable common wireless and sensor drivers in defconfig
   - more defconfig updates

  vexpress:
   - fix voltage calculation for opp
   - fix reboot hang and warning
   - fix out-of-bounds array access
   - improve error handling in clock driver

  overall:
   - always select CLKSRC_OF in multiplatform builds

  And these are the devicetree related changes:

  imx:
   - add missing #clock-cell properties
   - fix pinctrl setting in imx6sl-evk
   - fix video endpoint on imx53
   - remove obsolete lvds-channel nodes (multiple patches)
   - add missing second stmpe node
   - fix usb host mode on dmo-edmqmx6 (multiple patches)
   - fix gic node #address-cells to match usage
   - add missing legacy IRQ map for PCIe
   - fix microsom pincontrol setting for rgmii
   - fix fatal typo in touchscreen DT usage for mx5
   - list all RAM present on m53evk and mx53qsb

  omap:
   - fix bug in DT handling of gpmc external bus
   - add DT for older revision of beagleboard
   - fix regression after DT node name fixes
   - remove obsolete properties for gpmc
   - fix pinmux comment to match DT it refers to
   - fix newly added dra7xx clock node data
   - add missing clock for USB PHY

  mvebu:
   - add missing clock for mdio node
   - fix nonstandard vendor prefixes on i2c nodes

  rockchip:
   - fix pin control setting for uart

  shmobile:
   - fix typo in DT data for pin control (multiple patches)
   - fix gic node #address-cells to match usage

  tegra:
   - fix clock and uart DT representation to match hardware

  zynq:
   - add DT nodes for newly added driver
   - add DT properties required for cpufreq-ondemand

  overall:
   - restore alphabetic order in Makefile
   - grammar fixes in bindings"

* tag 'fixes-3.15-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (66 commits)
  ARM: vexpress/TC2: Convert OPP voltage to uV before storing
  power/reset: vexpress: Fix restart/power off operation
  dt: tegra: remove non-existent clock IDs
  clk: tegra: remove non-existent clocks
  ARM: tegra: remove UART5/UARTE from tegra124.dtsi
  ARM: tegra: remove TEGRA_EMC_SCALING_ENABLE
  ARM: Tidy up DTB Makefile entries
  ARM: fix missing CLKSRC_OF on multi-platform
  ARM: spear: add __init to spear_clocksource_init()
  ARM: pxa: hx4700.h: include "irqs.h" for PXA_NR_BUILTIN_GPIO
  arm/mach-vexpress: array accessed out of bounds
  clk: vexpress: NULL dereference on error path
  ARM: OMAP2+: Fix GPMC remap for devices using an offset
  ARM: zynq: dt: Add I2C nodes to Zynq device tree
  ARM: zynq: DT: Add 'clock-latency' property
  ARM: OMAP2+: Fix oops for GPMC free
  ARM: dts: Add support for the BeagleBoard xM A/B
  ARM: dts: Grammar /that will/it will/
  ARM: dts: Grammar /is uses/ is used/
  ARM: OMAP2+: Fix config name for USB3 PHY
  ...

80 files changed:
arch/arm/Kconfig
arch/arm/Kconfig.debug
arch/arm/common/bL_switcher.c
arch/arm/common/mcpm_entry.c
arch/arm/include/asm/div64.h
arch/arm/include/asm/mcpm.h
arch/arm/include/uapi/asm/unistd.h
arch/arm/kernel/calls.S
arch/arm/kernel/head.S
arch/arm/kernel/machine_kexec.c
arch/arm/kernel/sys_oabi-compat.c
arch/arm/mach-shmobile/clock-r8a7778.c
arch/arm/mm/Kconfig
arch/arm/mm/dma-mapping.c
arch/arm/vfp/vfpdouble.c
arch/arm/vfp/vfpsingle.c
arch/um/include/shared/os.h
arch/um/kernel/physmem.c
arch/um/os-Linux/file.c
arch/um/os-Linux/main.c
arch/um/os-Linux/mem.c
arch/x86/vdso/vdso-layout.lds.S
drivers/ata/Kconfig
drivers/ata/ahci.c
drivers/ata/ahci.h
drivers/ata/libata-core.c
drivers/ata/pata_arasan_cf.c
drivers/ata/pata_at91.c
drivers/ata/pata_samsung_cf.c
drivers/gpio/gpiolib-acpi.c
drivers/gpio/gpiolib.c
drivers/gpu/drm/radeon/atombios_dp.c
drivers/gpu/drm/radeon/cik_sdma.c
drivers/gpu/drm/radeon/r600_dpm.c
drivers/gpu/drm/radeon/radeon_atpx_handler.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_kms.c
drivers/gpu/drm/radeon/radeon_pm.c
drivers/input/misc/da9055_onkey.c
drivers/input/misc/soc_button_array.c
drivers/input/mouse/elantech.c
drivers/input/mouse/synaptics.c
drivers/input/serio/i8042-x86ia64io.h
drivers/input/serio/i8042.c
drivers/input/serio/serio.c
drivers/input/tablet/wacom_sys.c
drivers/input/tablet/wacom_wac.c
drivers/input/touchscreen/ads7846.c
drivers/regulator/pbias-regulator.c
drivers/spi/spi-atmel.c
drivers/spi/spi-bfin5xx.c
drivers/spi/spi-sh-hspi.c
drivers/spi/spi-sirf.c
fs/ceph/file.c
fs/compat.c
fs/ext4/balloc.c
fs/ext4/ext4.h
fs/ext4/extents.c
fs/ext4/extents_status.c
fs/ext4/file.c
fs/ext4/inode.c
fs/ext4/mballoc.c
fs/ext4/page-io.c
fs/ext4/super.c
fs/ext4/xattr.c
fs/fcntl.c
fs/locks.c
fs/nfsd/nfs4callback.c
fs/nfsd/nfs4xdr.c
fs/open.c
fs/xfs/xfs_file.c
include/linux/fs.h
include/linux/libata.h
include/linux/regulator/consumer.h
include/linux/serio.h
include/trace/events/ext4.h
include/uapi/asm-generic/fcntl.h
include/uapi/linux/input.h
mm/memory.c
security/selinux/hooks.c

index a48712ed0444456f561ab6e2cf2c6bd1e52b4087..9916e4d206a3b277008c93d228b68588c966e542 100644 (file)
@@ -30,9 +30,9 @@ config ARM
        select HAVE_ARCH_SECCOMP_FILTER if (AEABI && !OABI_COMPAT)
        select HAVE_ARCH_TRACEHOOK
        select HAVE_BPF_JIT
+       select HAVE_CC_STACKPROTECTOR
        select HAVE_CONTEXT_TRACKING
        select HAVE_C_RECORDMCOUNT
-       select HAVE_CC_STACKPROTECTOR
        select HAVE_DEBUG_KMEMLEAK
        select HAVE_DMA_API_DEBUG
        select HAVE_DMA_ATTRS
@@ -423,8 +423,8 @@ config ARCH_EFM32
        bool "Energy Micro efm32"
        depends on !MMU
        select ARCH_REQUIRE_GPIOLIB
-       select AUTO_ZRELADDR
        select ARM_NVIC
+       select AUTO_ZRELADDR
        select CLKSRC_OF
        select COMMON_CLK
        select CPU_V7M
@@ -512,8 +512,8 @@ config ARCH_IXP4XX
        bool "IXP4xx-based"
        depends on MMU
        select ARCH_HAS_DMA_SET_COHERENT_MASK
-       select ARCH_SUPPORTS_BIG_ENDIAN
        select ARCH_REQUIRE_GPIOLIB
+       select ARCH_SUPPORTS_BIG_ENDIAN
        select CLKSRC_MMIO
        select CPU_XSCALE
        select DMABOUNCE if PCI
@@ -1576,8 +1576,8 @@ config BIG_LITTLE
 config BL_SWITCHER
        bool "big.LITTLE switcher support"
        depends on BIG_LITTLE && MCPM && HOTPLUG_CPU
-       select CPU_PM
        select ARM_CPU_SUSPEND
+       select CPU_PM
        help
          The big.LITTLE "switcher" provides the core functionality to
          transparently handle transition between a cluster of A15's
@@ -1921,9 +1921,9 @@ config XEN
        depends on CPU_V7 && !CPU_V6
        depends on !GENERIC_ATOMIC64
        depends on MMU
+       select ARCH_DMA_ADDR_T_64BIT
        select ARM_PSCI
        select SWIOTLB_XEN
-       select ARCH_DMA_ADDR_T_64BIT
        help
          Say Y if you want to run Linux in a Virtual Machine on Xen on ARM.
 
index 4a2fc0bf6fc913683c29bc2113b85b1f3db9bdd3..eab8ecbe69c1d271369700a9f7aac14c628685b0 100644 (file)
@@ -1030,9 +1030,9 @@ config DEBUG_UART_PHYS
        default 0x40100000 if DEBUG_PXA_UART1
        default 0x42000000 if ARCH_GEMINI
        default 0x7c0003f8 if FOOTBRIDGE
-       default 0x80230000 if DEBUG_PICOXCELL_UART
        default 0x80070000 if DEBUG_IMX23_UART
        default 0x80074000 if DEBUG_IMX28_UART
+       default 0x80230000 if DEBUG_PICOXCELL_UART
        default 0x808c0000 if ARCH_EP93XX
        default 0x90020000 if DEBUG_NSPIRE_CLASSIC_UART || DEBUG_NSPIRE_CX_UART
        default 0xb0090000 if DEBUG_VEXPRESS_UART0_CRX
@@ -1096,22 +1096,22 @@ config DEBUG_UART_VIRT
        default 0xfeb26000 if DEBUG_RK3X_UART1
        default 0xfeb30c00 if DEBUG_KEYSTONE_UART0
        default 0xfeb31000 if DEBUG_KEYSTONE_UART1
-       default 0xfec12000 if DEBUG_MVEBU_UART || DEBUG_MVEBU_UART_ALTERNATE
-       default 0xfed60000 if DEBUG_RK29_UART0
-       default 0xfed64000 if DEBUG_RK29_UART1 || DEBUG_RK3X_UART2
-       default 0xfed68000 if DEBUG_RK29_UART2 || DEBUG_RK3X_UART3
        default 0xfec02000 if DEBUG_SOCFPGA_UART
+       default 0xfec12000 if DEBUG_MVEBU_UART || DEBUG_MVEBU_UART_ALTERNATE
        default 0xfec20000 if DEBUG_DAVINCI_DMx_UART0
        default 0xfed0c000 if DEBUG_DAVINCI_DA8XX_UART1
        default 0xfed0d000 if DEBUG_DAVINCI_DA8XX_UART2
        default 0xfed12000 if ARCH_KIRKWOOD
+       default 0xfed60000 if DEBUG_RK29_UART0
+       default 0xfed64000 if DEBUG_RK29_UART1 || DEBUG_RK3X_UART2
+       default 0xfed68000 if DEBUG_RK29_UART2 || DEBUG_RK3X_UART3
        default 0xfedc0000 if ARCH_EP93XX
        default 0xfee003f8 if FOOTBRIDGE
        default 0xfee20000 if DEBUG_NSPIRE_CLASSIC_UART || DEBUG_NSPIRE_CX_UART
-       default 0xfef36000 if DEBUG_HIGHBANK_UART
        default 0xfee82340 if ARCH_IOP13XX
        default 0xfef00000 if ARCH_IXP4XX && !CPU_BIG_ENDIAN
        default 0xfef00003 if ARCH_IXP4XX && CPU_BIG_ENDIAN
+       default 0xfef36000 if DEBUG_HIGHBANK_UART
        default 0xfefff700 if ARCH_IOP33X
        default 0xff003000 if DEBUG_U300_UART
        default DEBUG_UART_PHYS if !MMU
index 5774b6ea7ad55ab0e6c56a5239c475f00a9feb32..f01c0ee0c87ebd94debc320f5714bf247dfe5ab7 100644 (file)
@@ -797,10 +797,8 @@ static int __init bL_switcher_init(void)
 {
        int ret;
 
-       if (MAX_NR_CLUSTERS != 2) {
-               pr_err("%s: only dual cluster systems are supported\n", __func__);
-               return -EINVAL;
-       }
+       if (!mcpm_is_available())
+               return -ENODEV;
 
        cpu_notifier(bL_switcher_hotplug_callback, 0);
 
index 1e361abc29eb0e106492223348de051d1e4e9f3d..86fd60fefbc935a788b52bdf8701efebbe5d5f8d 100644 (file)
@@ -48,6 +48,11 @@ int __init mcpm_platform_register(const struct mcpm_platform_ops *ops)
        return 0;
 }
 
+bool mcpm_is_available(void)
+{
+       return (platform_ops) ? true : false;
+}
+
 int mcpm_cpu_power_up(unsigned int cpu, unsigned int cluster)
 {
        if (!platform_ops)
index 191ada6e4d2db3393270ef9595e9cc083e441909..662c7bd061081b2fadfc0e790e719d14cc526d77 100644 (file)
                /* Select the best insn combination to perform the   */ \
                /* actual __m * __n / (__p << 64) operation.         */ \
                if (!__c) {                                             \
-                       asm (   "umull  %Q0, %R0, %1, %Q2\n\t"          \
+                       asm (   "umull  %Q0, %R0, %Q1, %Q2\n\t"         \
                                "mov    %Q0, #0"                        \
                                : "=&r" (__res)                         \
                                : "r" (__m), "r" (__n)                  \
index 608516ebabfe6111a651f3a5ca6e63c607046fab..a5ff410dcdb6a47a03a03214bcc0d66fdc33da94 100644 (file)
@@ -53,6 +53,13 @@ void mcpm_set_early_poke(unsigned cpu, unsigned cluster,
  * CPU/cluster power operations API for higher subsystems to use.
  */
 
+/**
+ * mcpm_is_available - returns whether MCPM is initialized and available
+ *
+ * This returns true or false accordingly.
+ */
+bool mcpm_is_available(void);
+
 /**
  * mcpm_cpu_power_up - make given CPU in given cluster runable
  *
index fb5584d0cc050a6c55b30ff8342615a5a39a1c2f..ba94446c72d9127633de59545a3691390ecdfc5d 100644 (file)
 #define __NR_finit_module              (__NR_SYSCALL_BASE+379)
 #define __NR_sched_setattr             (__NR_SYSCALL_BASE+380)
 #define __NR_sched_getattr             (__NR_SYSCALL_BASE+381)
+#define __NR_renameat2                 (__NR_SYSCALL_BASE+382)
 
 /*
  * This may need to be greater than __NR_last_syscall+1 in order to
index 166e945de832f22b603d6b0de2ca3eb92f2ec732..8f51bdcdacbbf6675933f38fb595adbdc825f4c2 100644 (file)
                CALL(sys_finit_module)
 /* 380 */      CALL(sys_sched_setattr)
                CALL(sys_sched_getattr)
+               CALL(sys_renameat2)
 #ifndef syscalls_counted
 .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
 #define syscalls_counted
index f8c08839edf3053c3ee9ac884fab3f61e8ba84b3..591d6e4a64922cda2cd23531e32aa43d339c5dd3 100644 (file)
@@ -587,7 +587,7 @@ __fixup_pv_table:
        add     r6, r6, r3      @ adjust __pv_phys_pfn_offset address
        add     r7, r7, r3      @ adjust __pv_offset address
        mov     r0, r8, lsr #12 @ convert to PFN
-       str     r0, [r6, #LOW_OFFSET]   @ save computed PHYS_OFFSET to __pv_phys_pfn_offset
+       str     r0, [r6]        @ save computed PHYS_OFFSET to __pv_phys_pfn_offset
        strcc   ip, [r7, #HIGH_OFFSET]  @ save to __pv_offset high bits
        mov     r6, r3, lsr #24 @ constant for add/sub instructions
        teq     r3, r6, lsl #24 @ must be 16MiB aligned
index f0d180d8b29f4e22558a98fdf9366ebaf1c0c0cb..8cf0996aa1a8d795bfdb65add498aa1552829382 100644 (file)
@@ -184,3 +184,10 @@ void machine_kexec(struct kimage *image)
 
        soft_restart(reboot_entry_phys);
 }
+
+void arch_crash_save_vmcoreinfo(void)
+{
+#ifdef CONFIG_ARM_LPAE
+       VMCOREINFO_CONFIG(ARM_LPAE);
+#endif
+}
index 702bd329d9d0cd4f8b0912ca3a9694f942f1a568..e90a3148f38540c98c9f7a34ccce3f9ab7de7581 100644 (file)
@@ -203,9 +203,9 @@ asmlinkage long sys_oabi_fcntl64(unsigned int fd, unsigned int cmd,
        int ret;
 
        switch (cmd) {
-       case F_GETLKP:
-       case F_SETLKP:
-       case F_SETLKPW:
+       case F_OFD_GETLK:
+       case F_OFD_SETLK:
+       case F_OFD_SETLKW:
        case F_GETLK64:
        case F_SETLK64:
        case F_SETLKW64:
index 2009a9bc63562af9d761c47f433a4b3d6a80f25d..9989b1b06ffd7dae363552e4d1b973f99f423f0a 100644 (file)
@@ -170,7 +170,7 @@ static struct clk mstp_clks[MSTP_NR] = {
        [MSTP010] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 10, 0), /* SSI2 */
        [MSTP009] = SH_CLK_MSTP32(&p_clk, MSTPCR0,  9, 0), /* SSI3 */
        [MSTP008] = SH_CLK_MSTP32(&p_clk, MSTPCR0,  8, 0), /* SRU */
-       [MSTP007] = SH_CLK_MSTP32(&p_clk, MSTPCR0,  7, 0), /* HSPI */
+       [MSTP007] = SH_CLK_MSTP32(&s_clk, MSTPCR0,  7, 0), /* HSPI */
 };
 
 static struct clk_lookup lookups[] = {
index f5ad9ee70426b0f2a285cc463739a01173994875..5bf7c3c3b3018aa37a721a222714873bec8b92ff 100644 (file)
@@ -420,29 +420,29 @@ config CPU_32v3
        bool
        select CPU_USE_DOMAINS if MMU
        select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
-       select TLS_REG_EMUL if SMP || !MMU
        select NEED_KUSER_HELPERS
+       select TLS_REG_EMUL if SMP || !MMU
 
 config CPU_32v4
        bool
        select CPU_USE_DOMAINS if MMU
        select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
-       select TLS_REG_EMUL if SMP || !MMU
        select NEED_KUSER_HELPERS
+       select TLS_REG_EMUL if SMP || !MMU
 
 config CPU_32v4T
        bool
        select CPU_USE_DOMAINS if MMU
        select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
-       select TLS_REG_EMUL if SMP || !MMU
        select NEED_KUSER_HELPERS
+       select TLS_REG_EMUL if SMP || !MMU
 
 config CPU_32v5
        bool
        select CPU_USE_DOMAINS if MMU
        select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
-       select TLS_REG_EMUL if SMP || !MMU
        select NEED_KUSER_HELPERS
+       select TLS_REG_EMUL if SMP || !MMU
 
 config CPU_32v6
        bool
index f62aa0677e5c4b69918d1ab36e39fada230d3d59..6b00be1f971e15958cc40c369c88ca872f645aa6 100644 (file)
@@ -1963,8 +1963,8 @@ arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base, size_t size)
        mapping->nr_bitmaps = 1;
        mapping->extensions = extensions;
        mapping->base = base;
-       mapping->size = bitmap_size << PAGE_SHIFT;
        mapping->bits = BITS_PER_BYTE * bitmap_size;
+       mapping->size = mapping->bits << PAGE_SHIFT;
 
        spin_lock_init(&mapping->lock);
 
index 6cac43bd1d86c63638993bafa8ba989fea52e91f..423f56dd40283c3f7615a5aec0c1d5422313d61a 100644 (file)
@@ -866,6 +866,8 @@ vfp_double_multiply_accumulate(int dd, int dn, int dm, u32 fpscr, u32 negate, ch
                vdp.sign = vfp_sign_negate(vdp.sign);
 
        vfp_double_unpack(&vdn, vfp_get_double(dd));
+       if (vdn.exponent == 0 && vdn.significand)
+               vfp_double_normalise_denormal(&vdn);
        if (negate & NEG_SUBTRACT)
                vdn.sign = vfp_sign_negate(vdn.sign);
 
index b252631b406bd22bcbe040ede3d3f4dfbea8e987..4f96c1617aaec257a68496464aacbafe1f8d7ab8 100644 (file)
@@ -915,6 +915,8 @@ vfp_single_multiply_accumulate(int sd, int sn, s32 m, u32 fpscr, u32 negate, cha
        v = vfp_get_float(sd);
        pr_debug("VFP: s%u = %08x\n", sd, v);
        vfp_single_unpack(&vsn, v);
+       if (vsn.exponent == 0 && vsn.significand)
+               vfp_single_normalise_denormal(&vsn);
        if (negate & NEG_SUBTRACT)
                vsn.sign = vfp_sign_negate(vsn.sign);
 
index 75298d3358e7f3d2c7ff4e2b2c5ed8b81a8dca6d..08eec0b691b061ade61d8f9df7258ea4bee49f42 100644 (file)
@@ -136,6 +136,7 @@ extern int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg);
 extern int os_get_ifname(int fd, char *namebuf);
 extern int os_set_slip(int fd);
 extern int os_mode_fd(int fd, int mode);
+extern int os_fsync_file(int fd);
 
 extern int os_seek_file(int fd, unsigned long long offset);
 extern int os_open_file(const char *file, struct openflags flags, int mode);
index f116db15d4028217767f2a7f51dc0bba38b151a9..30fdd5d0067b26c91fb8c831da5a1d4008c79e22 100644 (file)
@@ -103,6 +103,7 @@ void __init setup_physmem(unsigned long start, unsigned long reserve_end,
         */
        os_seek_file(physmem_fd, __pa(&__syscall_stub_start));
        os_write_file(physmem_fd, &__syscall_stub_start, PAGE_SIZE);
+       os_fsync_file(physmem_fd);
 
        bootmap_size = init_bootmem(pfn, pfn + delta);
        free_bootmem(__pa(reserve_end) + bootmap_size,
index 07a750197bb09d3b5ce59b631aed874d58603386..08d90fba952c3e1ba07e0fa488012aa26a6b473c 100644 (file)
@@ -237,6 +237,12 @@ void os_close_file(int fd)
 {
        close(fd);
 }
+int os_fsync_file(int fd)
+{
+       if (fsync(fd) < 0)
+           return -errno;
+       return 0;
+}
 
 int os_seek_file(int fd, unsigned long long offset)
 {
index e1704ff600ff9e677a98a4711d5c8b7b2ff8cf6a..df9191acd926cfb3b5a0c3582549105ac0729d5a 100644 (file)
@@ -151,6 +151,7 @@ int __init main(int argc, char **argv, char **envp)
 #endif
 
        do_uml_initcalls();
+       change_sig(SIGPIPE, 0);
        ret = linux_main(argc, argv);
 
        /*
index 3c4af77e51a2f9047ad603fe1032334111d08e9f..897e9ad0c108ed7ef70571628ed2fde039109508 100644 (file)
 #include <string.h>
 #include <sys/stat.h>
 #include <sys/mman.h>
-#include <sys/param.h>
+#include <sys/vfs.h>
+#include <linux/magic.h>
 #include <init.h>
 #include <os.h>
 
-/* Modified by which_tmpdir, which is called during early boot */
-static char *default_tmpdir = "/tmp";
-
-/*
- *  Modified when creating the physical memory file and when checking
- * the tmp filesystem for usability, both happening during early boot.
- */
+/* Set by make_tempfile() during early boot. */
 static char *tempdir = NULL;
 
-static void __init find_tempdir(void)
+/* Check if dir is on tmpfs. Return 0 if yes, -1 if no or error. */
+static int __init check_tmpfs(const char *dir)
 {
-       const char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL };
-       int i;
-       char *dir = NULL;
-
-       if (tempdir != NULL)
-               /* We've already been called */
-               return;
-       for (i = 0; dirs[i]; i++) {
-               dir = getenv(dirs[i]);
-               if ((dir != NULL) && (*dir != '\0'))
-                       break;
-       }
-       if ((dir == NULL) || (*dir == '\0'))
-               dir = default_tmpdir;
+       struct statfs st;
 
-       tempdir = malloc(strlen(dir) + 2);
-       if (tempdir == NULL) {
-               fprintf(stderr, "Failed to malloc tempdir, "
-                       "errno = %d\n", errno);
-               return;
-       }
-       strcpy(tempdir, dir);
-       strcat(tempdir, "/");
-}
-
-/*
- * Remove bytes from the front of the buffer and refill it so that if there's a
- * partial string that we care about, it will be completed, and we can recognize
- * it.
- */
-static int pop(int fd, char *buf, size_t size, size_t npop)
-{
-       ssize_t n;
-       size_t len = strlen(&buf[npop]);
-
-       memmove(buf, &buf[npop], len + 1);
-       n = read(fd, &buf[len], size - len - 1);
-       if (n < 0)
-               return -errno;
-
-       buf[len + n] = '\0';
-       return 1;
-}
-
-/*
- * This will return 1, with the first character in buf being the
- * character following the next instance of c in the file.  This will
- * read the file as needed.  If there's an error, -errno is returned;
- * if the end of the file is reached, 0 is returned.
- */
-static int next(int fd, char *buf, size_t size, char c)
-{
-       ssize_t n;
-       char *ptr;
-
-       while ((ptr = strchr(buf, c)) == NULL) {
-               n = read(fd, buf, size - 1);
-               if (n == 0)
-                       return 0;
-               else if (n < 0)
-                       return -errno;
-
-               buf[n] = '\0';
+       printf("Checking if %s is on tmpfs...", dir);
+       if (statfs(dir, &st) < 0) {
+               printf("%s\n", strerror(errno));
+       } else if (st.f_type != TMPFS_MAGIC) {
+               printf("no\n");
+       } else {
+               printf("OK\n");
+               return 0;
        }
-
-       return pop(fd, buf, size, ptr - buf + 1);
+       return -1;
 }
 
 /*
- * Decode an octal-escaped and space-terminated path of the form used by
- * /proc/mounts. May be used to decode a path in-place. "out" must be at least
- * as large as the input. The output is always null-terminated. "len" gets the
- * length of the output, excluding the trailing null. Returns 0 if a full path
- * was successfully decoded, otherwise an error.
+ * Choose the tempdir to use. We want something on tmpfs so that our memory is
+ * not subject to the host's vm.dirty_ratio. If a tempdir is specified in the
+ * environment, we use that even if it's not on tmpfs, but we warn the user.
+ * Otherwise, we try common tmpfs locations, and if no tmpfs directory is found
+ * then we fall back to /tmp.
  */
-static int decode_path(const char *in, char *out, size_t *len)
+static char * __init choose_tempdir(void)
 {
-       char *first = out;
-       int c;
+       static const char * const vars[] = {
+               "TMPDIR",
+               "TMP",
+               "TEMP",
+               NULL
+       };
+       static const char fallback_dir[] = "/tmp";
+       static const char * const tmpfs_dirs[] = {
+               "/dev/shm",
+               fallback_dir,
+               NULL
+       };
        int i;
-       int ret = -EINVAL;
-       while (1) {
-               switch (*in) {
-               case '\0':
-                       goto out;
-
-               case ' ':
-                       ret = 0;
-                       goto out;
-
-               case '\\':
-                       in++;
-                       c = 0;
-                       for (i = 0; i < 3; i++) {
-                               if (*in < '0' || *in > '7')
-                                       goto out;
-                               c = (c << 3) | (*in++ - '0');
-                       }
-                       *(unsigned char *)out++ = (unsigned char) c;
-                       break;
-
-               default:
-                       *out++ = *in++;
-                       break;
+       const char *dir;
+
+       printf("Checking environment variables for a tempdir...");
+       for (i = 0; vars[i]; i++) {
+               dir = getenv(vars[i]);
+               if ((dir != NULL) && (*dir != '\0')) {
+                       printf("%s\n", dir);
+                       if (check_tmpfs(dir) >= 0)
+                               goto done;
+                       else
+                               goto warn;
                }
        }
+       printf("none found\n");
 
-out:
-       *out = '\0';
-       *len = out - first;
-       return ret;
-}
-
-/*
- * Computes the length of s when encoded with three-digit octal escape sequences
- * for the characters in chars.
- */
-static size_t octal_encoded_length(const char *s, const char *chars)
-{
-       size_t len = strlen(s);
-       while ((s = strpbrk(s, chars)) != NULL) {
-               len += 3;
-               s++;
-       }
-
-       return len;
-}
-
-enum {
-       OUTCOME_NOTHING_MOUNTED,
-       OUTCOME_TMPFS_MOUNT,
-       OUTCOME_NON_TMPFS_MOUNT,
-};
-
-/* Read a line of /proc/mounts data looking for a tmpfs mount at "path". */
-static int read_mount(int fd, char *buf, size_t bufsize, const char *path,
-                     int *outcome)
-{
-       int found;
-       int match;
-       char *space;
-       size_t len;
-
-       enum {
-               MATCH_NONE,
-               MATCH_EXACT,
-               MATCH_PARENT,
-       };
-
-       found = next(fd, buf, bufsize, ' ');
-       if (found != 1)
-               return found;
-
-       /*
-        * If there's no following space in the buffer, then this path is
-        * truncated, so it can't be the one we're looking for.
-        */
-       space = strchr(buf, ' ');
-       if (space) {
-               match = MATCH_NONE;
-               if (!decode_path(buf, buf, &len)) {
-                       if (!strcmp(buf, path))
-                               match = MATCH_EXACT;
-                       else if (!strncmp(buf, path, len)
-                                && (path[len] == '/' || !strcmp(buf, "/")))
-                               match = MATCH_PARENT;
-               }
-
-               found = pop(fd, buf, bufsize, space - buf + 1);
-               if (found != 1)
-                       return found;
-
-               switch (match) {
-               case MATCH_EXACT:
-                       if (!strncmp(buf, "tmpfs", strlen("tmpfs")))
-                               *outcome = OUTCOME_TMPFS_MOUNT;
-                       else
-                               *outcome = OUTCOME_NON_TMPFS_MOUNT;
-                       break;
-
-               case MATCH_PARENT:
-                       /* This mount obscures any previous ones. */
-                       *outcome = OUTCOME_NOTHING_MOUNTED;
-                       break;
-               }
+       for (i = 0; tmpfs_dirs[i]; i++) {
+               dir = tmpfs_dirs[i];
+               if (check_tmpfs(dir) >= 0)
+                       goto done;
        }
 
-       return next(fd, buf, bufsize, '\n');
+       dir = fallback_dir;
+warn:
+       printf("Warning: tempdir %s is not on tmpfs\n", dir);
+done:
+       /* Make a copy since getenv results may not remain valid forever. */
+       return strdup(dir);
 }
 
-/* which_tmpdir is called only during early boot */
-static int checked_tmpdir = 0;
-
 /*
- * Look for a tmpfs mounted at /dev/shm.  I couldn't find a cleaner
- * way to do this than to parse /proc/mounts.  statfs will return the
- * same filesystem magic number and fs id for both /dev and /dev/shm
- * when they are both tmpfs, so you can't tell if they are different
- * filesystems.  Also, there seems to be no other way of finding the
- * mount point of a filesystem from within it.
- *
- * If a /dev/shm tmpfs entry is found, then we switch to using it.
- * Otherwise, we stay with the default /tmp.
+ * Create an unlinked tempfile in a suitable tempdir. template must be the
+ * basename part of the template with a leading '/'.
  */
-static void which_tmpdir(void)
+static int __init make_tempfile(const char *template)
 {
+       char *tempname;
        int fd;
-       int found;
-       int outcome;
-       char *path;
-       char *buf;
-       size_t bufsize;
 
-       if (checked_tmpdir)
-               return;
-
-       checked_tmpdir = 1;
-
-       printf("Checking for tmpfs mount on /dev/shm...");
-
-       path = realpath("/dev/shm", NULL);
-       if (!path) {
-               printf("failed to check real path, errno = %d\n", errno);
-               return;
-       }
-       printf("%s...", path);
-
-       /*
-        * The buffer needs to be able to fit the full octal-escaped path, a
-        * space, and a trailing null in order to successfully decode it.
-        */
-       bufsize = octal_encoded_length(path, " \t\n\\") + 2;
-
-       if (bufsize < 128)
-               bufsize = 128;
-
-       buf = malloc(bufsize);
-       if (!buf) {
-               printf("malloc failed, errno = %d\n", errno);
-               goto out;
-       }
-       buf[0] = '\0';
-
-       fd = open("/proc/mounts", O_RDONLY);
-       if (fd < 0) {
-               printf("failed to open /proc/mounts, errno = %d\n", errno);
-               goto out1;
-       }
-
-       outcome = OUTCOME_NOTHING_MOUNTED;
-       while (1) {
-               found = read_mount(fd, buf, bufsize, path, &outcome);
-               if (found != 1)
-                       break;
-       }
-
-       if (found < 0) {
-               printf("read returned errno %d\n", -found);
-       } else {
-               switch (outcome) {
-               case OUTCOME_TMPFS_MOUNT:
-                       printf("OK\n");
-                       default_tmpdir = "/dev/shm";
-                       break;
-
-               case OUTCOME_NON_TMPFS_MOUNT:
-                       printf("not tmpfs\n");
-                       break;
-
-               default:
-                       printf("nothing mounted on /dev/shm\n");
-                       break;
+       if (tempdir == NULL) {
+               tempdir = choose_tempdir();
+               if (tempdir == NULL) {
+                       fprintf(stderr, "Failed to choose tempdir: %s\n",
+                               strerror(errno));
+                       return -1;
                }
        }
 
-       close(fd);
-out1:
-       free(buf);
-out:
-       free(path);
-}
-
-static int __init make_tempfile(const char *template, char **out_tempname,
-                               int do_unlink)
-{
-       char *tempname;
-       int fd;
-
-       which_tmpdir();
-       tempname = malloc(MAXPATHLEN);
+       tempname = malloc(strlen(tempdir) + strlen(template) + 1);
        if (tempname == NULL)
                return -1;
 
-       find_tempdir();
-       if ((tempdir == NULL) || (strlen(tempdir) >= MAXPATHLEN))
-               goto out;
-
-       if (template[0] != '/')
-               strcpy(tempname, tempdir);
-       else
-               tempname[0] = '\0';
-       strncat(tempname, template, MAXPATHLEN-1-strlen(tempname));
+       strcpy(tempname, tempdir);
+       strcat(tempname, template);
        fd = mkstemp(tempname);
        if (fd < 0) {
                fprintf(stderr, "open - cannot create %s: %s\n", tempname,
                        strerror(errno));
                goto out;
        }
-       if (do_unlink && (unlink(tempname) < 0)) {
+       if (unlink(tempname) < 0) {
                perror("unlink");
                goto close;
        }
-       if (out_tempname) {
-               *out_tempname = tempname;
-       } else
-               free(tempname);
+       free(tempname);
        return fd;
 close:
        close(fd);
@@ -351,14 +131,14 @@ out:
        return -1;
 }
 
-#define TEMPNAME_TEMPLATE "vm_file-XXXXXX"
+#define TEMPNAME_TEMPLATE "/vm_file-XXXXXX"
 
 static int __init create_tmp_file(unsigned long long len)
 {
        int fd, err;
        char zero;
 
-       fd = make_tempfile(TEMPNAME_TEMPLATE, NULL, 1);
+       fd = make_tempfile(TEMPNAME_TEMPLATE);
        if (fd < 0)
                exit(1);
 
@@ -402,7 +182,6 @@ int __init create_mem_file(unsigned long long len)
        return fd;
 }
 
-
 void __init check_tmpexec(void)
 {
        void *addr;
@@ -410,14 +189,13 @@ void __init check_tmpexec(void)
 
        addr = mmap(NULL, UM_KERN_PAGE_SIZE,
                    PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
-       printf("Checking PROT_EXEC mmap in %s...",tempdir);
-       fflush(stdout);
+       printf("Checking PROT_EXEC mmap in %s...", tempdir);
        if (addr == MAP_FAILED) {
                err = errno;
-               perror("failed");
+               printf("%s\n", strerror(err));
                close(fd);
                if (err == EPERM)
-                       printf("%s must be not mounted noexec\n",tempdir);
+                       printf("%s must be not mounted noexec\n", tempdir);
                exit(1);
        }
        printf("OK\n");
index 2e263f367b139c30da34b9e346007e206132955e..9df017ab2285a015a111cc384a0f28d6e488bbf8 100644 (file)
@@ -9,12 +9,9 @@ SECTIONS
 #ifdef BUILD_VDSO32
 #include <asm/vdso32.h>
 
-       .hpet_sect : {
-               hpet_page = . - VDSO_OFFSET(VDSO_HPET_PAGE);
-       } :text :hpet_sect
+       hpet_page = . - VDSO_OFFSET(VDSO_HPET_PAGE);
 
-       .vvar_sect : {
-               vvar = . - VDSO_OFFSET(VDSO_VVAR_PAGE);
+       vvar = . - VDSO_OFFSET(VDSO_VVAR_PAGE);
 
        /* Place all vvars at the offsets in asm/vvar.h. */
 #define EMIT_VVAR(name, offset) vvar_ ## name = vvar + offset;
@@ -22,7 +19,6 @@ SECTIONS
 #include <asm/vvar.h>
 #undef __VVAR_KERNEL_LDS
 #undef EMIT_VVAR
-       } :text :vvar_sect
 #endif
        . = SIZEOF_HEADERS;
 
@@ -61,7 +57,12 @@ SECTIONS
         */
        . = ALIGN(0x100);
 
-       .text           : { *(.text*) }                 :text   =0x90909090
+       .text           : { *(.text*) }                 :text   =0x90909090,
+
+       /*
+        * The comma above works around a bug in gold:
+        * https://sourceware.org/bugzilla/show_bug.cgi?id=16804
+        */
 
        /DISCARD/ : {
                *(.discard)
@@ -84,8 +85,4 @@ PHDRS
        dynamic         PT_DYNAMIC      FLAGS(4);               /* PF_R */
        note            PT_NOTE         FLAGS(4);               /* PF_R */
        eh_frame_hdr    PT_GNU_EH_FRAME;
-#ifdef BUILD_VDSO32
-       vvar_sect       PT_NULL         FLAGS(4);               /* PF_R */
-       hpet_sect       PT_NULL         FLAGS(4);               /* PF_R */
-#endif
 }
index 20e03a7eb8b431f692e534f6a3d895a2c2cd9476..c2706047337f17c0fad38b3161cabc93d95be0e5 100644 (file)
@@ -116,7 +116,7 @@ config AHCI_ST
 
 config AHCI_IMX
        tristate "Freescale i.MX AHCI SATA support"
-       depends on MFD_SYSCON
+       depends on MFD_SYSCON && (ARCH_MXC || COMPILE_TEST)
        help
          This option enables support for the Freescale i.MX SoC's
          onboard AHCI SATA.
@@ -134,8 +134,7 @@ config AHCI_SUNXI
 
 config AHCI_XGENE
        tristate "APM X-Gene 6.0Gbps AHCI SATA host controller support"
-       depends on ARM64 || COMPILE_TEST
-       select PHY_XGENE
+       depends on PHY_XGENE
        help
         This option enables support for APM X-Gene SoC SATA host controller.
 
index 5a0bf8ed649b8cf9266530ef309aec89a54f99ef..71e15b73513d22ed2bf5ac34afec9b5f42679fe7 100644 (file)
@@ -1164,9 +1164,9 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host)
 #endif
 
 static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports,
-                        struct ahci_host_priv *hpriv)
+                               struct ahci_host_priv *hpriv)
 {
-       int nvec;
+       int rc, nvec;
 
        if (hpriv->flags & AHCI_HFLAG_NO_MSI)
                goto intx;
@@ -1183,12 +1183,19 @@ static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports,
        if (nvec < n_ports)
                goto single_msi;
 
-       nvec = pci_enable_msi_range(pdev, nvec, nvec);
-       if (nvec == -ENOSPC)
+       rc = pci_enable_msi_exact(pdev, nvec);
+       if (rc == -ENOSPC)
                goto single_msi;
-       else if (nvec < 0)
+       else if (rc < 0)
                goto intx;
 
+       /* fallback to single MSI mode if the controller enforced MRSM mode */
+       if (readl(hpriv->mmio + HOST_CTL) & HOST_MRSM) {
+               pci_disable_msi(pdev);
+               printk(KERN_INFO "ahci: MRSM is on, fallback to single MSI\n");
+               goto single_msi;
+       }
+
        return nvec;
 
 single_msi:
@@ -1232,18 +1239,18 @@ int ahci_host_activate(struct ata_host *host, int irq, unsigned int n_msis)
                return rc;
 
        for (i = 0; i < host->n_ports; i++) {
-               const char* desc;
                struct ahci_port_priv *pp = host->ports[i]->private_data;
 
-               /* pp is NULL for dummy ports */
-               if (pp)
-                       desc = pp->irq_desc;
-               else
-                       desc = dev_driver_string(host->dev);
+               /* Do not receive interrupts sent by dummy ports */
+               if (!pp) {
+                       disable_irq(irq + i);
+                       continue;
+               }
 
-               rc = devm_request_threaded_irq(host->dev,
-                       irq + i, ahci_hw_interrupt, ahci_thread_fn, IRQF_SHARED,
-                       desc, host->ports[i]);
+               rc = devm_request_threaded_irq(host->dev, irq + i,
+                                              ahci_hw_interrupt,
+                                              ahci_thread_fn, IRQF_SHARED,
+                                              pp->irq_desc, host->ports[i]);
                if (rc)
                        goto out_free_irqs;
        }
index 51af275b3388541baad3f7bf021a098de9da9bf0..b5eb886da22635c3c76775bc0ef6374af3464b98 100644 (file)
@@ -94,6 +94,7 @@ enum {
        /* HOST_CTL bits */
        HOST_RESET              = (1 << 0),  /* reset controller; self-clear */
        HOST_IRQ_EN             = (1 << 1),  /* global IRQ enable */
+       HOST_MRSM               = (1 << 2),  /* MSI Revert to Single Message */
        HOST_AHCI_EN            = (1 << 31), /* AHCI enabled */
 
        /* HOST_CAP bits */
index c19734d96d7e6a029a1adf9667ce5a897708b58c..943cc8b83e59bb7f1b293abce887be717047ffff 100644 (file)
@@ -4224,8 +4224,10 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        { "PIONEER DVD-RW  DVR-216D",   NULL,   ATA_HORKAGE_NOSETXFER },
 
        /* devices that don't properly handle queued TRIM commands */
-       { "Micron_M500*",               NULL,   ATA_HORKAGE_NO_NCQ_TRIM, },
-       { "Crucial_CT???M500SSD*",      NULL,   ATA_HORKAGE_NO_NCQ_TRIM, },
+       { "Micron_M500*",               "MU0[1-4]*",    ATA_HORKAGE_NO_NCQ_TRIM, },
+       { "Crucial_CT???M500SSD*",      "MU0[1-4]*",    ATA_HORKAGE_NO_NCQ_TRIM, },
+       { "Micron_M550*",               NULL,           ATA_HORKAGE_NO_NCQ_TRIM, },
+       { "Crucial_CT???M550SSD*",      NULL,           ATA_HORKAGE_NO_NCQ_TRIM, },
 
        /*
         * Some WD SATA-I drives spin up and down erratically when the link
@@ -4792,21 +4794,26 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
 static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
 {
        struct ata_queued_cmd *qc = NULL;
-       unsigned int i;
+       unsigned int i, tag;
 
        /* no command while frozen */
        if (unlikely(ap->pflags & ATA_PFLAG_FROZEN))
                return NULL;
 
-       /* the last tag is reserved for internal command. */
-       for (i = 0; i < ATA_MAX_QUEUE - 1; i++)
-               if (!test_and_set_bit(i, &ap->qc_allocated)) {
-                       qc = __ata_qc_from_tag(ap, i);
+       for (i = 0; i < ATA_MAX_QUEUE; i++) {
+               tag = (i + ap->last_tag + 1) % ATA_MAX_QUEUE;
+
+               /* the last tag is reserved for internal command. */
+               if (tag == ATA_TAG_INTERNAL)
+                       continue;
+
+               if (!test_and_set_bit(tag, &ap->qc_allocated)) {
+                       qc = __ata_qc_from_tag(ap, tag);
+                       qc->tag = tag;
+                       ap->last_tag = tag;
                        break;
                }
-
-       if (qc)
-               qc->tag = i;
+       }
 
        return qc;
 }
index 6fac524c2f500381ac8d76b2a94bf4d88314f1e7..4edb1a81f63f68e3f37680b7334a3d7b81788f96 100644 (file)
@@ -898,9 +898,12 @@ static int arasan_cf_probe(struct platform_device *pdev)
 
        cf_card_detect(acdev, 0);
 
-       return ata_host_activate(host, acdev->irq, irq_handler, 0,
-                       &arasan_cf_sht);
+       ret = ata_host_activate(host, acdev->irq, irq_handler, 0,
+                               &arasan_cf_sht);
+       if (!ret)
+               return 0;
 
+       cf_exit(acdev);
 free_clk:
        clk_put(acdev->clk);
        return ret;
index e9c87274a781551d4496ac81b213855dd766ae41..8a66f23af4c40bd0ffd9e01776c02a16b26f0584 100644 (file)
@@ -407,12 +407,13 @@ static int pata_at91_probe(struct platform_device *pdev)
 
        host->private_data = info;
 
-       return ata_host_activate(host, gpio_is_valid(irq) ? gpio_to_irq(irq) : 0,
-                       gpio_is_valid(irq) ? ata_sff_interrupt : NULL,
-                       irq_flags, &pata_at91_sht);
+       ret = ata_host_activate(host, gpio_is_valid(irq) ? gpio_to_irq(irq) : 0,
+                               gpio_is_valid(irq) ? ata_sff_interrupt : NULL,
+                               irq_flags, &pata_at91_sht);
+       if (ret)
+               goto err_put;
 
-       if (!ret)
-               return 0;
+       return 0;
 
 err_put:
        clk_put(info->mck);
index a79566d056666f0d0449785856b679492d71456b..0610e78c8a2a8334cfa8b6d585285606af3613bc 100644 (file)
@@ -594,9 +594,13 @@ static int __init pata_s3c_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, host);
 
-       return ata_host_activate(host, info->irq,
-                       info->irq ? pata_s3c_irq : NULL,
-                       0, &pata_s3c_sht);
+       ret = ata_host_activate(host, info->irq,
+                               info->irq ? pata_s3c_irq : NULL,
+                               0, &pata_s3c_sht);
+       if (ret)
+               goto stop_clk;
+
+       return 0;
 
 stop_clk:
        clk_disable(info->clk);
index bf0f8b476696eeade9ff5b7947dc64628181a7ca..401add28933f4f6f39c70b626e081ec39aef554b 100644 (file)
@@ -233,7 +233,7 @@ static void acpi_gpiochip_request_interrupts(struct acpi_gpio_chip *acpi_gpio)
 {
        struct gpio_chip *chip = acpi_gpio->chip;
 
-       if (!chip->dev || !chip->to_irq)
+       if (!chip->to_irq)
                return;
 
        INIT_LIST_HEAD(&acpi_gpio->events);
@@ -253,7 +253,7 @@ static void acpi_gpiochip_free_interrupts(struct acpi_gpio_chip *acpi_gpio)
        struct acpi_gpio_event *event, *ep;
        struct gpio_chip *chip = acpi_gpio->chip;
 
-       if (!chip->dev || !chip->to_irq)
+       if (!chip->to_irq)
                return;
 
        list_for_each_entry_safe_reverse(event, ep, &acpi_gpio->events, node) {
@@ -451,7 +451,7 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
                if (function == ACPI_WRITE)
                        gpiod_set_raw_value(desc, !!((1 << i) & *value));
                else
-                       *value |= gpiod_get_raw_value(desc) << i;
+                       *value |= (u64)gpiod_get_raw_value(desc) << i;
        }
 
 out:
@@ -501,6 +501,9 @@ void acpi_gpiochip_add(struct gpio_chip *chip)
        acpi_handle handle;
        acpi_status status;
 
+       if (!chip || !chip->dev)
+               return;
+
        handle = ACPI_HANDLE(chip->dev);
        if (!handle)
                return;
@@ -531,6 +534,9 @@ void acpi_gpiochip_remove(struct gpio_chip *chip)
        acpi_handle handle;
        acpi_status status;
 
+       if (!chip || !chip->dev)
+               return;
+
        handle = ACPI_HANDLE(chip->dev);
        if (!handle)
                return;
index 761013f8b82f5a3d7c534f201a45f2c5902cd188..f48817d974802c3ec771814bef84bc97ab6039b5 100644 (file)
@@ -1387,8 +1387,8 @@ static int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,
 {
        struct gpio_chip *chip = d->host_data;
 
-       irq_set_chip_and_handler(irq, chip->irqchip, chip->irq_handler);
        irq_set_chip_data(irq, chip);
+       irq_set_chip_and_handler(irq, chip->irqchip, chip->irq_handler);
 #ifdef CONFIG_ARM
        set_irq_flags(irq, IRQF_VALID);
 #else
index 15936524f226ca46b9631cadf43022aa2cc81d31..bc0119fb6c12a9373e1bd282886d38f8ed858135 100644 (file)
@@ -209,6 +209,7 @@ void radeon_dp_aux_init(struct radeon_connector *radeon_connector)
 {
        int ret;
 
+       radeon_connector->ddc_bus->rec.hpd = radeon_connector->hpd.hpd;
        radeon_connector->ddc_bus->aux.dev = radeon_connector->base.kdev;
        radeon_connector->ddc_bus->aux.transfer = radeon_dp_aux_transfer;
        ret = drm_dp_aux_register_i2c_bus(&radeon_connector->ddc_bus->aux);
index 89b4afa5041c322a15afc67bfbba7f7cf2cef8d6..f7e46cf682afdcbe051cb4a6ecf6dfe66570a5c3 100644 (file)
@@ -597,7 +597,7 @@ int cik_sdma_ring_test(struct radeon_device *rdev,
        tmp = 0xCAFEDEAD;
        writel(tmp, ptr);
 
-       r = radeon_ring_lock(rdev, ring, 4);
+       r = radeon_ring_lock(rdev, ring, 5);
        if (r) {
                DRM_ERROR("radeon: dma failed to lock ring %d (%d).\n", ring->idx, r);
                return r;
index cbf7e3269f84882d1352a44ea402fa5dc4cbba7c..9c61b74ef4415cbf1f7bce501b268662d80da8de 100644 (file)
@@ -158,16 +158,18 @@ u32 r600_dpm_get_vblank_time(struct radeon_device *rdev)
        u32 line_time_us, vblank_lines;
        u32 vblank_time_us = 0xffffffff; /* if the displays are off, vblank time is max */
 
-       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-               radeon_crtc = to_radeon_crtc(crtc);
-               if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) {
-                       line_time_us = (radeon_crtc->hw_mode.crtc_htotal * 1000) /
-                               radeon_crtc->hw_mode.clock;
-                       vblank_lines = radeon_crtc->hw_mode.crtc_vblank_end -
-                               radeon_crtc->hw_mode.crtc_vdisplay +
-                               (radeon_crtc->v_border * 2);
-                       vblank_time_us = vblank_lines * line_time_us;
-                       break;
+       if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) {
+               list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+                       radeon_crtc = to_radeon_crtc(crtc);
+                       if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) {
+                               line_time_us = (radeon_crtc->hw_mode.crtc_htotal * 1000) /
+                                       radeon_crtc->hw_mode.clock;
+                               vblank_lines = radeon_crtc->hw_mode.crtc_vblank_end -
+                                       radeon_crtc->hw_mode.crtc_vdisplay +
+                                       (radeon_crtc->v_border * 2);
+                               vblank_time_us = vblank_lines * line_time_us;
+                               break;
+                       }
                }
        }
 
@@ -181,14 +183,15 @@ u32 r600_dpm_get_vrefresh(struct radeon_device *rdev)
        struct radeon_crtc *radeon_crtc;
        u32 vrefresh = 0;
 
-       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-               radeon_crtc = to_radeon_crtc(crtc);
-               if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) {
-                       vrefresh = radeon_crtc->hw_mode.vrefresh;
-                       break;
+       if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) {
+               list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+                       radeon_crtc = to_radeon_crtc(crtc);
+                       if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) {
+                               vrefresh = radeon_crtc->hw_mode.vrefresh;
+                               break;
+                       }
                }
        }
-
        return vrefresh;
 }
 
index dedea72f48c45b95022ec9bcb60cf85e8073e187..a9fb0d016d387683a1d4bb96f77c046b7cd804b7 100644 (file)
@@ -528,6 +528,13 @@ static bool radeon_atpx_detect(void)
                has_atpx |= (radeon_atpx_pci_probe_handle(pdev) == true);
        }
 
+       /* some newer PX laptops mark the dGPU as a non-VGA display device */
+       while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) {
+               vga_count++;
+
+               has_atpx |= (radeon_atpx_pci_probe_handle(pdev) == true);
+       }
+
        if (has_atpx && vga_count == 2) {
                acpi_get_name(radeon_atpx_priv.atpx.handle, ACPI_FULL_PATHNAME, &buffer);
                printk(KERN_INFO "VGA switcheroo: detected switching method %s handle\n",
index 2f7cbb901fb18c04c30c48e7357c23d01edc2529..8d99d5ee8014c4f23e031a31cbeab85bde33d81a 100644 (file)
@@ -839,6 +839,38 @@ static void avivo_reduce_ratio(unsigned *nom, unsigned *den,
        }
 }
 
+/**
+ * avivo_get_fb_ref_div - feedback and ref divider calculation
+ *
+ * @nom: nominator
+ * @den: denominator
+ * @post_div: post divider
+ * @fb_div_max: feedback divider maximum
+ * @ref_div_max: reference divider maximum
+ * @fb_div: resulting feedback divider
+ * @ref_div: resulting reference divider
+ *
+ * Calculate feedback and reference divider for a given post divider. Makes
+ * sure we stay within the limits.
+ */
+static void avivo_get_fb_ref_div(unsigned nom, unsigned den, unsigned post_div,
+                                unsigned fb_div_max, unsigned ref_div_max,
+                                unsigned *fb_div, unsigned *ref_div)
+{
+       /* limit reference * post divider to a maximum */
+       ref_div_max = min(210 / post_div, ref_div_max);
+
+       /* get matching reference and feedback divider */
+       *ref_div = min(max(DIV_ROUND_CLOSEST(den, post_div), 1u), ref_div_max);
+       *fb_div = DIV_ROUND_CLOSEST(nom * *ref_div * post_div, den);
+
+       /* limit fb divider to its maximum */
+        if (*fb_div > fb_div_max) {
+               *ref_div = DIV_ROUND_CLOSEST(*ref_div * fb_div_max, *fb_div);
+               *fb_div = fb_div_max;
+       }
+}
+
 /**
  * radeon_compute_pll_avivo - compute PLL paramaters
  *
@@ -860,6 +892,9 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll,
                              u32 *ref_div_p,
                              u32 *post_div_p)
 {
+       unsigned target_clock = pll->flags & RADEON_PLL_USE_FRAC_FB_DIV ?
+               freq : freq / 10;
+
        unsigned fb_div_min, fb_div_max, fb_div;
        unsigned post_div_min, post_div_max, post_div;
        unsigned ref_div_min, ref_div_max, ref_div;
@@ -880,14 +915,18 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll,
                ref_div_min = pll->reference_div;
        else
                ref_div_min = pll->min_ref_div;
-       ref_div_max = pll->max_ref_div;
+
+       if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV &&
+           pll->flags & RADEON_PLL_USE_REF_DIV)
+               ref_div_max = pll->reference_div;
+       else
+               ref_div_max = pll->max_ref_div;
 
        /* determine allowed post divider range */
        if (pll->flags & RADEON_PLL_USE_POST_DIV) {
                post_div_min = pll->post_div;
                post_div_max = pll->post_div;
        } else {
-               unsigned target_clock = freq / 10;
                unsigned vco_min, vco_max;
 
                if (pll->flags & RADEON_PLL_IS_LCD) {
@@ -898,6 +937,11 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll,
                        vco_max = pll->pll_out_max;
                }
 
+               if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) {
+                       vco_min *= 10;
+                       vco_max *= 10;
+               }
+
                post_div_min = vco_min / target_clock;
                if ((target_clock * post_div_min) < vco_min)
                        ++post_div_min;
@@ -912,7 +956,7 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll,
        }
 
        /* represent the searched ratio as fractional number */
-       nom = pll->flags & RADEON_PLL_USE_FRAC_FB_DIV ? freq : freq / 10;
+       nom = target_clock;
        den = pll->reference_freq;
 
        /* reduce the numbers to a simpler ratio */
@@ -926,7 +970,12 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll,
        diff_best = ~0;
 
        for (post_div = post_div_min; post_div <= post_div_max; ++post_div) {
-               unsigned diff = abs(den - den / post_div * post_div);
+               unsigned diff;
+               avivo_get_fb_ref_div(nom, den, post_div, fb_div_max,
+                                    ref_div_max, &fb_div, &ref_div);
+               diff = abs(target_clock - (pll->reference_freq * fb_div) /
+                       (ref_div * post_div));
+
                if (diff < diff_best || (diff == diff_best &&
                    !(pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP))) {
 
@@ -936,28 +985,9 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll,
        }
        post_div = post_div_best;
 
-       /* limit reference * post divider to a maximum */
-       ref_div_max = min(210 / post_div, ref_div_max);
-
-       /* get matching reference and feedback divider */
-       ref_div = max(DIV_ROUND_CLOSEST(den, post_div), 1u);
-       fb_div = DIV_ROUND_CLOSEST(nom * ref_div * post_div, den);
-
-       /* we're almost done, but reference and feedback
-          divider might be to large now */
-
-       nom = fb_div;
-       den = ref_div;
-
-        if (fb_div > fb_div_max) {
-               ref_div = DIV_ROUND_CLOSEST(den * fb_div_max, nom);
-               fb_div = fb_div_max;
-       }
-
-       if (ref_div > ref_div_max) {
-               ref_div = ref_div_max;
-               fb_div = DIV_ROUND_CLOSEST(nom * ref_div_max, den);
-       }
+       /* get the feedback and reference divider for the optimal value */
+       avivo_get_fb_ref_div(nom, den, post_div, fb_div_max, ref_div_max,
+                            &fb_div, &ref_div);
 
        /* reduce the numbers to a simpler ratio once more */
        /* this also makes sure that the reference divider is large enough */
@@ -979,7 +1009,7 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll,
        *post_div_p = post_div;
 
        DRM_DEBUG_KMS("%d - %d, pll dividers - fb: %d.%d ref: %d, post %d\n",
-                     freq, *dot_clock_p, *fb_div_p, *frac_fb_div_p,
+                     freq, *dot_clock_p * 10, *fb_div_p, *frac_fb_div_p,
                      ref_div, post_div);
 }
 
index fb3d13f693ddb18fd32e8a4ef1a486305c615eed..0cc47f12d9957d916b41acf4d3874fa062313175 100644 (file)
@@ -107,11 +107,9 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)
                flags |= RADEON_IS_PCI;
        }
 
-       if (radeon_runtime_pm == 1)
-               flags |= RADEON_IS_PX;
-       else if ((radeon_runtime_pm == -1) &&
-                radeon_has_atpx() &&
-                ((flags & RADEON_IS_IGP) == 0))
+       if ((radeon_runtime_pm != 0) &&
+           radeon_has_atpx() &&
+           ((flags & RADEON_IS_IGP) == 0))
                flags |= RADEON_IS_PX;
 
        /* radeon_device_init should report only fatal error
index ee738a524639e41e75c7af5279c583e4b3c7ee10..6fac8efe8340e2e99f83965201bab056de2997de 100644 (file)
@@ -603,7 +603,6 @@ static const struct attribute_group *hwmon_groups[] = {
 static int radeon_hwmon_init(struct radeon_device *rdev)
 {
        int err = 0;
-       struct device *hwmon_dev;
 
        switch (rdev->pm.int_thermal_type) {
        case THERMAL_TYPE_RV6XX:
@@ -616,11 +615,11 @@ static int radeon_hwmon_init(struct radeon_device *rdev)
        case THERMAL_TYPE_KV:
                if (rdev->asic->pm.get_temperature == NULL)
                        return err;
-               hwmon_dev = hwmon_device_register_with_groups(rdev->dev,
-                                                             "radeon", rdev,
-                                                             hwmon_groups);
-               if (IS_ERR(hwmon_dev)) {
-                       err = PTR_ERR(hwmon_dev);
+               rdev->pm.int_hwmon_dev = hwmon_device_register_with_groups(rdev->dev,
+                                                                          "radeon", rdev,
+                                                                          hwmon_groups);
+               if (IS_ERR(rdev->pm.int_hwmon_dev)) {
+                       err = PTR_ERR(rdev->pm.int_hwmon_dev);
                        dev_err(rdev->dev,
                                "Unable to register hwmon device: %d\n", err);
                }
@@ -632,6 +631,12 @@ static int radeon_hwmon_init(struct radeon_device *rdev)
        return err;
 }
 
+static void radeon_hwmon_fini(struct radeon_device *rdev)
+{
+       if (rdev->pm.int_hwmon_dev)
+               hwmon_device_unregister(rdev->pm.int_hwmon_dev);
+}
+
 static void radeon_dpm_thermal_work_handler(struct work_struct *work)
 {
        struct radeon_device *rdev =
@@ -1257,6 +1262,7 @@ int radeon_pm_init(struct radeon_device *rdev)
        case CHIP_RV670:
        case CHIP_RS780:
        case CHIP_RS880:
+       case CHIP_RV770:
        case CHIP_BARTS:
        case CHIP_TURKS:
        case CHIP_CAICOS:
@@ -1273,7 +1279,6 @@ int radeon_pm_init(struct radeon_device *rdev)
                else
                        rdev->pm.pm_method = PM_METHOD_PROFILE;
                break;
-       case CHIP_RV770:
        case CHIP_RV730:
        case CHIP_RV710:
        case CHIP_RV740:
@@ -1353,6 +1358,8 @@ static void radeon_pm_fini_old(struct radeon_device *rdev)
                device_remove_file(rdev->dev, &dev_attr_power_method);
        }
 
+       radeon_hwmon_fini(rdev);
+
        if (rdev->pm.power_state)
                kfree(rdev->pm.power_state);
 }
@@ -1372,6 +1379,8 @@ static void radeon_pm_fini_dpm(struct radeon_device *rdev)
        }
        radeon_dpm_fini(rdev);
 
+       radeon_hwmon_fini(rdev);
+
        if (rdev->pm.power_state)
                kfree(rdev->pm.power_state);
 }
@@ -1397,12 +1406,14 @@ static void radeon_pm_compute_clocks_old(struct radeon_device *rdev)
 
        rdev->pm.active_crtcs = 0;
        rdev->pm.active_crtc_count = 0;
-       list_for_each_entry(crtc,
-               &ddev->mode_config.crtc_list, head) {
-               radeon_crtc = to_radeon_crtc(crtc);
-               if (radeon_crtc->enabled) {
-                       rdev->pm.active_crtcs |= (1 << radeon_crtc->crtc_id);
-                       rdev->pm.active_crtc_count++;
+       if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) {
+               list_for_each_entry(crtc,
+                                   &ddev->mode_config.crtc_list, head) {
+                       radeon_crtc = to_radeon_crtc(crtc);
+                       if (radeon_crtc->enabled) {
+                               rdev->pm.active_crtcs |= (1 << radeon_crtc->crtc_id);
+                               rdev->pm.active_crtc_count++;
+                       }
                }
        }
 
@@ -1469,12 +1480,14 @@ static void radeon_pm_compute_clocks_dpm(struct radeon_device *rdev)
        /* update active crtc counts */
        rdev->pm.dpm.new_active_crtcs = 0;
        rdev->pm.dpm.new_active_crtc_count = 0;
-       list_for_each_entry(crtc,
-               &ddev->mode_config.crtc_list, head) {
-               radeon_crtc = to_radeon_crtc(crtc);
-               if (crtc->enabled) {
-                       rdev->pm.dpm.new_active_crtcs |= (1 << radeon_crtc->crtc_id);
-                       rdev->pm.dpm.new_active_crtc_count++;
+       if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) {
+               list_for_each_entry(crtc,
+                                   &ddev->mode_config.crtc_list, head) {
+                       radeon_crtc = to_radeon_crtc(crtc);
+                       if (crtc->enabled) {
+                               rdev->pm.dpm.new_active_crtcs |= (1 << radeon_crtc->crtc_id);
+                               rdev->pm.dpm.new_active_crtc_count++;
+                       }
                }
        }
 
index 4b11ede34950e57587daa09f8c0af0ed63602ea4..4765799fef746b0e7900b4f8aaf327f8af717576 100644 (file)
@@ -109,7 +109,6 @@ static int da9055_onkey_probe(struct platform_device *pdev)
 
        INIT_DELAYED_WORK(&onkey->work, da9055_onkey_work);
 
-       irq = regmap_irq_get_virq(da9055->irq_data, irq);
        err = request_threaded_irq(irq, NULL, da9055_onkey_irq,
                                   IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
                                   "ONKEY", onkey);
index 08ead2aaede5d8ba8a324ff8157beb74d7984b2d..20c80f543d5e56fbe59f15403f2d64d9cb791cff 100644 (file)
@@ -169,6 +169,7 @@ static int soc_button_pnp_probe(struct pnp_dev *pdev,
                                soc_button_remove(pdev);
                                return error;
                        }
+                       continue;
                }
 
                priv->children[i] = pd;
index ef1cf52f8bb99212a96e9fe415ebf81bbb1e21bf..088d3541c7d3d4485380dd859e9777c6e39c94d2 100644 (file)
@@ -1353,6 +1353,7 @@ static int elantech_set_properties(struct elantech_data *etd)
                case 6:
                case 7:
                case 8:
+               case 9:
                        etd->hw_version = 4;
                        break;
                default:
index d8d49d10f9bb60d477124bba603fb9f61be1efdb..ef9f4913450d12a06262dd906b8ebe93b0401dbe 100644 (file)
@@ -117,6 +117,44 @@ void synaptics_reset(struct psmouse *psmouse)
 }
 
 #ifdef CONFIG_MOUSE_PS2_SYNAPTICS
+/* This list has been kindly provided by Synaptics. */
+static const char * const topbuttonpad_pnp_ids[] = {
+       "LEN0017",
+       "LEN0018",
+       "LEN0019",
+       "LEN0023",
+       "LEN002A",
+       "LEN002B",
+       "LEN002C",
+       "LEN002D",
+       "LEN002E",
+       "LEN0033", /* Helix */
+       "LEN0034", /* T431s, T540, X1 Carbon 2nd */
+       "LEN0035", /* X240 */
+       "LEN0036", /* T440 */
+       "LEN0037",
+       "LEN0038",
+       "LEN0041",
+       "LEN0042", /* Yoga */
+       "LEN0045",
+       "LEN0046",
+       "LEN0047",
+       "LEN0048",
+       "LEN0049",
+       "LEN2000",
+       "LEN2001",
+       "LEN2002",
+       "LEN2003",
+       "LEN2004", /* L440 */
+       "LEN2005",
+       "LEN2006",
+       "LEN2007",
+       "LEN2008",
+       "LEN2009",
+       "LEN200A",
+       "LEN200B",
+       NULL
+};
 
 /*****************************************************************************
  *     Synaptics communications functions
@@ -1255,8 +1293,10 @@ static void set_abs_position_params(struct input_dev *dev,
        input_abs_set_res(dev, y_code, priv->y_res);
 }
 
-static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
+static void set_input_params(struct psmouse *psmouse,
+                            struct synaptics_data *priv)
 {
+       struct input_dev *dev = psmouse->dev;
        int i;
 
        /* Things that apply to both modes */
@@ -1325,6 +1365,17 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
 
        if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {
                __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit);
+               /* See if this buttonpad has a top button area */
+               if (!strncmp(psmouse->ps2dev.serio->firmware_id, "PNP:", 4)) {
+                       for (i = 0; topbuttonpad_pnp_ids[i]; i++) {
+                               if (strstr(psmouse->ps2dev.serio->firmware_id,
+                                          topbuttonpad_pnp_ids[i])) {
+                                       __set_bit(INPUT_PROP_TOPBUTTONPAD,
+                                                 dev->propbit);
+                                       break;
+                               }
+                       }
+               }
                /* Clickpads report only left button */
                __clear_bit(BTN_RIGHT, dev->keybit);
                __clear_bit(BTN_MIDDLE, dev->keybit);
@@ -1514,6 +1565,14 @@ static const struct dmi_system_id min_max_dmi_table[] __initconst = {
                },
                .driver_data = (int []){1232, 5710, 1156, 4696},
        },
+       {
+               /* Lenovo ThinkPad T431s */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T431"),
+               },
+               .driver_data = (int []){1024, 5112, 2024, 4832},
+       },
        {
                /* Lenovo ThinkPad T440s */
                .matches = {
@@ -1522,6 +1581,14 @@ static const struct dmi_system_id min_max_dmi_table[] __initconst = {
                },
                .driver_data = (int []){1024, 5112, 2024, 4832},
        },
+       {
+               /* Lenovo ThinkPad L440 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L440"),
+               },
+               .driver_data = (int []){1024, 5112, 2024, 4832},
+       },
        {
                /* Lenovo ThinkPad T540p */
                .matches = {
@@ -1530,6 +1597,32 @@ static const struct dmi_system_id min_max_dmi_table[] __initconst = {
                },
                .driver_data = (int []){1024, 5056, 2058, 4832},
        },
+       {
+               /* Lenovo ThinkPad L540 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L540"),
+               },
+               .driver_data = (int []){1024, 5112, 2024, 4832},
+       },
+       {
+               /* Lenovo Yoga S1 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_VERSION,
+                                       "ThinkPad S1 Yoga"),
+               },
+               .driver_data = (int []){1232, 5710, 1156, 4696},
+       },
+       {
+               /* Lenovo ThinkPad X1 Carbon Haswell (3rd generation) */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION,
+                                       "ThinkPad X1 Carbon 2nd"),
+               },
+               .driver_data = (int []){1024, 5112, 2024, 4832},
+       },
 #endif
        { }
 };
@@ -1593,7 +1686,7 @@ static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode)
                     priv->capabilities, priv->ext_cap, priv->ext_cap_0c,
                     priv->board_id, priv->firmware_id);
 
-       set_input_params(psmouse->dev, priv);
+       set_input_params(psmouse, priv);
 
        /*
         * Encode touchpad model so that it can be used to set
index 0ec9abbe31fec3af5248808fce517fc863ff75b2..381b20d4c5618d8fc7f5c3e616479d4663d9ae03 100644 (file)
@@ -702,6 +702,17 @@ static int i8042_pnp_aux_irq;
 static char i8042_pnp_kbd_name[32];
 static char i8042_pnp_aux_name[32];
 
+static void i8042_pnp_id_to_string(struct pnp_id *id, char *dst, int dst_size)
+{
+       strlcpy(dst, "PNP:", dst_size);
+
+       while (id) {
+               strlcat(dst, " ", dst_size);
+               strlcat(dst, id->id, dst_size);
+               id = id->next;
+       }
+}
+
 static int i8042_pnp_kbd_probe(struct pnp_dev *dev, const struct pnp_device_id *did)
 {
        if (pnp_port_valid(dev, 0) && pnp_port_len(dev, 0) == 1)
@@ -718,6 +729,8 @@ static int i8042_pnp_kbd_probe(struct pnp_dev *dev, const struct pnp_device_id *
                strlcat(i8042_pnp_kbd_name, ":", sizeof(i8042_pnp_kbd_name));
                strlcat(i8042_pnp_kbd_name, pnp_dev_name(dev), sizeof(i8042_pnp_kbd_name));
        }
+       i8042_pnp_id_to_string(dev->id, i8042_kbd_firmware_id,
+                              sizeof(i8042_kbd_firmware_id));
 
        /* Keyboard ports are always supposed to be wakeup-enabled */
        device_set_wakeup_enable(&dev->dev, true);
@@ -742,6 +755,8 @@ static int i8042_pnp_aux_probe(struct pnp_dev *dev, const struct pnp_device_id *
                strlcat(i8042_pnp_aux_name, ":", sizeof(i8042_pnp_aux_name));
                strlcat(i8042_pnp_aux_name, pnp_dev_name(dev), sizeof(i8042_pnp_aux_name));
        }
+       i8042_pnp_id_to_string(dev->id, i8042_aux_firmware_id,
+                              sizeof(i8042_aux_firmware_id));
 
        i8042_pnp_aux_devices++;
        return 0;
index 020053fa5aaa38fce82b5fc2d6ced8546661c9df..3807c3e971cca79e6ff42b745409ac418487bb0c 100644 (file)
@@ -87,6 +87,8 @@ MODULE_PARM_DESC(debug, "Turn i8042 debugging mode on and off");
 #endif
 
 static bool i8042_bypass_aux_irq_test;
+static char i8042_kbd_firmware_id[128];
+static char i8042_aux_firmware_id[128];
 
 #include "i8042.h"
 
@@ -1218,6 +1220,8 @@ static int __init i8042_create_kbd_port(void)
        serio->dev.parent       = &i8042_platform_device->dev;
        strlcpy(serio->name, "i8042 KBD port", sizeof(serio->name));
        strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys));
+       strlcpy(serio->firmware_id, i8042_kbd_firmware_id,
+               sizeof(serio->firmware_id));
 
        port->serio = serio;
        port->irq = I8042_KBD_IRQ;
@@ -1244,6 +1248,8 @@ static int __init i8042_create_aux_port(int idx)
        if (idx < 0) {
                strlcpy(serio->name, "i8042 AUX port", sizeof(serio->name));
                strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys));
+               strlcpy(serio->firmware_id, i8042_aux_firmware_id,
+                       sizeof(serio->firmware_id));
                serio->close = i8042_port_close;
        } else {
                snprintf(serio->name, sizeof(serio->name), "i8042 AUX%d port", idx);
index 8f4c4ab04bc2d8c61d5fda2a65696806e61ad6f2..b29134de983b85ff2df85ba171d8e4a7f8cdac5b 100644 (file)
@@ -451,6 +451,13 @@ static ssize_t serio_set_bind_mode(struct device *dev, struct device_attribute *
        return retval;
 }
 
+static ssize_t firmware_id_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct serio *serio = to_serio_port(dev);
+
+       return sprintf(buf, "%s\n", serio->firmware_id);
+}
+
 static DEVICE_ATTR_RO(type);
 static DEVICE_ATTR_RO(proto);
 static DEVICE_ATTR_RO(id);
@@ -473,12 +480,14 @@ static DEVICE_ATTR_RO(modalias);
 static DEVICE_ATTR_WO(drvctl);
 static DEVICE_ATTR(description, S_IRUGO, serio_show_description, NULL);
 static DEVICE_ATTR(bind_mode, S_IWUSR | S_IRUGO, serio_show_bind_mode, serio_set_bind_mode);
+static DEVICE_ATTR_RO(firmware_id);
 
 static struct attribute *serio_device_attrs[] = {
        &dev_attr_modalias.attr,
        &dev_attr_description.attr,
        &dev_attr_drvctl.attr,
        &dev_attr_bind_mode.attr,
+       &dev_attr_firmware_id.attr,
        NULL
 };
 
@@ -921,9 +930,14 @@ static int serio_uevent(struct device *dev, struct kobj_uevent_env *env)
        SERIO_ADD_UEVENT_VAR("SERIO_PROTO=%02x", serio->id.proto);
        SERIO_ADD_UEVENT_VAR("SERIO_ID=%02x", serio->id.id);
        SERIO_ADD_UEVENT_VAR("SERIO_EXTRA=%02x", serio->id.extra);
+
        SERIO_ADD_UEVENT_VAR("MODALIAS=serio:ty%02Xpr%02Xid%02Xex%02X",
                                serio->id.type, serio->id.proto, serio->id.id, serio->id.extra);
 
+       if (serio->firmware_id[0])
+               SERIO_ADD_UEVENT_VAR("SERIO_FIRMWARE_ID=%s",
+                                    serio->firmware_id);
+
        return 0;
 }
 #undef SERIO_ADD_UEVENT_VAR
index b16ebef5b9111c7a999845300e1c33070f2a31b4..611fc3905d00d9fafa7cf1088b28f6c22fccca28 100644 (file)
 #define HID_USAGE_PAGE_DIGITIZER       0x0d
 #define HID_USAGE_PAGE_DESKTOP         0x01
 #define HID_USAGE                      0x09
-#define HID_USAGE_X                    0x30
-#define HID_USAGE_Y                    0x31
-#define HID_USAGE_X_TILT               0x3d
-#define HID_USAGE_Y_TILT               0x3e
-#define HID_USAGE_FINGER               0x22
-#define HID_USAGE_STYLUS               0x20
-#define HID_USAGE_CONTACTMAX           0x55
+#define HID_USAGE_X                    ((HID_USAGE_PAGE_DESKTOP << 16) | 0x30)
+#define HID_USAGE_Y                    ((HID_USAGE_PAGE_DESKTOP << 16) | 0x31)
+#define HID_USAGE_PRESSURE             ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x30)
+#define HID_USAGE_X_TILT               ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x3d)
+#define HID_USAGE_Y_TILT               ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x3e)
+#define HID_USAGE_FINGER               ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x22)
+#define HID_USAGE_STYLUS               ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x20)
+#define HID_USAGE_CONTACTMAX           ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x55)
 #define HID_COLLECTION                 0xa1
 #define HID_COLLECTION_LOGICAL         0x02
 #define HID_COLLECTION_END             0xc0
 
-enum {
-       WCM_UNDEFINED = 0,
-       WCM_DESKTOP,
-       WCM_DIGITIZER,
-};
-
 struct hid_descriptor {
        struct usb_descriptor_header header;
        __le16   bcdHID;
@@ -305,7 +300,7 @@ static int wacom_parse_hid(struct usb_interface *intf,
        char limit = 0;
        /* result has to be defined as int for some devices */
        int result = 0, touch_max = 0;
-       int i = 0, usage = WCM_UNDEFINED, finger = 0, pen = 0;
+       int i = 0, page = 0, finger = 0, pen = 0;
        unsigned char *report;
 
        report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL);
@@ -332,134 +327,121 @@ static int wacom_parse_hid(struct usb_interface *intf,
 
                switch (report[i]) {
                case HID_USAGE_PAGE:
-                       switch (report[i + 1]) {
-                       case HID_USAGE_PAGE_DIGITIZER:
-                               usage = WCM_DIGITIZER;
-                               i++;
-                               break;
-
-                       case HID_USAGE_PAGE_DESKTOP:
-                               usage = WCM_DESKTOP;
-                               i++;
-                               break;
-                       }
+                       page = report[i + 1];
+                       i++;
                        break;
 
                case HID_USAGE:
-                       switch (report[i + 1]) {
+                       switch (page << 16 | report[i + 1]) {
                        case HID_USAGE_X:
-                               if (usage == WCM_DESKTOP) {
-                                       if (finger) {
-                                               features->device_type = BTN_TOOL_FINGER;
-                                               /* touch device at least supports one touch point */
-                                               touch_max = 1;
-                                               switch (features->type) {
-                                               case TABLETPC2FG:
-                                                       features->pktlen = WACOM_PKGLEN_TPC2FG;
-                                                       break;
-
-                                               case MTSCREEN:
-                                               case WACOM_24HDT:
-                                                       features->pktlen = WACOM_PKGLEN_MTOUCH;
-                                                       break;
-
-                                               case MTTPC:
-                                                       features->pktlen = WACOM_PKGLEN_MTTPC;
-                                                       break;
-
-                                               case BAMBOO_PT:
-                                                       features->pktlen = WACOM_PKGLEN_BBTOUCH;
-                                                       break;
-
-                                               default:
-                                                       features->pktlen = WACOM_PKGLEN_GRAPHIRE;
-                                                       break;
-                                               }
-
-                                               switch (features->type) {
-                                               case BAMBOO_PT:
-                                                       features->x_phy =
-                                                               get_unaligned_le16(&report[i + 5]);
-                                                       features->x_max =
-                                                               get_unaligned_le16(&report[i + 8]);
-                                                       i += 15;
-                                                       break;
-
-                                               case WACOM_24HDT:
-                                                       features->x_max =
-                                                               get_unaligned_le16(&report[i + 3]);
-                                                       features->x_phy =
-                                                               get_unaligned_le16(&report[i + 8]);
-                                                       features->unit = report[i - 1];
-                                                       features->unitExpo = report[i - 3];
-                                                       i += 12;
-                                                       break;
-
-                                               default:
-                                                       features->x_max =
-                                                               get_unaligned_le16(&report[i + 3]);
-                                                       features->x_phy =
-                                                               get_unaligned_le16(&report[i + 6]);
-                                                       features->unit = report[i + 9];
-                                                       features->unitExpo = report[i + 11];
-                                                       i += 12;
-                                                       break;
-                                               }
-                                       } else if (pen) {
-                                               /* penabled only accepts exact bytes of data */
-                                               if (features->type >= TABLETPC)
-                                                       features->pktlen = WACOM_PKGLEN_GRAPHIRE;
-                                               features->device_type = BTN_TOOL_PEN;
+                               if (finger) {
+                                       features->device_type = BTN_TOOL_FINGER;
+                                       /* touch device at least supports one touch point */
+                                       touch_max = 1;
+                                       switch (features->type) {
+                                       case TABLETPC2FG:
+                                               features->pktlen = WACOM_PKGLEN_TPC2FG;
+                                               break;
+
+                                       case MTSCREEN:
+                                       case WACOM_24HDT:
+                                               features->pktlen = WACOM_PKGLEN_MTOUCH;
+                                               break;
+
+                                       case MTTPC:
+                                               features->pktlen = WACOM_PKGLEN_MTTPC;
+                                               break;
+
+                                       case BAMBOO_PT:
+                                               features->pktlen = WACOM_PKGLEN_BBTOUCH;
+                                               break;
+
+                                       default:
+                                               features->pktlen = WACOM_PKGLEN_GRAPHIRE;
+                                               break;
+                                       }
+
+                                       switch (features->type) {
+                                       case BAMBOO_PT:
+                                               features->x_phy =
+                                                       get_unaligned_le16(&report[i + 5]);
+                                               features->x_max =
+                                                       get_unaligned_le16(&report[i + 8]);
+                                               i += 15;
+                                               break;
+
+                                       case WACOM_24HDT:
                                                features->x_max =
                                                        get_unaligned_le16(&report[i + 3]);
-                                               i += 4;
+                                               features->x_phy =
+                                                       get_unaligned_le16(&report[i + 8]);
+                                               features->unit = report[i - 1];
+                                               features->unitExpo = report[i - 3];
+                                               i += 12;
+                                               break;
+
+                                       default:
+                                               features->x_max =
+                                                       get_unaligned_le16(&report[i + 3]);
+                                               features->x_phy =
+                                                       get_unaligned_le16(&report[i + 6]);
+                                               features->unit = report[i + 9];
+                                               features->unitExpo = report[i + 11];
+                                               i += 12;
+                                               break;
                                        }
+                               } else if (pen) {
+                                       /* penabled only accepts exact bytes of data */
+                                       if (features->type >= TABLETPC)
+                                               features->pktlen = WACOM_PKGLEN_GRAPHIRE;
+                                       features->device_type = BTN_TOOL_PEN;
+                                       features->x_max =
+                                               get_unaligned_le16(&report[i + 3]);
+                                       i += 4;
                                }
                                break;
 
                        case HID_USAGE_Y:
-                               if (usage == WCM_DESKTOP) {
-                                       if (finger) {
-                                               switch (features->type) {
-                                               case TABLETPC2FG:
-                                               case MTSCREEN:
-                                               case MTTPC:
-                                                       features->y_max =
-                                                               get_unaligned_le16(&report[i + 3]);
-                                                       features->y_phy =
-                                                               get_unaligned_le16(&report[i + 6]);
-                                                       i += 7;
-                                                       break;
-
-                                               case WACOM_24HDT:
-                                                       features->y_max =
-                                                               get_unaligned_le16(&report[i + 3]);
-                                                       features->y_phy =
-                                                               get_unaligned_le16(&report[i - 2]);
-                                                       i += 7;
-                                                       break;
-
-                                               case BAMBOO_PT:
-                                                       features->y_phy =
-                                                               get_unaligned_le16(&report[i + 3]);
-                                                       features->y_max =
-                                                               get_unaligned_le16(&report[i + 6]);
-                                                       i += 12;
-                                                       break;
-
-                                               default:
-                                                       features->y_max =
-                                                               features->x_max;
-                                                       features->y_phy =
-                                                               get_unaligned_le16(&report[i + 3]);
-                                                       i += 4;
-                                                       break;
-                                               }
-                                       } else if (pen) {
+                               if (finger) {
+                                       switch (features->type) {
+                                       case TABLETPC2FG:
+                                       case MTSCREEN:
+                                       case MTTPC:
+                                               features->y_max =
+                                                       get_unaligned_le16(&report[i + 3]);
+                                               features->y_phy =
+                                                       get_unaligned_le16(&report[i + 6]);
+                                               i += 7;
+                                               break;
+
+                                       case WACOM_24HDT:
+                                               features->y_max =
+                                                       get_unaligned_le16(&report[i + 3]);
+                                               features->y_phy =
+                                                       get_unaligned_le16(&report[i - 2]);
+                                               i += 7;
+                                               break;
+
+                                       case BAMBOO_PT:
+                                               features->y_phy =
+                                                       get_unaligned_le16(&report[i + 3]);
+                                               features->y_max =
+                                                       get_unaligned_le16(&report[i + 6]);
+                                               i += 12;
+                                               break;
+
+                                       default:
                                                features->y_max =
+                                                       features->x_max;
+                                               features->y_phy =
                                                        get_unaligned_le16(&report[i + 3]);
                                                i += 4;
+                                               break;
                                        }
+                               } else if (pen) {
+                                       features->y_max =
+                                               get_unaligned_le16(&report[i + 3]);
+                                       i += 4;
                                }
                                break;
 
@@ -484,12 +466,20 @@ static int wacom_parse_hid(struct usb_interface *intf,
                                        wacom_retrieve_report_data(intf, features);
                                i++;
                                break;
+
+                       case HID_USAGE_PRESSURE:
+                               if (pen) {
+                                       features->pressure_max =
+                                               get_unaligned_le16(&report[i + 3]);
+                                       i += 4;
+                               }
+                               break;
                        }
                        break;
 
                case HID_COLLECTION_END:
                        /* reset UsagePage and Finger */
-                       finger = usage = 0;
+                       finger = page = 0;
                        break;
 
                case HID_COLLECTION:
index 05f371df6c400a882621c13509f6a13a40eed077..4822c57a3756f4e3175fac3e1def90611028eb6d 100644 (file)
@@ -178,10 +178,9 @@ static int wacom_ptu_irq(struct wacom_wac *wacom)
 
 static int wacom_dtu_irq(struct wacom_wac *wacom)
 {
-       struct wacom_features *features = &wacom->features;
-       char *data = wacom->data;
+       unsigned char *data = wacom->data;
        struct input_dev *input = wacom->input;
-       int prox = data[1] & 0x20, pressure;
+       int prox = data[1] & 0x20;
 
        dev_dbg(input->dev.parent,
                "%s: received report #%d", __func__, data[0]);
@@ -198,10 +197,7 @@ static int wacom_dtu_irq(struct wacom_wac *wacom)
        input_report_key(input, BTN_STYLUS2, data[1] & 0x10);
        input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
        input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
-       pressure = ((data[7] & 0x01) << 8) | data[6];
-       if (pressure < 0)
-               pressure = features->pressure_max + pressure + 1;
-       input_report_abs(input, ABS_PRESSURE, pressure);
+       input_report_abs(input, ABS_PRESSURE, ((data[7] & 0x01) << 8) | data[6]);
        input_report_key(input, BTN_TOUCH, data[1] & 0x05);
        if (!prox) /* out-prox */
                wacom->id[0] = 0;
@@ -906,7 +902,7 @@ static int int_dist(int x1, int y1, int x2, int y2)
 static int wacom_24hdt_irq(struct wacom_wac *wacom)
 {
        struct input_dev *input = wacom->input;
-       char *data = wacom->data;
+       unsigned char *data = wacom->data;
        int i;
        int current_num_contacts = data[61];
        int contacts_to_send = 0;
@@ -959,7 +955,7 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom)
 static int wacom_mt_touch(struct wacom_wac *wacom)
 {
        struct input_dev *input = wacom->input;
-       char *data = wacom->data;
+       unsigned char *data = wacom->data;
        int i;
        int current_num_contacts = data[2];
        int contacts_to_send = 0;
@@ -1038,7 +1034,7 @@ static int wacom_tpc_mt_touch(struct wacom_wac *wacom)
 
 static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len)
 {
-       char *data = wacom->data;
+       unsigned char *data = wacom->data;
        struct input_dev *input = wacom->input;
        bool prox;
        int x = 0, y = 0;
@@ -1074,10 +1070,8 @@ static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len)
 
 static int wacom_tpc_pen(struct wacom_wac *wacom)
 {
-       struct wacom_features *features = &wacom->features;
-       char *data = wacom->data;
+       unsigned char *data = wacom->data;
        struct input_dev *input = wacom->input;
-       int pressure;
        bool prox = data[1] & 0x20;
 
        if (!wacom->shared->stylus_in_proximity) /* first in prox */
@@ -1093,10 +1087,7 @@ static int wacom_tpc_pen(struct wacom_wac *wacom)
                input_report_key(input, BTN_STYLUS2, data[1] & 0x10);
                input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
                input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
-               pressure = ((data[7] & 0x01) << 8) | data[6];
-               if (pressure < 0)
-                       pressure = features->pressure_max + pressure + 1;
-               input_report_abs(input, ABS_PRESSURE, pressure);
+               input_report_abs(input, ABS_PRESSURE, ((data[7] & 0x03) << 8) | data[6]);
                input_report_key(input, BTN_TOUCH, data[1] & 0x05);
                input_report_key(input, wacom->tool[0], prox);
                return 1;
@@ -1107,7 +1098,7 @@ static int wacom_tpc_pen(struct wacom_wac *wacom)
 
 static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
 {
-       char *data = wacom->data;
+       unsigned char *data = wacom->data;
 
        dev_dbg(wacom->input->dev.parent,
                "%s: received report #%d\n", __func__, data[0]);
@@ -1838,7 +1829,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
        case DTU:
                if (features->type == DTUS) {
                        input_set_capability(input_dev, EV_MSC, MSC_SERIAL);
-                       for (i = 0; i < 3; i++)
+                       for (i = 0; i < 4; i++)
                                __set_bit(BTN_0 + i, input_dev->keybit);
                }
                __set_bit(BTN_TOOL_PEN, input_dev->keybit);
index 45a06e495ed25702831441da6be558fa88491671..7f8aa981500d88c10d8b23cc19f489befe7bedd6 100644 (file)
@@ -425,7 +425,7 @@ static int ads7845_read12_ser(struct device *dev, unsigned command)
 name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
        struct ads7846 *ts = dev_get_drvdata(dev); \
-       ssize_t v = ads7846_read12_ser(dev, \
+       ssize_t v = ads7846_read12_ser(&ts->spi->dev, \
                        READ_12BIT_SER(var)); \
        if (v < 0) \
                return v; \
index ded3b35742091dac92192c45f1c0e7f24565f924..6d38be3d970ca72b48d0a44c950da341071edb53 100644 (file)
@@ -38,66 +38,24 @@ struct pbias_reg_info {
 struct pbias_regulator_data {
        struct regulator_desc desc;
        void __iomem *pbias_addr;
-       unsigned int pbias_reg;
        struct regulator_dev *dev;
        struct regmap *syscon;
        const struct pbias_reg_info *info;
        int voltage;
 };
 
-static int pbias_regulator_set_voltage(struct regulator_dev *dev,
-                       int min_uV, int max_uV, unsigned *selector)
-{
-       struct pbias_regulator_data *data = rdev_get_drvdata(dev);
-       const struct pbias_reg_info *info = data->info;
-       int ret, vmode;
-
-       if (min_uV <= 1800000)
-               vmode = 0;
-       else if (min_uV > 1800000)
-               vmode = info->vmode;
-
-       ret = regmap_update_bits(data->syscon, data->pbias_reg,
-                                               info->vmode, vmode);
-
-       return ret;
-}
-
-static int pbias_regulator_get_voltage(struct regulator_dev *rdev)
-{
-       struct pbias_regulator_data *data = rdev_get_drvdata(rdev);
-       const struct pbias_reg_info *info = data->info;
-       int value, voltage;
-
-       regmap_read(data->syscon, data->pbias_reg, &value);
-       value &= info->vmode;
-
-       voltage = value ? 3000000 : 1800000;
-
-       return voltage;
-}
+static const unsigned int pbias_volt_table[] = {
+       1800000,
+       3000000
+};
 
 static int pbias_regulator_enable(struct regulator_dev *rdev)
 {
        struct pbias_regulator_data *data = rdev_get_drvdata(rdev);
        const struct pbias_reg_info *info = data->info;
-       int ret;
-
-       ret = regmap_update_bits(data->syscon, data->pbias_reg,
-                                       info->enable_mask, info->enable);
-
-       return ret;
-}
-
-static int pbias_regulator_disable(struct regulator_dev *rdev)
-{
-       struct pbias_regulator_data *data = rdev_get_drvdata(rdev);
-       const struct pbias_reg_info *info = data->info;
-       int ret;
 
-       ret = regmap_update_bits(data->syscon, data->pbias_reg,
-                                               info->enable_mask, 0);
-       return ret;
+       return regmap_update_bits(data->syscon, rdev->desc->enable_reg,
+                                 info->enable_mask, info->enable);
 }
 
 static int pbias_regulator_is_enable(struct regulator_dev *rdev)
@@ -106,17 +64,18 @@ static int pbias_regulator_is_enable(struct regulator_dev *rdev)
        const struct pbias_reg_info *info = data->info;
        int value;
 
-       regmap_read(data->syscon, data->pbias_reg, &value);
+       regmap_read(data->syscon, rdev->desc->enable_reg, &value);
 
-       return (value & info->enable_mask) == info->enable_mask;
+       return (value & info->enable_mask) == info->enable;
 }
 
 static struct regulator_ops pbias_regulator_voltage_ops = {
-       .set_voltage    = pbias_regulator_set_voltage,
-       .get_voltage    = pbias_regulator_get_voltage,
-       .enable         = pbias_regulator_enable,
-       .disable        = pbias_regulator_disable,
-       .is_enabled     = pbias_regulator_is_enable,
+       .list_voltage = regulator_list_voltage_table,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .enable = pbias_regulator_enable,
+       .disable = regulator_disable_regmap,
+       .is_enabled = pbias_regulator_is_enable,
 };
 
 static const struct pbias_reg_info pbias_mmc_omap2430 = {
@@ -192,6 +151,7 @@ static int pbias_regulator_probe(struct platform_device *pdev)
        if (IS_ERR(syscon))
                return PTR_ERR(syscon);
 
+       cfg.regmap = syscon;
        cfg.dev = &pdev->dev;
 
        for (idx = 0; idx < PBIAS_NUM_REGS && data_idx < count; idx++) {
@@ -207,15 +167,19 @@ static int pbias_regulator_probe(struct platform_device *pdev)
                if (!res)
                        return -EINVAL;
 
-               drvdata[data_idx].pbias_reg = res->start;
                drvdata[data_idx].syscon = syscon;
                drvdata[data_idx].info = info;
                drvdata[data_idx].desc.name = info->name;
                drvdata[data_idx].desc.owner = THIS_MODULE;
                drvdata[data_idx].desc.type = REGULATOR_VOLTAGE;
                drvdata[data_idx].desc.ops = &pbias_regulator_voltage_ops;
+               drvdata[data_idx].desc.volt_table = pbias_volt_table;
                drvdata[data_idx].desc.n_voltages = 2;
                drvdata[data_idx].desc.enable_time = info->enable_time;
+               drvdata[data_idx].desc.vsel_reg = res->start;
+               drvdata[data_idx].desc.vsel_mask = info->vmode;
+               drvdata[data_idx].desc.enable_reg = res->start;
+               drvdata[data_idx].desc.enable_mask = info->enable_mask;
 
                cfg.init_data = pbias_matches[idx].init_data;
                cfg.driver_data = &drvdata[data_idx];
index 8005f986948173e55d5bc5a5387da80c8a5b9185..079e6b1b0cdb6fbc2e05532f3d8548653f4d4694 100644 (file)
@@ -1115,8 +1115,11 @@ static int atmel_spi_one_transfer(struct spi_master *master,
                        atmel_spi_next_xfer_pio(master, xfer);
                }
 
+               /* interrupts are disabled, so free the lock for schedule */
+               atmel_spi_unlock(as);
                ret = wait_for_completion_timeout(&as->xfer_completion,
                                                        SPI_DMA_TIMEOUT);
+               atmel_spi_lock(as);
                if (WARN_ON(ret == 0)) {
                        dev_err(&spi->dev,
                                "spi trasfer timeout, err %d\n", ret);
index 55e57c3eb9bd051bc7fcca7d5090a2d999bf688b..ebf720b88a2a5ca5c47c389379c50ab18e4cbd2b 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/device.h>
+#include <linux/gpio.h>
 #include <linux/slab.h>
 #include <linux/io.h>
 #include <linux/ioport.h>
index 9009456bdf4d29c6febf56b162113fa5e4bf78ef..c8e795ef2e132fcb10dd4ac196decbd887861f5d 100644 (file)
@@ -244,9 +244,9 @@ static int hspi_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
 
-       clk = clk_get(NULL, "shyway_clk");
+       clk = clk_get(&pdev->dev, NULL);
        if (IS_ERR(clk)) {
-               dev_err(&pdev->dev, "shyway_clk is required\n");
+               dev_err(&pdev->dev, "couldn't get clock\n");
                ret = -EINVAL;
                goto error0;
        }
index 1a77ad52812fd79d3a2524264e7a2a8678ca1464..67d8909dcf3946a4d516d607fd83cef417aaabc1 100644 (file)
@@ -287,8 +287,8 @@ static irqreturn_t spi_sirfsoc_irq(int irq, void *dev_id)
                                sspi->left_rx_word)
                        sspi->rx_word(sspi);
 
-       if (spi_stat & (SIRFSOC_SPI_FIFO_EMPTY
-                       SIRFSOC_SPI_TXFIFO_THD_REACH))
+       if (spi_stat & (SIRFSOC_SPI_TXFIFO_EMPTY |
+                       SIRFSOC_SPI_TXFIFO_THD_REACH))
                while (!((readl(sspi->base + SIRFSOC_SPI_TXFIFO_STATUS)
                                & SIRFSOC_SPI_FIFO_FULL)) &&
                                sspi->left_tx_word)
@@ -470,7 +470,16 @@ static void spi_sirfsoc_chipselect(struct spi_device *spi, int value)
                writel(regval, sspi->base + SIRFSOC_SPI_CTRL);
        } else {
                int gpio = sspi->chipselect[spi->chip_select];
-               gpio_direction_output(gpio, spi->mode & SPI_CS_HIGH ? 0 : 1);
+               switch (value) {
+               case BITBANG_CS_ACTIVE:
+                       gpio_direction_output(gpio,
+                                       spi->mode & SPI_CS_HIGH ? 1 : 0);
+                       break;
+               case BITBANG_CS_INACTIVE:
+                       gpio_direction_output(gpio,
+                                       spi->mode & SPI_CS_HIGH ? 0 : 1);
+                       break;
+               }
        }
 }
 
@@ -559,6 +568,11 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
                regval &= ~SIRFSOC_SPI_CMD_MODE;
                sspi->tx_by_cmd = false;
        }
+       /*
+        * set spi controller in RISC chipselect mode, we are controlling CS by
+        * software BITBANG_CS_ACTIVE and BITBANG_CS_INACTIVE.
+        */
+       regval |= SIRFSOC_SPI_CS_IO_MODE;
        writel(regval, sspi->base + SIRFSOC_SPI_CTRL);
 
        if (IS_DMA_VALID(t)) {
index 39da1c2efa5030216d18bc6bb3020a78afb4c5f6..88a6df4cbe6d8a52bd083a756ac452b798c33708 100644 (file)
@@ -1221,9 +1221,6 @@ static long ceph_fallocate(struct file *file, int mode,
        if (!S_ISREG(inode->i_mode))
                return -EOPNOTSUPP;
 
-       if (IS_SWAPFILE(inode))
-               return -ETXTBSY;
-
        mutex_lock(&inode->i_mutex);
 
        if (ceph_snap(inode) != CEPH_NOSNAP) {
index ca926ad0430cf715af12ebc3f0fa86d8c273d492..66d3d3c6b4b248878af6d751178d055310224c3d 100644 (file)
@@ -457,9 +457,9 @@ COMPAT_SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd,
        case F_GETLK64:
        case F_SETLK64:
        case F_SETLKW64:
-       case F_GETLKP:
-       case F_SETLKP:
-       case F_SETLKPW:
+       case F_OFD_GETLK:
+       case F_OFD_SETLK:
+       case F_OFD_SETLKW:
                ret = get_compat_flock64(&f, compat_ptr(arg));
                if (ret != 0)
                        break;
@@ -468,7 +468,7 @@ COMPAT_SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd,
                conv_cmd = convert_fcntl_cmd(cmd);
                ret = sys_fcntl(fd, conv_cmd, (unsigned long)&f);
                set_fs(old_fs);
-               if ((conv_cmd == F_GETLK || conv_cmd == F_GETLKP) && ret == 0) {
+               if ((conv_cmd == F_GETLK || conv_cmd == F_OFD_GETLK) && ret == 0) {
                        /* need to return lock information - see above for commentary */
                        if (f.l_start > COMPAT_LOFF_T_MAX)
                                ret = -EOVERFLOW;
@@ -493,9 +493,9 @@ COMPAT_SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd,
        case F_GETLK64:
        case F_SETLK64:
        case F_SETLKW64:
-       case F_GETLKP:
-       case F_SETLKP:
-       case F_SETLKPW:
+       case F_OFD_GETLK:
+       case F_OFD_SETLK:
+       case F_OFD_SETLKW:
                return -EINVAL;
        }
        return compat_sys_fcntl64(fd, cmd, arg);
index 6ea7b1436bbc201e872d6ee18f7321b2e099f156..5c56785007e0e36fec78e6535aa210e09247a983 100644 (file)
@@ -667,7 +667,7 @@ ext4_fsblk_t ext4_count_free_clusters(struct super_block *sb)
                        continue;
 
                x = ext4_count_free(bitmap_bh->b_data,
-                                   EXT4_BLOCKS_PER_GROUP(sb) / 8);
+                                   EXT4_CLUSTERS_PER_GROUP(sb) / 8);
                printk(KERN_DEBUG "group %u: stored = %d, counted = %u\n",
                        i, ext4_free_group_clusters(sb, gdp), x);
                bitmap_count += x;
index f1c65dc7cc0ad268a9fccc7b6f1aeaf078d84a0a..66946aa621270716c580a2617bceecbcadb6bda7 100644 (file)
@@ -2466,23 +2466,6 @@ static inline void ext4_update_i_disksize(struct inode *inode, loff_t newsize)
        up_write(&EXT4_I(inode)->i_data_sem);
 }
 
-/*
- * Update i_disksize after writeback has been started. Races with truncate
- * are avoided by checking i_size under i_data_sem.
- */
-static inline void ext4_wb_update_i_disksize(struct inode *inode, loff_t newsize)
-{
-       loff_t i_size;
-
-       down_write(&EXT4_I(inode)->i_data_sem);
-       i_size = i_size_read(inode);
-       if (newsize > i_size)
-               newsize = i_size;
-       if (newsize > EXT4_I(inode)->i_disksize)
-               EXT4_I(inode)->i_disksize = newsize;
-       up_write(&EXT4_I(inode)->i_data_sem);
-}
-
 struct ext4_group_info {
        unsigned long   bb_state;
        struct rb_root  bb_free_root;
index 82df3ce9874ab7f3a65abc10e2bd2238b1ae2af3..01b0c208f62507e12f50ddd4fd3669972797f823 100644 (file)
@@ -3313,6 +3313,11 @@ static int ext4_split_extent(handle_t *handle,
                return PTR_ERR(path);
        depth = ext_depth(inode);
        ex = path[depth].p_ext;
+       if (!ex) {
+               EXT4_ERROR_INODE(inode, "unexpected hole at %lu",
+                                (unsigned long) map->m_lblk);
+               return -EIO;
+       }
        uninitialized = ext4_ext_is_uninitialized(ex);
        split_flag1 = 0;
 
@@ -3694,6 +3699,12 @@ static int ext4_convert_initialized_extents(handle_t *handle,
                }
                depth = ext_depth(inode);
                ex = path[depth].p_ext;
+               if (!ex) {
+                       EXT4_ERROR_INODE(inode, "unexpected hole at %lu",
+                                        (unsigned long) map->m_lblk);
+                       err = -EIO;
+                       goto out;
+               }
        }
 
        err = ext4_ext_get_access(handle, inode, path + depth);
@@ -4730,6 +4741,9 @@ static long ext4_zero_range(struct file *file, loff_t offset,
 
        trace_ext4_zero_range(inode, offset, len, mode);
 
+       if (!S_ISREG(inode->i_mode))
+               return -EINVAL;
+
        /*
         * Write out all dirty pages to avoid race conditions
         * Then release them.
@@ -4878,9 +4892,6 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
        if (mode & FALLOC_FL_PUNCH_HOLE)
                return ext4_punch_hole(inode, offset, len);
 
-       if (mode & FALLOC_FL_COLLAPSE_RANGE)
-               return ext4_collapse_range(inode, offset, len);
-
        ret = ext4_convert_inline_data(inode);
        if (ret)
                return ret;
@@ -4892,6 +4903,9 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
        if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
                return -EOPNOTSUPP;
 
+       if (mode & FALLOC_FL_COLLAPSE_RANGE)
+               return ext4_collapse_range(inode, offset, len);
+
        if (mode & FALLOC_FL_ZERO_RANGE)
                return ext4_zero_range(file, offset, len, mode);
 
@@ -5229,18 +5243,19 @@ ext4_ext_shift_path_extents(struct ext4_ext_path *path, ext4_lblk_t shift,
                        if (ex_start == EXT_FIRST_EXTENT(path[depth].p_hdr))
                                update = 1;
 
-                       *start = ex_last->ee_block +
+                       *start = le32_to_cpu(ex_last->ee_block) +
                                ext4_ext_get_actual_len(ex_last);
 
                        while (ex_start <= ex_last) {
-                               ex_start->ee_block -= shift;
-                               if (ex_start >
-                                       EXT_FIRST_EXTENT(path[depth].p_hdr)) {
-                                       if (ext4_ext_try_to_merge_right(inode,
-                                               path, ex_start - 1))
-                                               ex_last--;
-                               }
-                               ex_start++;
+                               le32_add_cpu(&ex_start->ee_block, -shift);
+                               /* Try to merge to the left. */
+                               if ((ex_start >
+                                    EXT_FIRST_EXTENT(path[depth].p_hdr)) &&
+                                   ext4_ext_try_to_merge_right(inode,
+                                                       path, ex_start - 1))
+                                       ex_last--;
+                               else
+                                       ex_start++;
                        }
                        err = ext4_ext_dirty(handle, inode, path + depth);
                        if (err)
@@ -5255,7 +5270,7 @@ ext4_ext_shift_path_extents(struct ext4_ext_path *path, ext4_lblk_t shift,
                if (err)
                        goto out;
 
-               path[depth].p_idx->ei_block -= shift;
+               le32_add_cpu(&path[depth].p_idx->ei_block, -shift);
                err = ext4_ext_dirty(handle, inode, path + depth);
                if (err)
                        goto out;
@@ -5300,7 +5315,8 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
                return ret;
        }
 
-       stop_block = extent->ee_block + ext4_ext_get_actual_len(extent);
+       stop_block = le32_to_cpu(extent->ee_block) +
+                       ext4_ext_get_actual_len(extent);
        ext4_ext_drop_refs(path);
        kfree(path);
 
@@ -5313,10 +5329,18 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
         * enough to accomodate the shift.
         */
        path = ext4_ext_find_extent(inode, start - 1, NULL, 0);
+       if (IS_ERR(path))
+               return PTR_ERR(path);
        depth = path->p_depth;
        extent =  path[depth].p_ext;
-       ex_start = extent->ee_block;
-       ex_end = extent->ee_block + ext4_ext_get_actual_len(extent);
+       if (extent) {
+               ex_start = le32_to_cpu(extent->ee_block);
+               ex_end = le32_to_cpu(extent->ee_block) +
+                       ext4_ext_get_actual_len(extent);
+       } else {
+               ex_start = 0;
+               ex_end = 0;
+       }
        ext4_ext_drop_refs(path);
        kfree(path);
 
@@ -5331,7 +5355,13 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
                        return PTR_ERR(path);
                depth = path->p_depth;
                extent = path[depth].p_ext;
-               current_block = extent->ee_block;
+               if (!extent) {
+                       EXT4_ERROR_INODE(inode, "unexpected hole at %lu",
+                                        (unsigned long) start);
+                       return -EIO;
+               }
+
+               current_block = le32_to_cpu(extent->ee_block);
                if (start > current_block) {
                        /* Hole, move to the next extent */
                        ret = mext_next_extent(inode, path, &extent);
@@ -5365,17 +5395,18 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
        ext4_lblk_t punch_start, punch_stop;
        handle_t *handle;
        unsigned int credits;
-       loff_t new_size;
+       loff_t new_size, ioffset;
        int ret;
 
-       BUG_ON(offset + len > i_size_read(inode));
-
        /* Collapse range works only on fs block size aligned offsets. */
        if (offset & (EXT4_BLOCK_SIZE(sb) - 1) ||
            len & (EXT4_BLOCK_SIZE(sb) - 1))
                return -EINVAL;
 
        if (!S_ISREG(inode->i_mode))
+               return -EINVAL;
+
+       if (EXT4_SB(inode->i_sb)->s_cluster_ratio > 1)
                return -EOPNOTSUPP;
 
        trace_ext4_collapse_range(inode, offset, len);
@@ -5383,22 +5414,34 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
        punch_start = offset >> EXT4_BLOCK_SIZE_BITS(sb);
        punch_stop = (offset + len) >> EXT4_BLOCK_SIZE_BITS(sb);
 
+       /* Call ext4_force_commit to flush all data in case of data=journal. */
+       if (ext4_should_journal_data(inode)) {
+               ret = ext4_force_commit(inode->i_sb);
+               if (ret)
+                       return ret;
+       }
+
+       /*
+        * Need to round down offset to be aligned with page size boundary
+        * for page size > block size.
+        */
+       ioffset = round_down(offset, PAGE_SIZE);
+
        /* Write out all dirty pages */
-       ret = filemap_write_and_wait_range(inode->i_mapping, offset, -1);
+       ret = filemap_write_and_wait_range(inode->i_mapping, ioffset,
+                                          LLONG_MAX);
        if (ret)
                return ret;
 
        /* Take mutex lock */
        mutex_lock(&inode->i_mutex);
 
-       /* It's not possible punch hole on append only file */
-       if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) {
-               ret = -EPERM;
-               goto out_mutex;
-       }
-
-       if (IS_SWAPFILE(inode)) {
-               ret = -ETXTBSY;
+       /*
+        * There is no need to overlap collapse range with EOF, in which case
+        * it is effectively a truncate operation
+        */
+       if (offset + len >= i_size_read(inode)) {
+               ret = -EINVAL;
                goto out_mutex;
        }
 
@@ -5408,7 +5451,7 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
                goto out_mutex;
        }
 
-       truncate_pagecache_range(inode, offset, -1);
+       truncate_pagecache(inode, ioffset);
 
        /* Wait for existing dio to complete */
        ext4_inode_block_unlocked_dio(inode);
@@ -5425,7 +5468,7 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
        ext4_discard_preallocations(inode);
 
        ret = ext4_es_remove_extent(inode, punch_start,
-                                   EXT_MAX_BLOCKS - punch_start - 1);
+                                   EXT_MAX_BLOCKS - punch_start);
        if (ret) {
                up_write(&EXT4_I(inode)->i_data_sem);
                goto out_stop;
@@ -5436,6 +5479,7 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
                up_write(&EXT4_I(inode)->i_data_sem);
                goto out_stop;
        }
+       ext4_discard_preallocations(inode);
 
        ret = ext4_ext_shift_extents(inode, handle, punch_stop,
                                     punch_stop - punch_start);
@@ -5445,10 +5489,9 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
        }
 
        new_size = i_size_read(inode) - len;
-       truncate_setsize(inode, new_size);
+       i_size_write(inode, new_size);
        EXT4_I(inode)->i_disksize = new_size;
 
-       ext4_discard_preallocations(inode);
        up_write(&EXT4_I(inode)->i_data_sem);
        if (IS_SYNC(inode))
                ext4_handle_sync(handle);
index 0a014a7194b28cac95e56f21b59f3776fcf8c9fc..0ebc21204b5184841405f890fa11dd5ae11ef54c 100644 (file)
@@ -810,7 +810,7 @@ retry:
 
                        newes.es_lblk = end + 1;
                        newes.es_len = len2;
-                       block = 0x7FDEADBEEF;
+                       block = 0x7FDEADBEEFULL;
                        if (ext4_es_is_written(&orig_es) ||
                            ext4_es_is_unwritten(&orig_es))
                                block = ext4_es_pblock(&orig_es) +
index ca7502d89fdee07b96585c768854375b207daaf6..063fc1538355972d912553ad6c8e419390f057de 100644 (file)
@@ -82,7 +82,7 @@ ext4_unaligned_aio(struct inode *inode, const struct iovec *iov,
        size_t count = iov_length(iov, nr_segs);
        loff_t final_size = pos + count;
 
-       if (pos >= inode->i_size)
+       if (pos >= i_size_read(inode))
                return 0;
 
        if ((pos & blockmask) || (final_size & blockmask))
index 5b0d2c7d54080dea4080909fe8ec6a74ecf19b56..d7b7462a0e13e11e7131f2b148d1323a3de5c996 100644 (file)
@@ -522,6 +522,10 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
        if (unlikely(map->m_len > INT_MAX))
                map->m_len = INT_MAX;
 
+       /* We can handle the block number less than EXT_MAX_BLOCKS */
+       if (unlikely(map->m_lblk >= EXT_MAX_BLOCKS))
+               return -EIO;
+
        /* Lookup extent status tree firstly */
        if (ext4_es_lookup_extent(inode, map->m_lblk, &es)) {
                ext4_es_lru_add(inode);
@@ -2243,13 +2247,23 @@ static int mpage_map_and_submit_extent(handle_t *handle,
                        return err;
        } while (map->m_len);
 
-       /* Update on-disk size after IO is submitted */
+       /*
+        * Update on-disk size after IO is submitted.  Races with
+        * truncate are avoided by checking i_size under i_data_sem.
+        */
        disksize = ((loff_t)mpd->first_page) << PAGE_CACHE_SHIFT;
        if (disksize > EXT4_I(inode)->i_disksize) {
                int err2;
-
-               ext4_wb_update_i_disksize(inode, disksize);
+               loff_t i_size;
+
+               down_write(&EXT4_I(inode)->i_data_sem);
+               i_size = i_size_read(inode);
+               if (disksize > i_size)
+                       disksize = i_size;
+               if (disksize > EXT4_I(inode)->i_disksize)
+                       EXT4_I(inode)->i_disksize = disksize;
                err2 = ext4_mark_inode_dirty(handle, inode);
+               up_write(&EXT4_I(inode)->i_data_sem);
                if (err2)
                        ext4_error(inode->i_sb,
                                   "Failed to mark inode %lu dirty",
@@ -3527,15 +3541,6 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
        }
 
        mutex_lock(&inode->i_mutex);
-       /* It's not possible punch hole on append only file */
-       if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) {
-               ret = -EPERM;
-               goto out_mutex;
-       }
-       if (IS_SWAPFILE(inode)) {
-               ret = -ETXTBSY;
-               goto out_mutex;
-       }
 
        /* No need to punch hole beyond i_size */
        if (offset >= inode->i_size)
@@ -3616,7 +3621,6 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
                ret = ext4_free_hole_blocks(handle, inode, first_block,
                                            stop_block);
 
-       ext4_discard_preallocations(inode);
        up_write(&EXT4_I(inode)->i_data_sem);
        if (IS_SYNC(inode))
                ext4_handle_sync(handle);
@@ -4423,21 +4427,20 @@ out_brelse:
  *
  * We are called from a few places:
  *
- * - Within generic_file_write() for O_SYNC files.
+ * - Within generic_file_aio_write() -> generic_write_sync() for O_SYNC files.
  *   Here, there will be no transaction running. We wait for any running
  *   transaction to commit.
  *
- * - Within sys_sync(), kupdate and such.
- *   We wait on commit, if tol to.
+ * - Within flush work (sys_sync(), kupdate and such).
+ *   We wait on commit, if told to.
  *
- * - Within prune_icache() (PF_MEMALLOC == true)
- *   Here we simply return.  We can't afford to block kswapd on the
- *   journal commit.
+ * - Within iput_final() -> write_inode_now()
+ *   We wait on commit, if told to.
  *
  * In all cases it is actually safe for us to return without doing anything,
  * because the inode has been copied into a raw inode buffer in
- * ext4_mark_inode_dirty().  This is a correctness thing for O_SYNC and for
- * knfsd.
+ * ext4_mark_inode_dirty().  This is a correctness thing for WB_SYNC_ALL
+ * writeback.
  *
  * Note that we are absolutely dependent upon all inode dirtiers doing the
  * right thing: they *must* call mark_inode_dirty() after dirtying info in
@@ -4449,15 +4452,15 @@ out_brelse:
  *     stuff();
  *     inode->i_size = expr;
  *
- * is in error because a kswapd-driven write_inode() could occur while
- * `stuff()' is running, and the new i_size will be lost.  Plus the inode
- * will no longer be on the superblock's dirty inode list.
+ * is in error because write_inode() could occur while `stuff()' is running,
+ * and the new i_size will be lost.  Plus the inode will no longer be on the
+ * superblock's dirty inode list.
  */
 int ext4_write_inode(struct inode *inode, struct writeback_control *wbc)
 {
        int err;
 
-       if (current->flags & PF_MEMALLOC)
+       if (WARN_ON_ONCE(current->flags & PF_MEMALLOC))
                return 0;
 
        if (EXT4_SB(inode->i_sb)->s_journal) {
index a888cac76e9c55c34002f930a7bc8a8df53376bf..c8238a26818cd9ef7567d0552a60a461bfd1f76e 100644 (file)
@@ -989,7 +989,7 @@ static int ext4_mb_get_buddy_page_lock(struct super_block *sb,
        poff = block % blocks_per_page;
        page = find_or_create_page(inode->i_mapping, pnum, GFP_NOFS);
        if (!page)
-               return -EIO;
+               return -ENOMEM;
        BUG_ON(page->mapping != inode->i_mapping);
        e4b->bd_bitmap_page = page;
        e4b->bd_bitmap = page_address(page) + (poff * sb->s_blocksize);
@@ -1003,7 +1003,7 @@ static int ext4_mb_get_buddy_page_lock(struct super_block *sb,
        pnum = block / blocks_per_page;
        page = find_or_create_page(inode->i_mapping, pnum, GFP_NOFS);
        if (!page)
-               return -EIO;
+               return -ENOMEM;
        BUG_ON(page->mapping != inode->i_mapping);
        e4b->bd_buddy_page = page;
        return 0;
@@ -1168,7 +1168,11 @@ ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group,
                        unlock_page(page);
                }
        }
-       if (page == NULL || !PageUptodate(page)) {
+       if (page == NULL) {
+               ret = -ENOMEM;
+               goto err;
+       }
+       if (!PageUptodate(page)) {
                ret = -EIO;
                goto err;
        }
@@ -1197,7 +1201,11 @@ ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group,
                        unlock_page(page);
                }
        }
-       if (page == NULL || !PageUptodate(page)) {
+       if (page == NULL) {
+               ret = -ENOMEM;
+               goto err;
+       }
+       if (!PageUptodate(page)) {
                ret = -EIO;
                goto err;
        }
@@ -5008,6 +5016,8 @@ error_return:
  */
 static int ext4_trim_extent(struct super_block *sb, int start, int count,
                             ext4_group_t group, struct ext4_buddy *e4b)
+__releases(bitlock)
+__acquires(bitlock)
 {
        struct ext4_free_extent ex;
        int ret = 0;
index ab95508e3d4018eab92647c6d2308e98524080d1..c18d95b5054081c75e0c7a2fab975976838f9b02 100644 (file)
@@ -308,13 +308,14 @@ static void ext4_end_bio(struct bio *bio, int error)
        if (error) {
                struct inode *inode = io_end->inode;
 
-               ext4_warning(inode->i_sb, "I/O error writing to inode %lu "
+               ext4_warning(inode->i_sb, "I/O error %d writing to inode %lu "
                             "(offset %llu size %ld starting block %llu)",
-                            inode->i_ino,
+                            error, inode->i_ino,
                             (unsigned long long) io_end->offset,
                             (long) io_end->size,
                             (unsigned long long)
                             bi_sector >> (inode->i_blkbits - 9));
+               mapping_set_error(inode->i_mapping, error);
        }
 
        if (io_end->flag & EXT4_IO_END_UNWRITTEN) {
index f3c667091618d8b26e09964dafe2f673a4c6cbd3..6f9e6fadac04e1c8af1d4a98d6258cdbc2f45dea 100644 (file)
@@ -3869,19 +3869,38 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                        goto failed_mount2;
                }
        }
+
+       /*
+        * set up enough so that it can read an inode,
+        * and create new inode for buddy allocator
+        */
+       sbi->s_gdb_count = db_count;
+       if (!test_opt(sb, NOLOAD) &&
+           EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL))
+               sb->s_op = &ext4_sops;
+       else
+               sb->s_op = &ext4_nojournal_sops;
+
+       ext4_ext_init(sb);
+       err = ext4_mb_init(sb);
+       if (err) {
+               ext4_msg(sb, KERN_ERR, "failed to initialize mballoc (%d)",
+                        err);
+               goto failed_mount2;
+       }
+
        if (!ext4_check_descriptors(sb, &first_not_zeroed)) {
                ext4_msg(sb, KERN_ERR, "group descriptors corrupted!");
-               goto failed_mount2;
+               goto failed_mount2a;
        }
        if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG))
                if (!ext4_fill_flex_info(sb)) {
                        ext4_msg(sb, KERN_ERR,
                               "unable to initialize "
                               "flex_bg meta info!");
-                       goto failed_mount2;
+                       goto failed_mount2a;
                }
 
-       sbi->s_gdb_count = db_count;
        get_random_bytes(&sbi->s_next_generation, sizeof(u32));
        spin_lock_init(&sbi->s_next_gen_lock);
 
@@ -3916,14 +3935,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        sbi->s_stripe = ext4_get_stripe_size(sbi);
        sbi->s_extent_max_zeroout_kb = 32;
 
-       /*
-        * set up enough so that it can read an inode
-        */
-       if (!test_opt(sb, NOLOAD) &&
-           EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL))
-               sb->s_op = &ext4_sops;
-       else
-               sb->s_op = &ext4_nojournal_sops;
        sb->s_export_op = &ext4_export_ops;
        sb->s_xattr = ext4_xattr_handlers;
 #ifdef CONFIG_QUOTA
@@ -4113,21 +4124,13 @@ no_journal:
        if (err) {
                ext4_msg(sb, KERN_ERR, "failed to reserve %llu clusters for "
                         "reserved pool", ext4_calculate_resv_clusters(sb));
-               goto failed_mount4a;
+               goto failed_mount5;
        }
 
        err = ext4_setup_system_zone(sb);
        if (err) {
                ext4_msg(sb, KERN_ERR, "failed to initialize system "
                         "zone (%d)", err);
-               goto failed_mount4a;
-       }
-
-       ext4_ext_init(sb);
-       err = ext4_mb_init(sb);
-       if (err) {
-               ext4_msg(sb, KERN_ERR, "failed to initialize mballoc (%d)",
-                        err);
                goto failed_mount5;
        }
 
@@ -4204,11 +4207,8 @@ failed_mount8:
 failed_mount7:
        ext4_unregister_li_request(sb);
 failed_mount6:
-       ext4_mb_release(sb);
-failed_mount5:
-       ext4_ext_release(sb);
        ext4_release_system_zone(sb);
-failed_mount4a:
+failed_mount5:
        dput(sb->s_root);
        sb->s_root = NULL;
 failed_mount4:
@@ -4232,11 +4232,14 @@ failed_mount3:
        percpu_counter_destroy(&sbi->s_extent_cache_cnt);
        if (sbi->s_mmp_tsk)
                kthread_stop(sbi->s_mmp_tsk);
+failed_mount2a:
+       ext4_mb_release(sb);
 failed_mount2:
        for (i = 0; i < db_count; i++)
                brelse(sbi->s_group_desc[i]);
        ext4_kvfree(sbi->s_group_desc);
 failed_mount:
+       ext4_ext_release(sb);
        if (sbi->s_chksum_driver)
                crypto_free_shash(sbi->s_chksum_driver);
        if (sbi->s_proc) {
index 1f5cf5880718d28c8ca7893f7165807f78101c6b..4eec399ec807bc6733d1a90b8c3d0d205eb795c1 100644 (file)
@@ -520,8 +520,8 @@ static void ext4_xattr_update_super_block(handle_t *handle,
 }
 
 /*
- * Release the xattr block BH: If the reference count is > 1, decrement
- * it; otherwise free the block.
+ * Release the xattr block BH: If the reference count is > 1, decrement it;
+ * otherwise free the block.
  */
 static void
 ext4_xattr_release_block(handle_t *handle, struct inode *inode,
@@ -542,16 +542,31 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode,
                if (ce)
                        mb_cache_entry_free(ce);
                get_bh(bh);
+               unlock_buffer(bh);
                ext4_free_blocks(handle, inode, bh, 0, 1,
                                 EXT4_FREE_BLOCKS_METADATA |
                                 EXT4_FREE_BLOCKS_FORGET);
-               unlock_buffer(bh);
        } else {
                le32_add_cpu(&BHDR(bh)->h_refcount, -1);
                if (ce)
                        mb_cache_entry_release(ce);
+               /*
+                * Beware of this ugliness: Releasing of xattr block references
+                * from different inodes can race and so we have to protect
+                * from a race where someone else frees the block (and releases
+                * its journal_head) before we are done dirtying the buffer. In
+                * nojournal mode this race is harmless and we actually cannot
+                * call ext4_handle_dirty_xattr_block() with locked buffer as
+                * that function can call sync_dirty_buffer() so for that case
+                * we handle the dirtying after unlocking the buffer.
+                */
+               if (ext4_handle_valid(handle))
+                       error = ext4_handle_dirty_xattr_block(handle, inode,
+                                                             bh);
                unlock_buffer(bh);
-               error = ext4_handle_dirty_xattr_block(handle, inode, bh);
+               if (!ext4_handle_valid(handle))
+                       error = ext4_handle_dirty_xattr_block(handle, inode,
+                                                             bh);
                if (IS_SYNC(inode))
                        ext4_handle_sync(handle);
                dquot_free_block(inode, EXT4_C2B(EXT4_SB(inode->i_sb), 1));
index 9ead1596399a12ef66ecf5f087b59463424ccf5d..72c82f69b01b28594e56bb9518df6f211f0d51a9 100644 (file)
@@ -274,15 +274,15 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg,
                break;
 #if BITS_PER_LONG != 32
        /* 32-bit arches must use fcntl64() */
-       case F_GETLKP:
+       case F_OFD_GETLK:
 #endif
        case F_GETLK:
                err = fcntl_getlk(filp, cmd, (struct flock __user *) arg);
                break;
 #if BITS_PER_LONG != 32
        /* 32-bit arches must use fcntl64() */
-       case F_SETLKP:
-       case F_SETLKPW:
+       case F_OFD_SETLK:
+       case F_OFD_SETLKW:
 #endif
                /* Fallthrough */
        case F_SETLK:
@@ -399,13 +399,13 @@ SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd,
        
        switch (cmd) {
        case F_GETLK64:
-       case F_GETLKP:
+       case F_OFD_GETLK:
                err = fcntl_getlk64(f.file, cmd, (struct flock64 __user *) arg);
                break;
        case F_SETLK64:
        case F_SETLKW64:
-       case F_SETLKP:
-       case F_SETLKPW:
+       case F_OFD_SETLK:
+       case F_OFD_SETLKW:
                err = fcntl_setlk64(fd, f.file, cmd,
                                (struct flock64 __user *) arg);
                break;
index 13fc7a6d380ae6648945c8956cc53901de2d0ccc..e663aeac579e5d8aaa2596a177114b17f262bd6c 100644 (file)
 #define IS_POSIX(fl)   (fl->fl_flags & FL_POSIX)
 #define IS_FLOCK(fl)   (fl->fl_flags & FL_FLOCK)
 #define IS_LEASE(fl)   (fl->fl_flags & (FL_LEASE|FL_DELEG))
-#define IS_FILE_PVT(fl)        (fl->fl_flags & FL_FILE_PVT)
+#define IS_OFDLCK(fl)  (fl->fl_flags & FL_OFDLCK)
 
 static bool lease_breaking(struct file_lock *fl)
 {
@@ -564,7 +564,7 @@ static void __locks_insert_block(struct file_lock *blocker,
        BUG_ON(!list_empty(&waiter->fl_block));
        waiter->fl_next = blocker;
        list_add_tail(&waiter->fl_block, &blocker->fl_block);
-       if (IS_POSIX(blocker) && !IS_FILE_PVT(blocker))
+       if (IS_POSIX(blocker) && !IS_OFDLCK(blocker))
                locks_insert_global_blocked(waiter);
 }
 
@@ -759,12 +759,12 @@ EXPORT_SYMBOL(posix_test_lock);
  * of tasks (such as posix threads) sharing the same open file table.
  * To handle those cases, we just bail out after a few iterations.
  *
- * For FL_FILE_PVT locks, the owner is the filp, not the files_struct.
+ * For FL_OFDLCK locks, the owner is the filp, not the files_struct.
  * Because the owner is not even nominally tied to a thread of
  * execution, the deadlock detection below can't reasonably work well. Just
  * skip it for those.
  *
- * In principle, we could do a more limited deadlock detection on FL_FILE_PVT
+ * In principle, we could do a more limited deadlock detection on FL_OFDLCK
  * locks that just checks for the case where two tasks are attempting to
  * upgrade from read to write locks on the same inode.
  */
@@ -791,9 +791,9 @@ static int posix_locks_deadlock(struct file_lock *caller_fl,
 
        /*
         * This deadlock detector can't reasonably detect deadlocks with
-        * FL_FILE_PVT locks, since they aren't owned by a process, per-se.
+        * FL_OFDLCK locks, since they aren't owned by a process, per-se.
         */
-       if (IS_FILE_PVT(caller_fl))
+       if (IS_OFDLCK(caller_fl))
                return 0;
 
        while ((block_fl = what_owner_is_waiting_for(block_fl))) {
@@ -1391,11 +1391,10 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
 
 restart:
        break_time = flock->fl_break_time;
-       if (break_time != 0) {
+       if (break_time != 0)
                break_time -= jiffies;
-               if (break_time == 0)
-                       break_time++;
-       }
+       if (break_time == 0)
+               break_time++;
        locks_insert_block(flock, new_fl);
        spin_unlock(&inode->i_lock);
        error = wait_event_interruptible_timeout(new_fl->fl_wait,
@@ -1891,7 +1890,7 @@ EXPORT_SYMBOL_GPL(vfs_test_lock);
 
 static int posix_lock_to_flock(struct flock *flock, struct file_lock *fl)
 {
-       flock->l_pid = IS_FILE_PVT(fl) ? -1 : fl->fl_pid;
+       flock->l_pid = IS_OFDLCK(fl) ? -1 : fl->fl_pid;
 #if BITS_PER_LONG == 32
        /*
         * Make sure we can represent the posix lock via
@@ -1913,7 +1912,7 @@ static int posix_lock_to_flock(struct flock *flock, struct file_lock *fl)
 #if BITS_PER_LONG == 32
 static void posix_lock_to_flock64(struct flock64 *flock, struct file_lock *fl)
 {
-       flock->l_pid = IS_FILE_PVT(fl) ? -1 : fl->fl_pid;
+       flock->l_pid = IS_OFDLCK(fl) ? -1 : fl->fl_pid;
        flock->l_start = fl->fl_start;
        flock->l_len = fl->fl_end == OFFSET_MAX ? 0 :
                fl->fl_end - fl->fl_start + 1;
@@ -1942,13 +1941,13 @@ int fcntl_getlk(struct file *filp, unsigned int cmd, struct flock __user *l)
        if (error)
                goto out;
 
-       if (cmd == F_GETLKP) {
+       if (cmd == F_OFD_GETLK) {
                error = -EINVAL;
                if (flock.l_pid != 0)
                        goto out;
 
                cmd = F_GETLK;
-               file_lock.fl_flags |= FL_FILE_PVT;
+               file_lock.fl_flags |= FL_OFDLCK;
                file_lock.fl_owner = (fl_owner_t)filp;
        }
 
@@ -2074,25 +2073,25 @@ again:
 
        /*
         * If the cmd is requesting file-private locks, then set the
-        * FL_FILE_PVT flag and override the owner.
+        * FL_OFDLCK flag and override the owner.
         */
        switch (cmd) {
-       case F_SETLKP:
+       case F_OFD_SETLK:
                error = -EINVAL;
                if (flock.l_pid != 0)
                        goto out;
 
                cmd = F_SETLK;
-               file_lock->fl_flags |= FL_FILE_PVT;
+               file_lock->fl_flags |= FL_OFDLCK;
                file_lock->fl_owner = (fl_owner_t)filp;
                break;
-       case F_SETLKPW:
+       case F_OFD_SETLKW:
                error = -EINVAL;
                if (flock.l_pid != 0)
                        goto out;
 
                cmd = F_SETLKW;
-               file_lock->fl_flags |= FL_FILE_PVT;
+               file_lock->fl_flags |= FL_OFDLCK;
                file_lock->fl_owner = (fl_owner_t)filp;
                /* Fallthrough */
        case F_SETLKW:
@@ -2144,13 +2143,13 @@ int fcntl_getlk64(struct file *filp, unsigned int cmd, struct flock64 __user *l)
        if (error)
                goto out;
 
-       if (cmd == F_GETLKP) {
+       if (cmd == F_OFD_GETLK) {
                error = -EINVAL;
                if (flock.l_pid != 0)
                        goto out;
 
                cmd = F_GETLK64;
-               file_lock.fl_flags |= FL_FILE_PVT;
+               file_lock.fl_flags |= FL_OFDLCK;
                file_lock.fl_owner = (fl_owner_t)filp;
        }
 
@@ -2209,25 +2208,25 @@ again:
 
        /*
         * If the cmd is requesting file-private locks, then set the
-        * FL_FILE_PVT flag and override the owner.
+        * FL_OFDLCK flag and override the owner.
         */
        switch (cmd) {
-       case F_SETLKP:
+       case F_OFD_SETLK:
                error = -EINVAL;
                if (flock.l_pid != 0)
                        goto out;
 
                cmd = F_SETLK64;
-               file_lock->fl_flags |= FL_FILE_PVT;
+               file_lock->fl_flags |= FL_OFDLCK;
                file_lock->fl_owner = (fl_owner_t)filp;
                break;
-       case F_SETLKPW:
+       case F_OFD_SETLKW:
                error = -EINVAL;
                if (flock.l_pid != 0)
                        goto out;
 
                cmd = F_SETLKW64;
-               file_lock->fl_flags |= FL_FILE_PVT;
+               file_lock->fl_flags |= FL_OFDLCK;
                file_lock->fl_owner = (fl_owner_t)filp;
                /* Fallthrough */
        case F_SETLKW64:
@@ -2413,8 +2412,8 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl,
        if (IS_POSIX(fl)) {
                if (fl->fl_flags & FL_ACCESS)
                        seq_printf(f, "ACCESS");
-               else if (IS_FILE_PVT(fl))
-                       seq_printf(f, "FLPVT ");
+               else if (IS_OFDLCK(fl))
+                       seq_printf(f, "OFDLCK");
                else
                        seq_printf(f, "POSIX ");
 
index 39c8ef875f91b5a93b57c8886b56569d679296a3..2c73cae9899d25007818373e11eaec1c8fdb9436 100644 (file)
@@ -654,9 +654,11 @@ static struct rpc_clnt *create_backchannel_client(struct rpc_create_args *args)
 
 static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn, struct nfsd4_session *ses)
 {
+       int maxtime = max_cb_time(clp->net);
        struct rpc_timeout      timeparms = {
-               .to_initval     = max_cb_time(clp->net),
+               .to_initval     = maxtime,
                .to_retries     = 0,
+               .to_maxval      = maxtime,
        };
        struct rpc_create_args args = {
                .net            = clp->net,
index 2723c1badd01276f9c1802d6cac210aa40f8f0a3..18881f34737ad89e8259042fd33ee5d6a9c26edc 100644 (file)
@@ -3627,14 +3627,6 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
        /* nfsd4_check_resp_size guarantees enough room for error status */
        if (!op->status)
                op->status = nfsd4_check_resp_size(resp, 0);
-       if (op->status == nfserr_resource && nfsd4_has_session(&resp->cstate)) {
-               struct nfsd4_slot *slot = resp->cstate.slot;
-
-               if (slot->sl_flags & NFSD4_SLOT_CACHETHIS)
-                       op->status = nfserr_rep_too_big_to_cache;
-               else
-                       op->status = nfserr_rep_too_big;
-       }
        if (so) {
                so->so_replay.rp_status = op->status;
                so->so_replay.rp_buflen = (char *)resp->p - (char *)(statp+1);
index 3d30eb1fc95e383e50e91605d3526161bcfdebde..9d64679cec73b00fc4685e23d69374ca122fed09 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -254,16 +254,21 @@ int do_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
                return -EBADF;
 
        /*
-        * It's not possible to punch hole or perform collapse range
-        * on append only file
+        * We can only allow pure fallocate on append only files
         */
-       if (mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_COLLAPSE_RANGE)
-           && IS_APPEND(inode))
+       if ((mode & ~FALLOC_FL_KEEP_SIZE) && IS_APPEND(inode))
                return -EPERM;
 
        if (IS_IMMUTABLE(inode))
                return -EPERM;
 
+       /*
+        * We can not allow to do any fallocate operation on an active
+        * swapfile
+        */
+       if (IS_SWAPFILE(inode))
+               ret = -ETXTBSY;
+
        /*
         * Revalidate the write permissions, in case security policy has
         * changed since the files were opened.
@@ -286,14 +291,6 @@ int do_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
        if (((offset + len) > inode->i_sb->s_maxbytes) || ((offset + len) < 0))
                return -EFBIG;
 
-       /*
-        * There is no need to overlap collapse range with EOF, in which case
-        * it is effectively a truncate operation
-        */
-       if ((mode & FALLOC_FL_COLLAPSE_RANGE) &&
-           (offset + len >= i_size_read(inode)))
-               return -EINVAL;
-
        if (!file->f_op->fallocate)
                return -EOPNOTSUPP;
 
index 82afdcb33183951350df18d3ce05b3aeecdf3e76..951a2321ee010f35c1d3395c09d0830d74197cfd 100644 (file)
@@ -841,7 +841,15 @@ xfs_file_fallocate(
                        goto out_unlock;
                }
 
-               ASSERT(offset + len < i_size_read(inode));
+               /*
+                * There is no need to overlap collapse range with EOF,
+                * in which case it is effectively a truncate operation
+                */
+               if (offset + len >= i_size_read(inode)) {
+                       error = -EINVAL;
+                       goto out_unlock;
+               }
+
                new_size = i_size_read(inode) - len;
 
                error = xfs_collapse_file_space(ip, offset, len);
index 7a9c5bca2b7694f5496dbcf793eea2920fd37af9..878031227c57a0b41be7cde3070ee90f1921b570 100644 (file)
@@ -815,7 +815,7 @@ static inline struct file *get_file(struct file *f)
 #define FL_SLEEP       128     /* A blocking lock */
 #define FL_DOWNGRADE_PENDING   256 /* Lease is being downgraded */
 #define FL_UNLOCK_PENDING      512 /* Lease is being broken */
-#define FL_FILE_PVT    1024    /* lock is private to the file */
+#define FL_OFDLCK      1024    /* lock is "owned" by struct file */
 
 /*
  * Special return value from posix_lock_file() and vfs_lock_file() for
index 1de36be64df4d1516a2a451901733d36fd32ec4e..5ab4e3a76721760e4d5a70f88de282a687858990 100644 (file)
@@ -822,6 +822,7 @@ struct ata_port {
        unsigned long           qc_allocated;
        unsigned int            qc_active;
        int                     nr_active_links; /* #links with active qcs */
+       unsigned int            last_tag;       /* track next tag hw expects */
 
        struct ata_link         link;           /* host default link */
        struct ata_link         *slave_link;    /* see ata_slave_link_init() */
index e530681bea7049cfa818e66acea0bf863952d281..1a4a8c157b31a7eb8cf3e9c1bedba8ab64354542 100644 (file)
@@ -258,14 +258,14 @@ regulator_get_exclusive(struct device *dev, const char *id)
 static inline struct regulator *__must_check
 regulator_get_optional(struct device *dev, const char *id)
 {
-       return NULL;
+       return ERR_PTR(-ENODEV);
 }
 
 
 static inline struct regulator *__must_check
 devm_regulator_get_optional(struct device *dev, const char *id)
 {
-       return NULL;
+       return ERR_PTR(-ENODEV);
 }
 
 static inline void regulator_put(struct regulator *regulator)
index 36aac733840afc1b71deee284cfaf78b973aa673..9f779c7a2da467c7945cff496e7609a3a16bd71a 100644 (file)
@@ -23,6 +23,7 @@ struct serio {
 
        char name[32];
        char phys[32];
+       char firmware_id[128];
 
        bool manual_bind;
 
index 010ea89eeb0e407a85a052e6b8905dedb6ac5991..6a1a0245474feee8f32fe040e56f0044f53a20f4 100644 (file)
@@ -16,15 +16,6 @@ struct mpage_da_data;
 struct ext4_map_blocks;
 struct extent_status;
 
-/* shim until we merge in the xfs_collapse_range branch */
-#ifndef FALLOC_FL_COLLAPSE_RANGE
-#define FALLOC_FL_COLLAPSE_RANGE       0x08
-#endif
-
-#ifndef FALLOC_FL_ZERO_RANGE
-#define FALLOC_FL_ZERO_RANGE           0x10
-#endif
-
 #define EXT4_I(inode) (container_of(inode, struct ext4_inode_info, vfs_inode))
 
 #define show_mballoc_flags(flags) __print_flags(flags, "|",    \
index a9b13f8b3595107579ca6ea20421d53a9dd15017..7543b3e51331fcb38574e3f309713b3a6a2d31c0 100644 (file)
 #endif
 
 /*
- * fd "private" POSIX locks.
+ * Open File Description Locks
  *
- * Usually POSIX locks held by a process are released on *any* close and are
+ * Usually record locks held by a process are released on *any* close and are
  * not inherited across a fork().
  *
- * These cmd values will set locks that conflict with normal POSIX locks, but
- * are "owned" by the opened file, not the process. This means that they are
- * inherited across fork() like BSD (flock) locks, and they are only released
- * automatically when the last reference to the the open file against which
- * they were acquired is put.
+ * These cmd values will set locks that conflict with process-associated
+ * record  locks, but are "owned" by the open file description, not the
+ * process. This means that they are inherited across fork() like BSD (flock)
+ * locks, and they are only released automatically when the last reference to
+ * the the open file against which they were acquired is put.
  */
-#define F_GETLKP       36
-#define F_SETLKP       37
-#define F_SETLKPW      38
+#define F_OFD_GETLK    36
+#define F_OFD_SETLK    37
+#define F_OFD_SETLKW   38
 
 #define F_OWNER_TID    0
 #define F_OWNER_PID    1
index bd24470d24a2c7a3145af21094e03f67b7ce0761..f4849525519c7a301f4202f68a8eea9fb0e9d296 100644 (file)
@@ -164,6 +164,7 @@ struct input_keymap_entry {
 #define INPUT_PROP_DIRECT              0x01    /* direct input devices */
 #define INPUT_PROP_BUTTONPAD           0x02    /* has button(s) under pad */
 #define INPUT_PROP_SEMI_MT             0x03    /* touch rectangle only */
+#define INPUT_PROP_TOPBUTTONPAD                0x04    /* softbuttons at top of pad */
 
 #define INPUT_PROP_MAX                 0x1f
 #define INPUT_PROP_CNT                 (INPUT_PROP_MAX + 1)
index d0f0bef3be488af9eb9406cc5d28272093abb5a6..93e332d5ed778f4185c3a0a791edc0928b78d198 100644 (file)
@@ -1955,12 +1955,17 @@ int fixup_user_fault(struct task_struct *tsk, struct mm_struct *mm,
                     unsigned long address, unsigned int fault_flags)
 {
        struct vm_area_struct *vma;
+       vm_flags_t vm_flags;
        int ret;
 
        vma = find_extend_vma(mm, address);
        if (!vma || address < vma->vm_start)
                return -EFAULT;
 
+       vm_flags = (fault_flags & FAULT_FLAG_WRITE) ? VM_WRITE : VM_READ;
+       if (!(vm_flags & vma->vm_flags))
+               return -EFAULT;
+
        ret = handle_mm_fault(mm, vma, address, fault_flags);
        if (ret & VM_FAULT_ERROR) {
                if (ret & VM_FAULT_OOM)
index b4beb77967b17949daf46623a822cb7e960e8829..2c7341dbc5d68d1948ad0efa713ad3a85307608e 100644 (file)
@@ -3317,9 +3317,9 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd,
        case F_GETLK:
        case F_SETLK:
        case F_SETLKW:
-       case F_GETLKP:
-       case F_SETLKP:
-       case F_SETLKPW:
+       case F_OFD_GETLK:
+       case F_OFD_SETLK:
+       case F_OFD_SETLKW:
 #if BITS_PER_LONG == 32
        case F_GETLK64:
        case F_SETLK64: