Merge tag 'efi-for-3.8' into x86/efi
authorH. Peter Anvin <hpa@linux.intel.com>
Wed, 30 Jan 2013 22:43:05 +0000 (14:43 -0800)
committerH. Peter Anvin <hpa@linux.intel.com>
Wed, 30 Jan 2013 22:43:05 +0000 (14:43 -0800)
Various urgent EFI fixes and some warning cleanups for v3.8

  * EFI boot stub fix for Macbook Pro's from Maarten Lankhorst
  * Fix an oops in efivarfs from Lingzhu Xiang
  * 32-bit warning cleanups from Jan Beulich
  * Patch to Boot on >512GB RAM systems from Nathan Zimmer
  * Set efi.runtime_version correctly
  * efivarfs updates

Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
259 files changed:
Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt
Documentation/filesystems/f2fs.txt
Documentation/x86/boot.txt
Documentation/x86/zero-page.txt
MAINTAINERS
Makefile
arch/arm/boot/dts/armada-370-db.dts
arch/arm/boot/dts/armada-xp-mv78230.dtsi
arch/arm/boot/dts/armada-xp-mv78260.dtsi
arch/arm/boot/dts/armada-xp-mv78460.dtsi
arch/arm/boot/dts/at91rm9200.dtsi
arch/arm/boot/dts/at91sam9x5.dtsi
arch/arm/boot/dts/cros5250-common.dtsi
arch/arm/boot/dts/dove-cubox.dts
arch/arm/boot/dts/exynos5250-smdk5250.dts
arch/arm/boot/dts/kirkwood-ns2-common.dtsi
arch/arm/boot/dts/kirkwood.dtsi
arch/arm/boot/dts/kizbox.dts
arch/arm/boot/dts/sunxi.dtsi
arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
arch/arm/configs/at91_dt_defconfig
arch/arm/kernel/debug.S
arch/arm/kernel/head.S
arch/arm/kernel/hyp-stub.S
arch/arm/mach-at91/setup.c
arch/arm/mach-imx/Kconfig
arch/arm/mach-imx/clk-imx25.c
arch/arm/mach-imx/clk-imx27.c
arch/arm/mach-imx/clk-imx31.c
arch/arm/mach-imx/clk-imx35.c
arch/arm/mach-imx/clk-imx51-imx53.c
arch/arm/mach-imx/clk-imx6q.c
arch/arm/mach-imx/common.h
arch/arm/mach-imx/devices/devices-common.h
arch/arm/mach-imx/devices/platform-fsl-usb2-udc.c
arch/arm/mach-imx/devices/platform-imx-fb.c
arch/arm/mach-imx/hotplug.c
arch/arm/mach-imx/iram_alloc.c
arch/arm/mach-imx/platsmp.c
arch/arm/mach-imx/pm-imx6q.c
arch/arm/mach-integrator/pci_v3.c
arch/arm/mach-kirkwood/board-ns2.c
arch/arm/mach-mvebu/Makefile
arch/arm/mach-omap2/board-omap4panda.c
arch/arm/mach-omap2/cclock2420_data.c
arch/arm/mach-omap2/cclock2430_data.c
arch/arm/mach-omap2/cclock44xx_data.c
arch/arm/mach-omap2/devices.c
arch/arm/mach-omap2/drm.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/mach-omap2/timer.c
arch/arm/mach-s3c64xx/mach-crag6410-module.c
arch/arm/mach-s3c64xx/pm.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/mmu.c
arch/arm/plat-versatile/headsmp.S
arch/arm/vfp/entry.S
arch/arm/vfp/vfphw.S
arch/arm64/include/asm/elf.h
arch/ia64/kernel/ptrace.c
arch/m68k/include/asm/dma-mapping.h
arch/m68k/include/asm/pgtable_no.h
arch/m68k/include/asm/unistd.h
arch/m68k/include/uapi/asm/unistd.h
arch/m68k/kernel/syscalltable.S
arch/m68k/mm/init.c
arch/parisc/kernel/entry.S
arch/parisc/kernel/irq.c
arch/parisc/kernel/ptrace.c
arch/parisc/kernel/signal.c
arch/parisc/math-emu/cnv_float.h
arch/powerpc/kvm/emulate.c
arch/x86/boot/Makefile
arch/x86/boot/compressed/eboot.c
arch/x86/boot/compressed/head_32.S
arch/x86/boot/compressed/head_64.S
arch/x86/boot/header.S
arch/x86/boot/setup.ld
arch/x86/boot/tools/build.c
arch/x86/include/uapi/asm/bootparam.h
arch/x86/kernel/cpu/perf_event.c
arch/x86/kernel/entry_32.S
arch/x86/kernel/step.c
arch/x86/tools/relocs.c
arch/x86/xen/smp.c
drivers/acpi/apei/apei-base.c
drivers/acpi/processor_idle.c
drivers/acpi/processor_perflib.c
drivers/ata/ahci.c
drivers/ata/libahci.c
drivers/ata/libata-core.c
drivers/ata/libata-eh.c
drivers/base/regmap/regmap-debugfs.c
drivers/base/regmap/regmap.c
drivers/block/virtio_blk.c
drivers/clk/mvebu/clk-cpu.c
drivers/cpufreq/Kconfig.x86
drivers/cpufreq/acpi-cpufreq.c
drivers/cpufreq/cpufreq-cpu0.c
drivers/cpufreq/omap-cpufreq.c
drivers/devfreq/devfreq.c
drivers/devfreq/exynos4_bus.c
drivers/dma/imx-dma.c
drivers/dma/ioat/dma_v3.c
drivers/dma/tegra20-apb-dma.c
drivers/gpio/gpio-mvebu.c
drivers/gpio/gpio-samsung.c
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem_execbuffer.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_object.c
drivers/gpu/drm/radeon/radeon_ring.c
drivers/gpu/drm/radeon/radeon_semaphore.c
drivers/gpu/drm/radeon/reg_srcs/rv515
drivers/gpu/drm/radeon/si.c
drivers/gpu/drm/ttm/ttm_bo.c
drivers/gpu/drm/ttm/ttm_bo_util.c
drivers/hv/hv_balloon.c
drivers/i2c/busses/i2c-designware-core.c
drivers/i2c/busses/i2c-mxs.c
drivers/i2c/busses/i2c-omap.c
drivers/i2c/busses/i2c-sirf.c
drivers/i2c/muxes/i2c-mux-pinctrl.c
drivers/idle/intel_idle.c
drivers/media/i2c/m5mols/m5mols_core.c
drivers/media/platform/coda.c
drivers/media/platform/omap3isp/ispvideo.c
drivers/media/platform/s5p-fimc/fimc-mdevice.c
drivers/media/platform/s5p-mfc/s5p_mfc.c
drivers/media/usb/gspca/kinect.c
drivers/media/usb/gspca/sonixb.c
drivers/media/usb/gspca/sonixj.c
drivers/media/usb/uvc/uvc_ctrl.c
drivers/media/usb/uvc/uvc_v4l2.c
drivers/media/v4l2-core/videobuf2-core.c
drivers/mfd/vexpress-sysreg.c
drivers/misc/ti-st/st_kim.c
drivers/mmc/host/mvsdio.c
drivers/pci/hotplug/pciehp.h
drivers/pci/hotplug/pciehp_core.c
drivers/pci/hotplug/pciehp_ctrl.c
drivers/pci/hotplug/pciehp_hpc.c
drivers/pci/hotplug/shpchp.h
drivers/pci/hotplug/shpchp_core.c
drivers/pci/hotplug/shpchp_ctrl.c
drivers/pci/pcie/Kconfig
drivers/pci/pcie/aer/aerdrv_core.c
drivers/pci/pcie/aspm.c
drivers/staging/iio/adc/mxs-lradc.c
drivers/staging/iio/gyro/adis16080_core.c
drivers/staging/sb105x/sb_pci_mp.c
drivers/staging/vt6656/bssdb.h
drivers/staging/vt6656/int.h
drivers/staging/vt6656/iocmd.h
drivers/staging/vt6656/iowpa.h
drivers/staging/wlan-ng/prism2mgmt.c
drivers/tty/pty.c
drivers/tty/serial/8250/8250.c
drivers/tty/serial/8250/8250.h
drivers/tty/serial/8250/8250_dw.c
drivers/tty/serial/8250/8250_pci.c
drivers/tty/serial/ifx6x60.c
drivers/tty/serial/mxs-auart.c
drivers/tty/serial/samsung.c
drivers/tty/serial/vt8500_serial.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/f_fs.c
drivers/usb/gadget/fsl_mxc_udc.c
drivers/usb/gadget/fsl_udc_core.c
drivers/usb/gadget/fsl_usb2_udc.h
drivers/usb/host/Kconfig
drivers/usb/host/Makefile
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-mxc.c
drivers/usb/host/ehci.h
drivers/usb/host/uhci-hcd.c
drivers/usb/musb/cppi_dma.c
drivers/usb/serial/io_ti.c
drivers/usb/serial/option.c
drivers/vfio/pci/vfio_pci_rdwr.c
drivers/video/imxfb.c
drivers/xen/cpu_hotplug.c
drivers/xen/gntdev.c
drivers/xen/grant-table.c
drivers/xen/privcmd.c
drivers/xen/xen-pciback/pciback.h
fs/Kconfig
fs/btrfs/extent-tree.c
fs/btrfs/extent_map.c
fs/btrfs/extent_map.h
fs/btrfs/file-item.c
fs/btrfs/file.c
fs/btrfs/free-space-cache.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/qgroup.c
fs/btrfs/send.c
fs/btrfs/super.c
fs/btrfs/transaction.c
fs/btrfs/tree-log.c
fs/btrfs/volumes.c
fs/cifs/cifs_dfs_ref.c
fs/cifs/connect.c
fs/f2fs/acl.c
fs/f2fs/checkpoint.c
fs/f2fs/data.c
fs/f2fs/debug.c
fs/f2fs/dir.c
fs/f2fs/f2fs.h
fs/f2fs/file.c
fs/f2fs/gc.c
fs/f2fs/inode.c
fs/f2fs/node.c
fs/f2fs/recovery.c
fs/f2fs/segment.c
fs/f2fs/super.c
fs/f2fs/xattr.c
fs/fuse/Kconfig
fs/fuse/cuse.c
fs/fuse/dev.c
fs/fuse/file.c
include/asm-generic/dma-mapping-broken.h
include/asm-generic/pgtable.h
include/asm-generic/syscalls.h
include/linux/ata.h
include/linux/libata.h
include/linux/module.h
include/linux/platform_data/imx-iram.h [moved from arch/arm/mach-imx/iram.h with 100% similarity]
include/linux/ptrace.h
include/linux/sched.h
include/uapi/linux/serial_core.h
init/do_mounts_initrd.c
init/main.c
kernel/async.c
kernel/compat.c
kernel/debug/kdb/kdb_main.c
kernel/fork.c
kernel/module.c
kernel/ptrace.c
kernel/sched/core.c
kernel/signal.c
kernel/trace/ftrace.c
lib/bug.c
security/device_cgroup.c
security/integrity/evm/evm_crypto.c
sound/pci/hda/hda_codec.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_realtek.c
tools/perf/MANIFEST
tools/perf/Makefile

index 3a26812..bc50899 100644 (file)
@@ -81,7 +81,8 @@ PA31  TXD4
 Required properties for pin configuration node:
 - atmel,pins: 4 integers array, represents a group of pins mux and config
   setting. The format is atmel,pins = <PIN_BANK PIN_BANK_NUM PERIPH CONFIG>.
-  The PERIPH 0 means gpio.
+  The PERIPH 0 means gpio, PERIPH 1 is periph A, PERIPH 2 is periph B...
+  PIN_BANK 0 is pioA, PIN_BANK 1 is pioB...
 
 Bits used for CONFIG:
 PULL_UP                (1 << 0): indicate this pin need a pull up.
@@ -126,7 +127,7 @@ pinctrl@fffff400 {
                pinctrl_dbgu: dbgu-0 {
                        atmel,pins =
                                <1 14 0x1 0x0   /* PB14 periph A */
-                                1 15 0x1 0x1>; /* PB15 periph with pullup */
+                                1 15 0x1 0x1>; /* PB15 periph with pullup */
                };
        };
 };
index 8fbd8b4..dcf338e 100644 (file)
@@ -175,9 +175,9 @@ consists of multiple segments as described below.
                                             align with the zone size <-|
                  |-> align with the segment size
      _________________________________________________________________________
-    |            |            |    Node     |   Segment   |   Segment  |      |
-    | Superblock | Checkpoint |   Address   |    Info.    |   Summary  | Main |
-    |    (SB)    |   (CP)     | Table (NAT) | Table (SIT) | Area (SSA) |      |
+    |            |            |   Segment   |    Node     |   Segment  |      |
+    | Superblock | Checkpoint |    Info.    |   Address   |   Summary  | Main |
+    |    (SB)    |   (CP)     | Table (SIT) | Table (NAT) | Area (SSA) |      |
     |____________|_____2______|______N______|______N______|______N_____|__N___|
                                                                        .      .
                                                              .                .
@@ -200,14 +200,14 @@ consists of multiple segments as described below.
  : It contains file system information, bitmaps for valid NAT/SIT sets, orphan
    inode lists, and summary entries of current active segments.
 
-- Node Address Table (NAT)
- : It is composed of a block address table for all the node blocks stored in
-   Main area.
-
 - Segment Information Table (SIT)
  : It contains segment information such as valid block count and bitmap for the
    validity of all the blocks.
 
+- Node Address Table (NAT)
+ : It is composed of a block address table for all the node blocks stored in
+   Main area.
+
 - Segment Summary Area (SSA)
  : It contains summary entries which contains the owner information of all the
    data and node blocks stored in Main area.
@@ -236,13 +236,13 @@ For file system consistency, each CP points to which NAT and SIT copies are
 valid, as shown as below.
 
   +--------+----------+---------+
-  |   CP   |    NAT   |   SIT   |
+  |   CP   |    SIT   |   NAT   |
   +--------+----------+---------+
   .         .          .          .
   .            .              .              .
   .               .                 .                 .
   +-------+-------+--------+--------+--------+--------+
-  | CP #0 | CP #1 | NAT #0 | NAT #1 | SIT #0 | SIT #1 |
+  | CP #0 | CP #1 | SIT #0 | SIT #1 | NAT #0 | NAT #1 |
   +-------+-------+--------+--------+--------+--------+
      |             ^                          ^
      |             |                          |
index 406d82d..3edb4c2 100644 (file)
@@ -57,6 +57,10 @@ Protocol 2.10:       (Kernel 2.6.31) Added a protocol for relaxed alignment
 Protocol 2.11: (Kernel 3.6) Added a field for offset of EFI handover
                protocol entry point.
 
+Protocol 2.12: (Kernel 3.9) Added the xloadflags field and extension fields
+               to struct boot_params for for loading bzImage and ramdisk
+               above 4G in 64bit.
+
 **** MEMORY LAYOUT
 
 The traditional memory map for the kernel loader, used for Image or
@@ -182,7 +186,7 @@ Offset      Proto   Name            Meaning
 0230/4 2.05+   kernel_alignment Physical addr alignment required for kernel
 0234/1 2.05+   relocatable_kernel Whether kernel is relocatable or not
 0235/1 2.10+   min_alignment   Minimum alignment, as a power of two
-0236/2 N/A     pad3            Unused
+0236/2 2.12+   xloadflags      Boot protocol option flags
 0238/4 2.06+   cmdline_size    Maximum size of the kernel command line
 023C/4 2.07+   hardware_subarch Hardware subarchitecture
 0240/8 2.07+   hardware_subarch_data Subarchitecture-specific data
@@ -582,6 +586,27 @@ Protocol:  2.10+
   misaligned kernel.  Therefore, a loader should typically try each
   power-of-two alignment from kernel_alignment down to this alignment.
 
+Field name:     xloadflags
+Type:           read
+Offset/size:    0x236/2
+Protocol:       2.12+
+
+  This field is a bitmask.
+
+  Bit 0 (read):        XLF_KERNEL_64
+       - If 1, this kernel has the legacy 64-bit entry point at 0x200.
+
+  Bit 1 (read): XLF_CAN_BE_LOADED_ABOVE_4G
+        - If 1, kernel/boot_params/cmdline/ramdisk can be above 4G.
+
+  Bit 2 (read):        XLF_EFI_HANDOVER_32
+       - If 1, the kernel supports the 32-bit EFI handoff entry point
+          given at handover_offset.
+
+  Bit 3 (read): XLF_EFI_HANDOVER_64
+       - If 1, the kernel supports the 64-bit EFI handoff entry point
+          given at handover_offset + 0x200.
+
 Field name:    cmdline_size
 Type:          read
 Offset/size:   0x238/4
index cf5437d..199f453 100644 (file)
@@ -19,6 +19,9 @@ Offset        Proto   Name            Meaning
 090/010        ALL     hd1_info        hd1 disk parameter, OBSOLETE!!
 0A0/010        ALL     sys_desc_table  System description table (struct sys_desc_table)
 0B0/010        ALL     olpc_ofw_header OLPC's OpenFirmware CIF and friends
+0C0/004        ALL     ext_ramdisk_image ramdisk_image high 32bits
+0C4/004        ALL     ext_ramdisk_size  ramdisk_size high 32bits
+0C8/004        ALL     ext_cmd_line_ptr  cmd_line_ptr high 32bits
 140/080        ALL     edid_info       Video mode setup (struct edid_info)
 1C0/020        ALL     efi_info        EFI 32 information (struct efi_info)
 1E0/004        ALL     alk_mem_k       Alternative mem check, in KB
@@ -27,6 +30,7 @@ Offset        Proto   Name            Meaning
 1E9/001        ALL     eddbuf_entries  Number of entries in eddbuf (below)
 1EA/001        ALL     edd_mbr_sig_buf_entries Number of entries in edd_mbr_sig_buffer
                                (below)
+1EF/001        ALL     sentinel        Used to detect broken bootloaders
 290/040        ALL     edd_mbr_sig_buffer EDD MBR signatures
 2D0/A00        ALL     e820_map        E820 memory map table
                                (array of struct e820entry)
index 3105c48..8ae709e 100644 (file)
@@ -6585,7 +6585,7 @@ F:        drivers/media/platform/s3c-camif/
 F:     include/media/s3c_camif.h
 
 SERIAL DRIVERS
-M:     Alan Cox <alan@linux.intel.com>
+M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 L:     linux-serial@vger.kernel.org
 S:     Maintained
 F:     drivers/tty/serial
index 253a455..2d3c92c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 8
 SUBLEVEL = 0
-EXTRAVERSION = -rc4
+EXTRAVERSION = -rc5
 NAME = Terrified Chipmunk
 
 # *DOCUMENTATION*
@@ -169,7 +169,7 @@ SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
                                  -e s/arm.*/arm/ -e s/sa110/arm/ \
                                  -e s/s390x/s390/ -e s/parisc64/parisc/ \
                                  -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
-                                 -e s/sh[234].*/sh/ )
+                                 -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ )
 
 # Cross compiling and selecting different set of gcc/bin-utils
 # ---------------------------------------------------------------------------
index 0004402..9b82fac 100644 (file)
@@ -26,7 +26,7 @@
 
        memory {
                device_type = "memory";
-               reg = <0x00000000 0x20000000>; /* 512 MB */
+               reg = <0x00000000 0x40000000>; /* 1 GB */
        };
 
        soc {
index 271855a..e041f42 100644 (file)
                };
 
                gpio0: gpio@d0018100 {
-                       compatible = "marvell,armadaxp-gpio";
-                       reg = <0xd0018100 0x40>,
-                           <0xd0018800 0x30>;
+                       compatible = "marvell,orion-gpio";
+                       reg = <0xd0018100 0x40>;
                        ngpios = <32>;
                        gpio-controller;
                        #gpio-cells = <2>;
                        interrupt-controller;
                        #interrupts-cells = <2>;
-                       interrupts = <16>, <17>, <18>, <19>;
+                       interrupts = <82>, <83>, <84>, <85>;
                };
 
                gpio1: gpio@d0018140 {
-                       compatible = "marvell,armadaxp-gpio";
-                       reg = <0xd0018140 0x40>,
-                           <0xd0018840 0x30>;
+                       compatible = "marvell,orion-gpio";
+                       reg = <0xd0018140 0x40>;
                        ngpios = <17>;
                        gpio-controller;
                        #gpio-cells = <2>;
                        interrupt-controller;
                        #interrupts-cells = <2>;
-                       interrupts = <20>, <21>, <22>;
+                       interrupts = <87>, <88>, <89>;
                };
        };
 };
index 1c1937d..9e23bd8 100644 (file)
                };
 
                gpio0: gpio@d0018100 {
-                       compatible = "marvell,armadaxp-gpio";
-                       reg = <0xd0018100 0x40>,
-                           <0xd0018800 0x30>;
+                       compatible = "marvell,orion-gpio";
+                       reg = <0xd0018100 0x40>;
                        ngpios = <32>;
                        gpio-controller;
                        #gpio-cells = <2>;
                        interrupt-controller;
                        #interrupts-cells = <2>;
-                       interrupts = <16>, <17>, <18>, <19>;
+                       interrupts = <82>, <83>, <84>, <85>;
                };
 
                gpio1: gpio@d0018140 {
-                       compatible = "marvell,armadaxp-gpio";
-                       reg = <0xd0018140 0x40>,
-                           <0xd0018840 0x30>;
+                       compatible = "marvell,orion-gpio";
+                       reg = <0xd0018140 0x40>;
                        ngpios = <32>;
                        gpio-controller;
                        #gpio-cells = <2>;
                        interrupt-controller;
                        #interrupts-cells = <2>;
-                       interrupts = <20>, <21>, <22>, <23>;
+                       interrupts = <87>, <88>, <89>, <90>;
                };
 
                gpio2: gpio@d0018180 {
-                       compatible = "marvell,armadaxp-gpio";
-                       reg = <0xd0018180 0x40>,
-                           <0xd0018870 0x30>;
+                       compatible = "marvell,orion-gpio";
+                       reg = <0xd0018180 0x40>;
                        ngpios = <3>;
                        gpio-controller;
                        #gpio-cells = <2>;
                        interrupt-controller;
                        #interrupts-cells = <2>;
-                       interrupts = <24>;
+                       interrupts = <91>;
                };
 
                ethernet@d0034000 {
index 4905cf3..9659661 100644 (file)
                };
 
                gpio0: gpio@d0018100 {
-                       compatible = "marvell,armadaxp-gpio";
-                       reg = <0xd0018100 0x40>,
-                           <0xd0018800 0x30>;
+                       compatible = "marvell,orion-gpio";
+                       reg = <0xd0018100 0x40>;
                        ngpios = <32>;
                        gpio-controller;
                        #gpio-cells = <2>;
                        interrupt-controller;
                        #interrupts-cells = <2>;
-                       interrupts = <16>, <17>, <18>, <19>;
+                       interrupts = <82>, <83>, <84>, <85>;
                };
 
                gpio1: gpio@d0018140 {
-                       compatible = "marvell,armadaxp-gpio";
-                       reg = <0xd0018140 0x40>,
-                           <0xd0018840 0x30>;
+                       compatible = "marvell,orion-gpio";
+                       reg = <0xd0018140 0x40>;
                        ngpios = <32>;
                        gpio-controller;
                        #gpio-cells = <2>;
                        interrupt-controller;
                        #interrupts-cells = <2>;
-                       interrupts = <20>, <21>, <22>, <23>;
+                       interrupts = <87>, <88>, <89>, <90>;
                };
 
                gpio2: gpio@d0018180 {
-                       compatible = "marvell,armadaxp-gpio";
-                       reg = <0xd0018180 0x40>,
-                           <0xd0018870 0x30>;
+                       compatible = "marvell,orion-gpio";
+                       reg = <0xd0018180 0x40>;
                        ngpios = <3>;
                        gpio-controller;
                        #gpio-cells = <2>;
                        interrupt-controller;
                        #interrupts-cells = <2>;
-                       interrupts = <24>;
+                       interrupts = <91>;
                };
 
                ethernet@d0034000 {
index e154f24..222047f 100644 (file)
 
        i2c@0 {
                compatible = "i2c-gpio";
-               gpios = <&pioA 23 0 /* sda */
-                        &pioA 24 0 /* scl */
+               gpios = <&pioA 25 0 /* sda */
+                        &pioA 26 0 /* scl */
                        >;
                i2c-gpio,sda-open-drain;
                i2c-gpio,scl-open-drain;
index 3a47cf9..8ecca69 100644 (file)
                                                atmel,pins =
                                                        <0 3 0x1 0x0>;  /* PA3 periph A */
                                        };
+
+                                       pinctrl_usart0_sck: usart0_sck-0 {
+                                               atmel,pins =
+                                                       <0 4 0x1 0x0>;  /* PA4 periph A */
+                                       };
                                };
 
                                usart1 {
 
                                        pinctrl_usart1_rts: usart1_rts-0 {
                                                atmel,pins =
-                                                       <3 27 0x3 0x0>; /* PC27 periph C */
+                                                       <2 27 0x3 0x0>; /* PC27 periph C */
                                        };
 
                                        pinctrl_usart1_cts: usart1_cts-0 {
                                                atmel,pins =
-                                                       <3 28 0x3 0x0>; /* PC28 periph C */
+                                                       <2 28 0x3 0x0>; /* PC28 periph C */
+                                       };
+
+                                       pinctrl_usart1_sck: usart1_sck-0 {
+                                               atmel,pins =
+                                                       <2 28 0x3 0x0>; /* PC29 periph C */
                                        };
                                };
 
 
                                        pinctrl_uart2_rts: uart2_rts-0 {
                                                atmel,pins =
-                                                       <0 0 0x2 0x0>;  /* PB0 periph B */
+                                                       <1 0 0x2 0x0>;  /* PB0 periph B */
                                        };
 
                                        pinctrl_uart2_cts: uart2_cts-0 {
                                                atmel,pins =
-                                                       <0 1 0x2 0x0>;  /* PB1 periph B */
+                                                       <1 1 0x2 0x0>;  /* PB1 periph B */
+                                       };
+
+                                       pinctrl_usart2_sck: usart2_sck-0 {
+                                               atmel,pins =
+                                                       <1 2 0x2 0x0>;  /* PB2 periph B */
                                        };
                                };
 
                                usart3 {
                                        pinctrl_uart3: usart3-0 {
                                                atmel,pins =
-                                                       <3 23 0x2 0x1   /* PC22 periph B with pullup */
-                                                        3 23 0x2 0x0>; /* PC23 periph B */
+                                                       <2 23 0x2 0x1   /* PC22 periph B with pullup */
+                                                        2 23 0x2 0x0>; /* PC23 periph B */
                                        };
 
                                        pinctrl_usart3_rts: usart3_rts-0 {
                                                atmel,pins =
-                                                       <3 24 0x2 0x0>; /* PC24 periph B */
+                                                       <2 24 0x2 0x0>; /* PC24 periph B */
                                        };
 
                                        pinctrl_usart3_cts: usart3_cts-0 {
                                                atmel,pins =
-                                                       <3 25 0x2 0x0>; /* PC25 periph B */
+                                                       <2 25 0x2 0x0>; /* PC25 periph B */
+                                       };
+
+                                       pinctrl_usart3_sck: usart3_sck-0 {
+                                               atmel,pins =
+                                                       <2 26 0x2 0x0>; /* PC26 periph B */
                                        };
                                };
 
                                uart0 {
                                        pinctrl_uart0: uart0-0 {
                                                atmel,pins =
-                                                       <3 8 0x3 0x0    /* PC8 periph C */
-                                                        3 9 0x3 0x1>;  /* PC9 periph C with pullup */
+                                                       <2 8 0x3 0x0    /* PC8 periph C */
+                                                        2 9 0x3 0x1>;  /* PC9 periph C with pullup */
                                        };
                                };
 
                                uart1 {
                                        pinctrl_uart1: uart1-0 {
                                                atmel,pins =
-                                                       <3 16 0x3 0x0   /* PC16 periph C */
-                                                        3 17 0x3 0x1>; /* PC17 periph C with pullup */
+                                                       <2 16 0x3 0x0   /* PC16 periph C */
+                                                        2 17 0x3 0x1>; /* PC17 periph C with pullup */
                                        };
                                };
 
 
                                        pinctrl_macb0_rmii_mii: macb0_rmii_mii-0 {
                                                atmel,pins =
-                                                       <1 8 0x1 0x0    /* PA8 periph A */
-                                                        1 11 0x1 0x0   /* PA11 periph A */
-                                                        1 12 0x1 0x0   /* PA12 periph A */
-                                                        1 13 0x1 0x0   /* PA13 periph A */
-                                                        1 14 0x1 0x0   /* PA14 periph A */
-                                                        1 15 0x1 0x0   /* PA15 periph A */
-                                                        1 16 0x1 0x0   /* PA16 periph A */
-                                                        1 17 0x1 0x0>; /* PA17 periph A */
+                                                       <1 8 0x1 0x0    /* PB8 periph A */
+                                                        1 11 0x1 0x0   /* PB11 periph A */
+                                                        1 12 0x1 0x0   /* PB12 periph A */
+                                                        1 13 0x1 0x0   /* PB13 periph A */
+                                                        1 14 0x1 0x0   /* PB14 periph A */
+                                                        1 15 0x1 0x0   /* PB15 periph A */
+                                                        1 16 0x1 0x0   /* PB16 periph A */
+                                                        1 17 0x1 0x0>; /* PB17 periph A */
                                        };
                                };
 
index fddd174..46c0980 100644 (file)
@@ -96,8 +96,8 @@
                fifo-depth = <0x80>;
                card-detect-delay = <200>;
                samsung,dw-mshc-ciu-div = <3>;
-               samsung,dw-mshc-sdr-timing = <2 3 3>;
-               samsung,dw-mshc-ddr-timing = <1 2 3>;
+               samsung,dw-mshc-sdr-timing = <2 3>;
+               samsung,dw-mshc-ddr-timing = <1 2>;
 
                slot@0 {
                        reg = <0>;
                fifo-depth = <0x80>;
                card-detect-delay = <200>;
                samsung,dw-mshc-ciu-div = <3>;
-               samsung,dw-mshc-sdr-timing = <2 3 3>;
-               samsung,dw-mshc-ddr-timing = <1 2 3>;
+               samsung,dw-mshc-sdr-timing = <2 3>;
+               samsung,dw-mshc-ddr-timing = <1 2>;
 
                slot@0 {
                        reg = <0>;
                fifo-depth = <0x80>;
                card-detect-delay = <200>;
                samsung,dw-mshc-ciu-div = <3>;
-               samsung,dw-mshc-sdr-timing = <2 3 3>;
-               samsung,dw-mshc-ddr-timing = <1 2 3>;
+               samsung,dw-mshc-sdr-timing = <2 3>;
+               samsung,dw-mshc-ddr-timing = <1 2>;
 
                slot@0 {
                        reg = <0>;
index fed7d3f..cdee96f 100644 (file)
 };
 
 &uart0 { status = "okay"; };
-&sdio0 { status = "okay"; };
 &sata0 { status = "okay"; };
 &i2c0 { status = "okay"; };
 
+&sdio0 {
+       status = "okay";
+       /* sdio0 card detect is connected to wrong pin on CuBox */
+       cd-gpios = <&gpio0 12 1>;
+};
+
 &spi0 {
        status = "okay";
 
 };
 
 &pinctrl {
-       pinctrl-0 = <&pmx_gpio_18>;
+       pinctrl-0 = <&pmx_gpio_12 &pmx_gpio_18>;
        pinctrl-names = "default";
 
+       pmx_gpio_12: pmx-gpio-12 {
+               marvell,pins = "mpp12";
+               marvell,function = "gpio";
+       };
+
        pmx_gpio_18: pmx-gpio-18 {
                marvell,pins = "mpp18";
                marvell,function = "gpio";
index 942d576..e05b18f 100644 (file)
                fifo-depth = <0x80>;
                card-detect-delay = <200>;
                samsung,dw-mshc-ciu-div = <3>;
-               samsung,dw-mshc-sdr-timing = <2 3 3>;
-               samsung,dw-mshc-ddr-timing = <1 2 3>;
+               samsung,dw-mshc-sdr-timing = <2 3>;
+               samsung,dw-mshc-ddr-timing = <1 2>;
 
                slot@0 {
                        reg = <0>;
                fifo-depth = <0x80>;
                card-detect-delay = <200>;
                samsung,dw-mshc-ciu-div = <3>;
-               samsung,dw-mshc-sdr-timing = <2 3 3>;
-               samsung,dw-mshc-ddr-timing = <1 2 3>;
+               samsung,dw-mshc-sdr-timing = <2 3>;
+               samsung,dw-mshc-ddr-timing = <1 2>;
 
                slot@0 {
                        reg = <0>;
index 9bc6785..77d21ab 100644 (file)
@@ -1,4 +1,5 @@
 /include/ "kirkwood.dtsi"
+/include/ "kirkwood-6281.dtsi"
 
 / {
        chosen {
@@ -6,6 +7,21 @@
        };
 
        ocp@f1000000 {
+               pinctrl: pinctrl@10000 {
+                       pinctrl-0 = < &pmx_spi &pmx_twsi0 &pmx_uart0
+                                       &pmx_ns2_sata0 &pmx_ns2_sata1>;
+                       pinctrl-names = "default";
+
+                       pmx_ns2_sata0: pmx-ns2-sata0 {
+                               marvell,pins = "mpp21";
+                               marvell,function = "sata0";
+                       };
+                       pmx_ns2_sata1: pmx-ns2-sata1 {
+                               marvell,pins = "mpp20";
+                               marvell,function = "sata1";
+                       };
+               };
+
                serial@12000 {
                        clock-frequency = <166666667>;
                        status = "okay";
index 110d6cb..d6ab442 100644 (file)
@@ -36,6 +36,7 @@
                        reg = <0x10100 0x40>;
                        ngpios = <32>;
                        interrupt-controller;
+                       #interrupt-cells = <2>;
                        interrupts = <35>, <36>, <37>, <38>;
                };
 
@@ -46,6 +47,7 @@
                        reg = <0x10140 0x40>;
                        ngpios = <18>;
                        interrupt-controller;
+                       #interrupt-cells = <2>;
                        interrupts = <39>, <40>, <41>;
                };
 
index e8814fe..b4dc3ed 100644 (file)
@@ -48,6 +48,8 @@
 
                        macb0: ethernet@fffc4000 {
                                phy-mode = "mii";
+                               pinctrl-0 = <&pinctrl_macb_rmii
+                                            &pinctrl_macb_rmii_mii_alt>;
                                status = "okay";
                        };
 
index 8bbc2bf..8b36abe 100644 (file)
                };
 
                uart0: uart@01c28000 {
-                       compatible = "ns8250";
+                       compatible = "snps,dw-apb-uart";
                        reg = <0x01c28000 0x400>;
                        interrupts = <1>;
                        reg-shift = <2>;
+                       reg-io-width = <4>;
                        clock-frequency = <24000000>;
                        status = "disabled";
                };
 
                uart1: uart@01c28400 {
-                       compatible = "ns8250";
+                       compatible = "snps,dw-apb-uart";
                        reg = <0x01c28400 0x400>;
                        interrupts = <2>;
                        reg-shift = <2>;
+                       reg-io-width = <4>;
                        clock-frequency = <24000000>;
                        status = "disabled";
                };
index 1fc405a..cf8071a 100644 (file)
@@ -45,7 +45,6 @@
                        reg = <1>;
                };
 
-/* A7s disabled till big.LITTLE patches are available...
                cpu2: cpu@2 {
                        device_type = "cpu";
                        compatible = "arm,cortex-a7";
@@ -63,7 +62,6 @@
                        compatible = "arm,cortex-a7";
                        reg = <0x102>;
                };
-*/
        };
 
        memory@80000000 {
index b175577..1ea9590 100644 (file)
@@ -19,6 +19,7 @@ CONFIG_SOC_AT91SAM9260=y
 CONFIG_SOC_AT91SAM9263=y
 CONFIG_SOC_AT91SAM9G45=y
 CONFIG_SOC_AT91SAM9X5=y
+CONFIG_SOC_AT91SAM9N12=y
 CONFIG_MACH_AT91SAM_DT=y
 CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
 CONFIG_AT91_TIMER_HZ=128
@@ -31,7 +32,7 @@ CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_ARM_APPENDED_DTB=y
 CONFIG_ARM_ATAG_DTB_COMPAT=y
-CONFIG_CMDLINE="mem=128M console=ttyS0,115200 initrd=0x21100000,25165824 root=/dev/ram0 rw"
+CONFIG_CMDLINE="console=ttyS0,115200 initrd=0x21100000,25165824 root=/dev/ram0 rw"
 CONFIG_KEXEC=y
 CONFIG_AUTO_ZRELADDR=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
index 6809200..14f7c3b 100644 (file)
@@ -100,12 +100,14 @@ ENTRY(printch)
                b       1b
 ENDPROC(printch)
 
+#ifdef CONFIG_MMU
 ENTRY(debug_ll_addr)
                addruart r2, r3, ip
                str     r2, [r0]
                str     r3, [r1]
                mov     pc, lr
 ENDPROC(debug_ll_addr)
+#endif
 
 #else
 
index 4eee351..486a15a 100644 (file)
@@ -246,6 +246,7 @@ __create_page_tables:
 
        /*
         * Then map boot params address in r2 if specified.
+        * We map 2 sections in case the ATAGs/DTB crosses a section boundary.
         */
        mov     r0, r2, lsr #SECTION_SHIFT
        movs    r0, r0, lsl #SECTION_SHIFT
@@ -253,6 +254,8 @@ __create_page_tables:
        addne   r3, r3, #PAGE_OFFSET
        addne   r3, r4, r3, lsr #(SECTION_SHIFT - PMD_ORDER)
        orrne   r6, r7, r0
+       strne   r6, [r3], #1 << PMD_ORDER
+       addne   r6, r6, #1 << SECTION_SHIFT
        strne   r6, [r3]
 
 #ifdef CONFIG_DEBUG_LL
@@ -331,7 +334,7 @@ ENTRY(secondary_startup)
         * as it has already been validated by the primary processor.
         */
 #ifdef CONFIG_ARM_VIRT_EXT
-       bl      __hyp_stub_install
+       bl      __hyp_stub_install_secondary
 #endif
        safe_svcmode_maskall r9
 
index 65b2417..1315c4c 100644 (file)
@@ -99,7 +99,7 @@ ENTRY(__hyp_stub_install_secondary)
         * immediately.
         */
        compare_cpu_mode_with_primary   r4, r5, r6, r7
-       bxne    lr
+       movne   pc, lr
 
        /*
         * Once we have given up on one CPU, we do not try to install the
@@ -111,7 +111,7 @@ ENTRY(__hyp_stub_install_secondary)
         */
 
        cmp     r4, #HYP_MODE
-       bxne    lr                      @ give up if the CPU is not in HYP mode
+       movne   pc, lr                  @ give up if the CPU is not in HYP mode
 
 /*
  * Configure HSCTLR to set correct exception endianness/instruction set
@@ -120,7 +120,8 @@ ENTRY(__hyp_stub_install_secondary)
  * Eventually, CPU-specific code might be needed -- assume not for now
  *
  * This code relies on the "eret" instruction to synchronize the
- * various coprocessor accesses.
+ * various coprocessor accesses. This is done when we switch to SVC
+ * (see safe_svcmode_maskall).
  */
        @ Now install the hypervisor stub:
        adr     r7, __hyp_stub_vectors
@@ -155,14 +156,7 @@ THUMB(     orr     r7, #(1 << 30)  )       @ HSCTLR.TE
 1:
 #endif
 
-       bic     r7, r4, #MODE_MASK
-       orr     r7, r7, #SVC_MODE
-THUMB( orr     r7, r7, #PSR_T_BIT      )
-       msr     spsr_cxsf, r7           @ This is SPSR_hyp.
-
-       __MSR_ELR_HYP(14)               @ msr elr_hyp, lr
-       __ERET                          @ return, switching to SVC mode
-                                       @ The boot CPU mode is left in r4.
+       bx      lr                      @ The boot CPU mode is left in r4.
 ENDPROC(__hyp_stub_install_secondary)
 
 __hyp_stub_do_trap:
@@ -200,7 +194,7 @@ ENDPROC(__hyp_get_vectors)
        @ fall through
 ENTRY(__hyp_set_vectors)
        __HVC(0)
-       bx      lr
+       mov     pc, lr
 ENDPROC(__hyp_set_vectors)
 
 #ifndef ZIMAGE
index 9ee866c..4b67847 100644 (file)
@@ -105,6 +105,8 @@ static void __init soc_detect(u32 dbgu_base)
        switch (socid) {
        case ARCH_ID_AT91RM9200:
                at91_soc_initdata.type = AT91_SOC_RM9200;
+               if (at91_soc_initdata.subtype == AT91_SOC_SUBTYPE_NONE)
+                       at91_soc_initdata.subtype = AT91_SOC_RM9200_BGA;
                at91_boot_soc = at91rm9200_soc;
                break;
 
index 3e628fd..0a2349d 100644 (file)
@@ -851,6 +851,7 @@ config SOC_IMX6Q
        select HAVE_CAN_FLEXCAN if CAN
        select HAVE_IMX_GPC
        select HAVE_IMX_MMDC
+       select HAVE_IMX_SRC
        select HAVE_SMP
        select MFD_SYSCON
        select PINCTRL
index b197aa7..2c570cd 100644 (file)
@@ -254,9 +254,9 @@ int __init mx25_clocks_init(void)
        clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.2");
        clk_register_clkdev(clk[usbotg_ahb], "ahb", "mxc-ehci.2");
        clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.2");
-       clk_register_clkdev(clk[ipg], "ipg", "fsl-usb2-udc");
-       clk_register_clkdev(clk[usbotg_ahb], "ahb", "fsl-usb2-udc");
-       clk_register_clkdev(clk[usb_div], "per", "fsl-usb2-udc");
+       clk_register_clkdev(clk[ipg], "ipg", "imx-udc-mx27");
+       clk_register_clkdev(clk[usbotg_ahb], "ahb", "imx-udc-mx27");
+       clk_register_clkdev(clk[usb_div], "per", "imx-udc-mx27");
        clk_register_clkdev(clk[nfc_ipg_per], NULL, "imx25-nand.0");
        /* i.mx25 has the i.mx35 type cspi */
        clk_register_clkdev(clk[cspi1_ipg], NULL, "imx35-cspi.0");
index 4c1d1e4..1ffe3b5 100644 (file)
@@ -236,9 +236,9 @@ int __init mx27_clocks_init(unsigned long fref)
        clk_register_clkdev(clk[lcdc_ahb_gate], "ahb", "imx21-fb.0");
        clk_register_clkdev(clk[csi_ahb_gate], "ahb", "imx27-camera.0");
        clk_register_clkdev(clk[per4_gate], "per", "imx27-camera.0");
-       clk_register_clkdev(clk[usb_div], "per", "fsl-usb2-udc");
-       clk_register_clkdev(clk[usb_ipg_gate], "ipg", "fsl-usb2-udc");
-       clk_register_clkdev(clk[usb_ahb_gate], "ahb", "fsl-usb2-udc");
+       clk_register_clkdev(clk[usb_div], "per", "imx-udc-mx27");
+       clk_register_clkdev(clk[usb_ipg_gate], "ipg", "imx-udc-mx27");
+       clk_register_clkdev(clk[usb_ahb_gate], "ahb", "imx-udc-mx27");
        clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.0");
        clk_register_clkdev(clk[usb_ipg_gate], "ipg", "mxc-ehci.0");
        clk_register_clkdev(clk[usb_ahb_gate], "ahb", "mxc-ehci.0");
index 8be64e0..16ccbd4 100644 (file)
@@ -139,9 +139,9 @@ int __init mx31_clocks_init(unsigned long fref)
        clk_register_clkdev(clk[usb_div_post], "per", "mxc-ehci.2");
        clk_register_clkdev(clk[usb_gate], "ahb", "mxc-ehci.2");
        clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.2");
-       clk_register_clkdev(clk[usb_div_post], "per", "fsl-usb2-udc");
-       clk_register_clkdev(clk[usb_gate], "ahb", "fsl-usb2-udc");
-       clk_register_clkdev(clk[ipg], "ipg", "fsl-usb2-udc");
+       clk_register_clkdev(clk[usb_div_post], "per", "imx-udc-mx27");
+       clk_register_clkdev(clk[usb_gate], "ahb", "imx-udc-mx27");
+       clk_register_clkdev(clk[ipg], "ipg", "imx-udc-mx27");
        clk_register_clkdev(clk[csi_gate], NULL, "mx3-camera.0");
        /* i.mx31 has the i.mx21 type uart */
        clk_register_clkdev(clk[uart1_gate], "per", "imx21-uart.0");
index 66f3d65..f0727e8 100644 (file)
@@ -251,9 +251,9 @@ int __init mx35_clocks_init()
        clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.2");
        clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.2");
        clk_register_clkdev(clk[usbotg_gate], "ahb", "mxc-ehci.2");
-       clk_register_clkdev(clk[usb_div], "per", "fsl-usb2-udc");
-       clk_register_clkdev(clk[ipg], "ipg", "fsl-usb2-udc");
-       clk_register_clkdev(clk[usbotg_gate], "ahb", "fsl-usb2-udc");
+       clk_register_clkdev(clk[usb_div], "per", "imx-udc-mx27");
+       clk_register_clkdev(clk[ipg], "ipg", "imx-udc-mx27");
+       clk_register_clkdev(clk[usbotg_gate], "ahb", "imx-udc-mx27");
        clk_register_clkdev(clk[wdog_gate], NULL, "imx2-wdt.0");
        clk_register_clkdev(clk[nfc_div], NULL, "imx25-nand.0");
        clk_register_clkdev(clk[csi_gate], NULL, "mx3-camera.0");
index 579023f..fb7cb84 100644 (file)
@@ -269,9 +269,9 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil,
        clk_register_clkdev(clk[usboh3_per_gate], "per", "mxc-ehci.2");
        clk_register_clkdev(clk[usboh3_gate], "ipg", "mxc-ehci.2");
        clk_register_clkdev(clk[usboh3_gate], "ahb", "mxc-ehci.2");
-       clk_register_clkdev(clk[usboh3_per_gate], "per", "fsl-usb2-udc");
-       clk_register_clkdev(clk[usboh3_gate], "ipg", "fsl-usb2-udc");
-       clk_register_clkdev(clk[usboh3_gate], "ahb", "fsl-usb2-udc");
+       clk_register_clkdev(clk[usboh3_per_gate], "per", "imx-udc-mx51");
+       clk_register_clkdev(clk[usboh3_gate], "ipg", "imx-udc-mx51");
+       clk_register_clkdev(clk[usboh3_gate], "ahb", "imx-udc-mx51");
        clk_register_clkdev(clk[nfc_gate], NULL, "imx51-nand");
        clk_register_clkdev(clk[ssi1_ipg_gate], NULL, "imx-ssi.0");
        clk_register_clkdev(clk[ssi2_ipg_gate], NULL, "imx-ssi.1");
index 7f2c10c..c0c4e72 100644 (file)
@@ -436,6 +436,9 @@ int __init mx6q_clocks_init(void)
        for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
                clk_prepare_enable(clk[clks_init_on[i]]);
 
+       /* Set initial power mode */
+       imx6q_set_lpm(WAIT_CLOCKED);
+
        np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt");
        base = of_iomap(np, 0);
        WARN_ON(!base);
index 7191ab4..fa36fb8 100644 (file)
@@ -142,6 +142,7 @@ extern int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode);
 extern void imx6q_clock_map_io(void);
 
 extern void imx_cpu_die(unsigned int cpu);
+extern int imx_cpu_kill(unsigned int cpu);
 
 #ifdef CONFIG_PM
 extern void imx6q_pm_init(void);
index 6277baf..9bd5777 100644 (file)
@@ -63,6 +63,7 @@ struct platform_device *__init imx_add_flexcan(
 
 #include <linux/fsl_devices.h>
 struct imx_fsl_usb2_udc_data {
+       const char *devid;
        resource_size_t iobase;
        resource_size_t irq;
 };
index 37e4439..3c06bd9 100644 (file)
 #include "../hardware.h"
 #include "devices-common.h"
 
-#define imx_fsl_usb2_udc_data_entry_single(soc)                                \
+#define imx_fsl_usb2_udc_data_entry_single(soc, _devid)                        \
        {                                                               \
+               .devid = _devid,                                        \
                .iobase = soc ## _USB_OTG_BASE_ADDR,                    \
                .irq = soc ## _INT_USB_OTG,                             \
        }
 
 #ifdef CONFIG_SOC_IMX25
 const struct imx_fsl_usb2_udc_data imx25_fsl_usb2_udc_data __initconst =
-       imx_fsl_usb2_udc_data_entry_single(MX25);
+       imx_fsl_usb2_udc_data_entry_single(MX25, "imx-udc-mx27");
 #endif /* ifdef CONFIG_SOC_IMX25 */
 
 #ifdef CONFIG_SOC_IMX27
 const struct imx_fsl_usb2_udc_data imx27_fsl_usb2_udc_data __initconst =
-       imx_fsl_usb2_udc_data_entry_single(MX27);
+       imx_fsl_usb2_udc_data_entry_single(MX27, "imx-udc-mx27");
 #endif /* ifdef CONFIG_SOC_IMX27 */
 
 #ifdef CONFIG_SOC_IMX31
 const struct imx_fsl_usb2_udc_data imx31_fsl_usb2_udc_data __initconst =
-       imx_fsl_usb2_udc_data_entry_single(MX31);
+       imx_fsl_usb2_udc_data_entry_single(MX31, "imx-udc-mx27");
 #endif /* ifdef CONFIG_SOC_IMX31 */
 
 #ifdef CONFIG_SOC_IMX35
 const struct imx_fsl_usb2_udc_data imx35_fsl_usb2_udc_data __initconst =
-       imx_fsl_usb2_udc_data_entry_single(MX35);
+       imx_fsl_usb2_udc_data_entry_single(MX35, "imx-udc-mx27");
 #endif /* ifdef CONFIG_SOC_IMX35 */
 
 #ifdef CONFIG_SOC_IMX51
 const struct imx_fsl_usb2_udc_data imx51_fsl_usb2_udc_data __initconst =
-       imx_fsl_usb2_udc_data_entry_single(MX51);
+       imx_fsl_usb2_udc_data_entry_single(MX51, "imx-udc-mx51");
 #endif
 
 struct platform_device *__init imx_add_fsl_usb2_udc(
@@ -57,7 +58,7 @@ struct platform_device *__init imx_add_fsl_usb2_udc(
                        .flags = IORESOURCE_IRQ,
                },
        };
-       return imx_add_platform_device_dmamask("fsl-usb2-udc", -1,
+       return imx_add_platform_device_dmamask(data->devid, -1,
                        res, ARRAY_SIZE(res),
                        pdata, sizeof(*pdata), DMA_BIT_MASK(32));
 }
index 10b0ed3..25a47c6 100644 (file)
@@ -54,7 +54,7 @@ struct platform_device *__init imx_add_imx_fb(
                        .flags = IORESOURCE_IRQ,
                },
        };
-       return imx_add_platform_device_dmamask("imx-fb", 0,
+       return imx_add_platform_device_dmamask(data->devid, 0,
                        res, ARRAY_SIZE(res),
                        pdata, sizeof(*pdata), DMA_BIT_MASK(32));
 }
index 3dec962..7bc5fe1 100644 (file)
@@ -46,9 +46,11 @@ static inline void cpu_enter_lowpower(void)
 void imx_cpu_die(unsigned int cpu)
 {
        cpu_enter_lowpower();
-       imx_enable_cpu(cpu, false);
+       cpu_do_idle();
+}
 
-       /* spin here until hardware takes it down */
-       while (1)
-               ;
+int imx_cpu_kill(unsigned int cpu)
+{
+       imx_enable_cpu(cpu, false);
+       return 1;
 }
index 6c80424..e05cf40 100644 (file)
@@ -22,8 +22,7 @@
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/genalloc.h>
-
-#include "iram.h"
+#include "linux/platform_data/imx-iram.h"
 
 static unsigned long iram_phys_base;
 static void __iomem *iram_virt_base;
index 3777b80..66fae88 100644 (file)
@@ -92,5 +92,6 @@ struct smp_operations  imx_smp_ops __initdata = {
        .smp_boot_secondary     = imx_boot_secondary,
 #ifdef CONFIG_HOTPLUG_CPU
        .cpu_die                = imx_cpu_die,
+       .cpu_kill               = imx_cpu_kill,
 #endif
 };
index a17543d..ee42d20 100644 (file)
@@ -41,6 +41,7 @@ static int imx6q_pm_enter(suspend_state_t state)
                cpu_suspend(0, imx6q_suspend_finish);
                imx_smp_prepare();
                imx_gpc_post_resume();
+               imx6q_set_lpm(WAIT_CLOCKED);
                break;
        default:
                return -EINVAL;
index be50e79..e7fcea7 100644 (file)
@@ -475,13 +475,12 @@ int __init pci_v3_setup(int nr, struct pci_sys_data *sys)
 {
        int ret = 0;
 
+       if (!ap_syscon_base)
+               return -EINVAL;
+
        if (nr == 0) {
                sys->mem_offset = PHYS_PCI_MEM_BASE;
                ret = pci_v3_setup_resources(sys);
-               /* Remap the Integrator system controller */
-               ap_syscon_base = ioremap(INTEGRATOR_SC_BASE, 0x100);
-               if (!ap_syscon_base)
-                       return -EINVAL;
        }
 
        return ret;
@@ -497,6 +496,13 @@ void __init pci_v3_preinit(void)
        unsigned int temp;
        int ret;
 
+       /* Remap the Integrator system controller */
+       ap_syscon_base = ioremap(INTEGRATOR_SC_BASE, 0x100);
+       if (!ap_syscon_base) {
+               pr_err("unable to remap the AP syscon for PCIv3\n");
+               return;
+       }
+
        pcibios_min_mem = 0x00100000;
 
        /*
index 8821720..f4632a8 100644 (file)
 #include <linux/gpio.h>
 #include <linux/of.h>
 #include "common.h"
-#include "mpp.h"
 
 static struct mv643xx_eth_platform_data ns2_ge00_data = {
        .phy_addr       = MV643XX_ETH_PHY_ADDR(8),
 };
 
-static unsigned int ns2_mpp_config[] __initdata = {
-       MPP0_SPI_SCn,
-       MPP1_SPI_MOSI,
-       MPP2_SPI_SCK,
-       MPP3_SPI_MISO,
-       MPP4_NF_IO6,
-       MPP5_NF_IO7,
-       MPP6_SYSRST_OUTn,
-       MPP7_GPO,               /* Fan speed (bit 1) */
-       MPP8_TW0_SDA,
-       MPP9_TW0_SCK,
-       MPP10_UART0_TXD,
-       MPP11_UART0_RXD,
-       MPP12_GPO,              /* Red led */
-       MPP14_GPIO,             /* USB fuse */
-       MPP16_GPIO,             /* SATA 0 power */
-       MPP17_GPIO,             /* SATA 1 power */
-       MPP18_NF_IO0,
-       MPP19_NF_IO1,
-       MPP20_SATA1_ACTn,
-       MPP21_SATA0_ACTn,
-       MPP22_GPIO,             /* Fan speed (bit 0) */
-       MPP23_GPIO,             /* Fan power */
-       MPP24_GPIO,             /* USB mode select */
-       MPP25_GPIO,             /* Fan rotation fail */
-       MPP26_GPIO,             /* USB device vbus */
-       MPP28_GPIO,             /* USB enable host vbus */
-       MPP29_GPIO,             /* Blue led (slow register) */
-       MPP30_GPIO,             /* Blue led (command register) */
-       MPP31_GPIO,             /* Board power off */
-       MPP32_GPIO,             /* Power button (0 = Released, 1 = Pushed) */
-       MPP33_GPO,              /* Fan speed (bit 2) */
-       0
-};
-
 #define NS2_GPIO_POWER_OFF     31
 
 static void ns2_power_off(void)
@@ -71,8 +35,6 @@ void __init ns2_init(void)
        /*
         * Basic setup. Needs to be called early.
         */
-       kirkwood_mpp_conf(ns2_mpp_config);
-
        if (of_machine_is_compatible("lacie,netspace_lite_v2") ||
            of_machine_is_compatible("lacie,netspace_mini_v2"))
                ns2_ge00_data.phy_addr = MV643XX_ETH_PHY_ADDR(0);
index 5dcb369..99df4df 100644 (file)
@@ -1,6 +1,8 @@
 ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \
        -I$(srctree)/arch/arm/plat-orion/include
 
+AFLAGS_coherency_ll.o          := -Wa,-march=armv7-a
+
 obj-y += system-controller.o
 obj-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-xp.o irq-armada-370-xp.o addr-map.o coherency.o coherency_ll.o pmsu.o
 obj-$(CONFIG_SMP)                += platsmp.o headsmp.o
index 5c8e9ce..769c1fe 100644 (file)
@@ -397,6 +397,12 @@ static struct omap_board_mux board_mux[] __initdata = {
                  OMAP_PULL_ENA),
        OMAP4_MUX(ABE_MCBSP1_FSX, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
 
+       /* UART2 - BT/FM/GPS shared transport */
+       OMAP4_MUX(UART2_CTS,    OMAP_PIN_INPUT  | OMAP_MUX_MODE0),
+       OMAP4_MUX(UART2_RTS,    OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
+       OMAP4_MUX(UART2_RX,     OMAP_PIN_INPUT  | OMAP_MUX_MODE0),
+       OMAP4_MUX(UART2_TX,     OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
+
        { .reg_offset = OMAP_MUX_TERMINATOR },
 };
 
index 7e5febe..ab7e952 100644 (file)
@@ -1935,6 +1935,8 @@ int __init omap2420_clk_init(void)
                        omap2_init_clk_hw_omap_clocks(c->lk.clk);
        }
 
+       omap2xxx_clkt_vps_late_init();
+
        omap2_clk_disable_autoidle_all();
 
        omap2_clk_enable_init_clocks(enable_init_clks,
index eda079b..eb3dab6 100644 (file)
@@ -2050,6 +2050,8 @@ int __init omap2430_clk_init(void)
                        omap2_init_clk_hw_omap_clocks(c->lk.clk);
        }
 
+       omap2xxx_clkt_vps_late_init();
+
        omap2_clk_disable_autoidle_all();
 
        omap2_clk_enable_init_clocks(enable_init_clks,
index 5789a5e..a2cc046 100644 (file)
@@ -2026,14 +2026,13 @@ int __init omap4xxx_clk_init(void)
         * On OMAP4460 the ABE DPLL fails to turn on if in idle low-power
         * state when turning the ABE clock domain. Workaround this by
         * locking the ABE DPLL on boot.
+        * Lock the ABE DPLL in any case to avoid issues with audio.
         */
-       if (cpu_is_omap446x()) {
-               rc = clk_set_parent(&abe_dpll_refclk_mux_ck, &sys_32k_ck);
-               if (!rc)
-                       rc = clk_set_rate(&dpll_abe_ck, OMAP4_DPLL_ABE_DEFFREQ);
-               if (rc)
-                       pr_err("%s: failed to configure ABE DPLL!\n", __func__);
-       }
+       rc = clk_set_parent(&abe_dpll_refclk_mux_ck, &sys_32k_ck);
+       if (!rc)
+               rc = clk_set_rate(&dpll_abe_ck, OMAP4_DPLL_ABE_DEFFREQ);
+       if (rc)
+               pr_err("%s: failed to configure ABE DPLL!\n", __func__);
 
        return 0;
 }
index 5e304d0..626f3ea 100644 (file)
@@ -639,7 +639,7 @@ static int count_ocp2scp_devices(struct omap_ocp2scp_dev *ocp2scp_dev)
        return cnt;
 }
 
-static void omap_init_ocp2scp(void)
+static void __init omap_init_ocp2scp(void)
 {
        struct omap_hwmod       *oh;
        struct platform_device  *pdev;
index 4c7566c..2a2cfa8 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/platform_data/omap_drm.h>
 
+#include "soc.h"
 #include "omap_device.h"
 #include "omap_hwmod.h"
 
@@ -56,7 +57,7 @@ static int __init omap_init_drm(void)
                        oh->name);
        }
 
-       platform_data.omaprev = GET_OMAP_REVISION();
+       platform_data.omaprev = GET_OMAP_TYPE;
 
        return platform_device_register(&omap_drm_device);
 
index 129d508..793f54a 100644 (file)
@@ -2132,8 +2132,12 @@ static struct omap_hwmod omap44xx_mcpdm_hwmod = {
         * currently reset very early during boot, before I2C is
         * available, so it doesn't seem that we have any choice in
         * the kernel other than to avoid resetting it.
+        *
+        * Also, McPDM needs to be configured to NO_IDLE mode when it
+        * is in used otherwise vital clocks will be gated which
+        * results 'slow motion' audio playback.
         */
-       .flags          = HWMOD_EXT_OPT_MAIN_CLK,
+       .flags          = HWMOD_EXT_OPT_MAIN_CLK | HWMOD_SWSUP_SIDLE,
        .mpu_irqs       = omap44xx_mcpdm_irqs,
        .sdma_reqs      = omap44xx_mcpdm_sdma_reqs,
        .main_clk       = "mcpdm_fck",
index 691aa67..b8ad6e6 100644 (file)
@@ -165,15 +165,11 @@ static struct device_node * __init omap_get_timer_dt(struct of_device_id *match,
        struct device_node *np;
 
        for_each_matching_node(np, match) {
-               if (!of_device_is_available(np)) {
-                       of_node_put(np);
+               if (!of_device_is_available(np))
                        continue;
-               }
 
-               if (property && !of_get_property(np, property, NULL)) {
-                       of_node_put(np);
+               if (property && !of_get_property(np, property, NULL))
                        continue;
-               }
 
                of_add_property(np, &device_disabled);
                return np;
index 553059f..755c0bb 100644 (file)
@@ -47,7 +47,7 @@ static struct spi_board_info wm1253_devs[] = {
                .bus_num        = 0,
                .chip_select    = 0,
                .mode           = SPI_MODE_0,
-               .irq            = S3C_EINT(5),
+               .irq            = S3C_EINT(4),
                .controller_data = &wm0010_spi_csinfo,
                .platform_data = &wm0010_pdata,
        },
index 7feb426..d2e1a16 100644 (file)
@@ -338,8 +338,10 @@ int __init s3c64xx_pm_init(void)
        for (i = 0; i < ARRAY_SIZE(s3c64xx_pm_domains); i++)
                pm_genpd_init(&s3c64xx_pm_domains[i]->pd, NULL, false);
 
+#ifdef CONFIG_S3C_DEV_FB
        if (dev_get_platdata(&s3c_device_fb.dev))
                pm_genpd_add_device(&s3c64xx_pm_f.pd, &s3c_device_fb.dev);
+#endif
 
        return 0;
 }
index 6b2fb87..076c26d 100644 (file)
@@ -774,25 +774,27 @@ static void dma_cache_maint_page(struct page *page, unsigned long offset,
        size_t size, enum dma_data_direction dir,
        void (*op)(const void *, size_t, int))
 {
+       unsigned long pfn;
+       size_t left = size;
+
+       pfn = page_to_pfn(page) + offset / PAGE_SIZE;
+       offset %= PAGE_SIZE;
+
        /*
         * A single sg entry may refer to multiple physically contiguous
         * pages.  But we still need to process highmem pages individually.
         * If highmem is not configured then the bulk of this loop gets
         * optimized out.
         */
-       size_t left = size;
        do {
                size_t len = left;
                void *vaddr;
 
+               page = pfn_to_page(pfn);
+
                if (PageHighMem(page)) {
-                       if (len + offset > PAGE_SIZE) {
-                               if (offset >= PAGE_SIZE) {
-                                       page += offset / PAGE_SIZE;
-                                       offset %= PAGE_SIZE;
-                               }
+                       if (len + offset > PAGE_SIZE)
                                len = PAGE_SIZE - offset;
-                       }
                        vaddr = kmap_high_get(page);
                        if (vaddr) {
                                vaddr += offset;
@@ -809,7 +811,7 @@ static void dma_cache_maint_page(struct page *page, unsigned long offset,
                        op(vaddr, len, dir);
                }
                offset = 0;
-               page++;
+               pfn++;
                left -= len;
        } while (left);
 }
index 9f06102..ce328c7 100644 (file)
@@ -283,7 +283,7 @@ static struct mem_type mem_types[] = {
        },
        [MT_MEMORY_SO] = {
                .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
-                               L_PTE_MT_UNCACHED,
+                               L_PTE_MT_UNCACHED | L_PTE_XN,
                .prot_l1   = PMD_TYPE_TABLE,
                .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_S |
                                PMD_SECT_UNCACHED | PMD_SECT_XN,
index dd703ef..b178d44 100644 (file)
@@ -20,7 +20,7 @@
  */
 ENTRY(versatile_secondary_startup)
        mrc     p15, 0, r0, c0, c0, 5
-       and     r0, r0, #15
+       bic     r0, #0xff000000
        adr     r4, 1f
        ldmia   r4, {r5, r6}
        sub     r4, r4, r5
index cc926c9..323ce1a 100644 (file)
@@ -22,7 +22,7 @@
 @  IRQs disabled.
 @
 ENTRY(do_vfp)
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPT_COUNT
        ldr     r4, [r10, #TI_PREEMPT]  @ get preempt count
        add     r11, r4, #1             @ increment it
        str     r11, [r10, #TI_PREEMPT]
@@ -35,7 +35,7 @@ ENTRY(do_vfp)
 ENDPROC(do_vfp)
 
 ENTRY(vfp_null_entry)
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPT_COUNT
        get_thread_info r10
        ldr     r4, [r10, #TI_PREEMPT]  @ get preempt count
        sub     r11, r4, #1             @ decrement it
@@ -53,7 +53,7 @@ ENDPROC(vfp_null_entry)
 
        __INIT
 ENTRY(vfp_testing_entry)
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPT_COUNT
        get_thread_info r10
        ldr     r4, [r10, #TI_PREEMPT]  @ get preempt count
        sub     r11, r4, #1             @ decrement it
index ea0349f..dd5e56f 100644 (file)
@@ -168,7 +168,7 @@ vfp_hw_state_valid:
                                        @ else it's one 32-bit instruction, so
                                        @ always subtract 4 from the following
                                        @ instruction address.
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPT_COUNT
        get_thread_info r10
        ldr     r4, [r10, #TI_PREEMPT]  @ get preempt count
        sub     r11, r4, #1             @ decrement it
@@ -192,7 +192,7 @@ look_for_VFP_exceptions:
        @ not recognised by VFP
 
        DBGSTR  "not VFP"
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPT_COUNT
        get_thread_info r10
        ldr     r4, [r10, #TI_PREEMPT]  @ get preempt count
        sub     r11, r4, #1             @ decrement it
index 07fea29..fe32c0e 100644 (file)
 
 typedef unsigned long elf_greg_t;
 
-#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t))
+#define ELF_NGREG (sizeof(struct user_pt_regs) / sizeof(elf_greg_t))
+#define ELF_CORE_COPY_REGS(dest, regs) \
+       *(struct user_pt_regs *)&(dest) = (regs)->user_regs;
+
 typedef elf_greg_t elf_gregset_t[ELF_NGREG];
 typedef struct user_fpsimd_state elf_fpregset_t;
 
index 4265ff6..b7a5fff 100644 (file)
@@ -672,33 +672,6 @@ ptrace_attach_sync_user_rbs (struct task_struct *child)
        read_unlock(&tasklist_lock);
 }
 
-static inline int
-thread_matches (struct task_struct *thread, unsigned long addr)
-{
-       unsigned long thread_rbs_end;
-       struct pt_regs *thread_regs;
-
-       if (ptrace_check_attach(thread, 0) < 0)
-               /*
-                * If the thread is not in an attachable state, we'll
-                * ignore it.  The net effect is that if ADDR happens
-                * to overlap with the portion of the thread's
-                * register backing store that is currently residing
-                * on the thread's kernel stack, then ptrace() may end
-                * up accessing a stale value.  But if the thread
-                * isn't stopped, that's a problem anyhow, so we're
-                * doing as well as we can...
-                */
-               return 0;
-
-       thread_regs = task_pt_regs(thread);
-       thread_rbs_end = ia64_get_user_rbs_end(thread, thread_regs, NULL);
-       if (!on_kernel_rbs(addr, thread_regs->ar_bspstore, thread_rbs_end))
-               return 0;
-
-       return 1;       /* looks like we've got a winner */
-}
-
 /*
  * Write f32-f127 back to task->thread.fph if it has been modified.
  */
index 17f7a45..3e6b844 100644 (file)
@@ -21,6 +21,22 @@ extern void *dma_alloc_coherent(struct device *, size_t,
 extern void dma_free_coherent(struct device *, size_t,
                              void *, dma_addr_t);
 
+static inline void *dma_alloc_attrs(struct device *dev, size_t size,
+                                   dma_addr_t *dma_handle, gfp_t flag,
+                                   struct dma_attrs *attrs)
+{
+       /* attrs is not supported and ignored */
+       return dma_alloc_coherent(dev, size, dma_handle, flag);
+}
+
+static inline void dma_free_attrs(struct device *dev, size_t size,
+                                 void *cpu_addr, dma_addr_t dma_handle,
+                                 struct dma_attrs *attrs)
+{
+       /* attrs is not supported and ignored */
+       dma_free_coherent(dev, size, cpu_addr, dma_handle);
+}
+
 static inline void *dma_alloc_noncoherent(struct device *dev, size_t size,
                                          dma_addr_t *handle, gfp_t flag)
 {
index bf86b29..037028f 100644 (file)
@@ -64,6 +64,8 @@ extern unsigned int kobjsize(const void *objp);
  */
 #define        VMALLOC_START   0
 #define        VMALLOC_END     0xffffffff
+#define        KMAP_START      0
+#define        KMAP_END        0xffffffff
 
 #include <asm-generic/pgtable.h>
 
index 847994c..f9337f6 100644 (file)
@@ -4,7 +4,7 @@
 #include <uapi/asm/unistd.h>
 
 
-#define NR_syscalls            348
+#define NR_syscalls            349
 
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
index b94bfbf..625f321 100644 (file)
 #define __NR_process_vm_readv  345
 #define __NR_process_vm_writev 346
 #define __NR_kcmp              347
+#define __NR_finit_module      348
 
 #endif /* _UAPI_ASM_M68K_UNISTD_H_ */
index c30da5b..3f04ea0 100644 (file)
@@ -368,4 +368,5 @@ ENTRY(sys_call_table)
        .long sys_process_vm_readv      /* 345 */
        .long sys_process_vm_writev
        .long sys_kcmp
+       .long sys_finit_module
 
index f0e05bc..afd8106 100644 (file)
 void *empty_zero_page;
 EXPORT_SYMBOL(empty_zero_page);
 
+#if !defined(CONFIG_SUN3) && !defined(CONFIG_COLDFIRE)
+extern void init_pointer_table(unsigned long ptable);
+extern pmd_t *zero_pgtable;
+#endif
+
 #ifdef CONFIG_MMU
 
 pg_data_t pg_data_map[MAX_NUMNODES];
@@ -69,9 +74,6 @@ void __init m68k_setup_node(int node)
        node_set_online(node);
 }
 
-extern void init_pointer_table(unsigned long ptable);
-extern pmd_t *zero_pgtable;
-
 #else /* CONFIG_MMU */
 
 /*
index bfb4424..eb7850b 100644 (file)
@@ -1865,7 +1865,7 @@ syscall_restore:
 
        /* Are we being ptraced? */
        ldw     TASK_FLAGS(%r1),%r19
-       ldi     (_TIF_SINGLESTEP|_TIF_BLOCKSTEP),%r2
+       ldi     _TIF_SYSCALL_TRACE_MASK,%r2
        and,COND(=)     %r19,%r2,%r0
        b,n     syscall_restore_rfi
 
@@ -1978,15 +1978,23 @@ syscall_restore_rfi:
        /* sr2 should be set to zero for userspace syscalls */
        STREG   %r0,TASK_PT_SR2(%r1)
 
-pt_regs_ok:
        LDREG   TASK_PT_GR31(%r1),%r2
-       depi    3,31,2,%r2                         /* ensure return to user mode. */
-       STREG   %r2,TASK_PT_IAOQ0(%r1)
+       depi    3,31,2,%r2                 /* ensure return to user mode. */
+       STREG   %r2,TASK_PT_IAOQ0(%r1)
        ldo     4(%r2),%r2
        STREG   %r2,TASK_PT_IAOQ1(%r1)
+       b       intr_restore
        copy    %r25,%r16
+
+pt_regs_ok:
+       LDREG   TASK_PT_IAOQ0(%r1),%r2
+       depi    3,31,2,%r2                 /* ensure return to user mode. */
+       STREG   %r2,TASK_PT_IAOQ0(%r1)
+       LDREG   TASK_PT_IAOQ1(%r1),%r2
+       depi    3,31,2,%r2
+       STREG   %r2,TASK_PT_IAOQ1(%r1)
        b       intr_restore
-       nop
+       copy    %r25,%r16
 
        .import schedule,code
 syscall_do_resched:
index c0b1aff..0299d63 100644 (file)
@@ -410,11 +410,13 @@ void __init init_IRQ(void)
 {
        local_irq_disable();    /* PARANOID - should already be disabled */
        mtctl(~0UL, 23);        /* EIRR : clear all pending external intr */
-       claim_cpu_irqs();
 #ifdef CONFIG_SMP
-       if (!cpu_eiem)
+       if (!cpu_eiem) {
+               claim_cpu_irqs();
                cpu_eiem = EIEM_MASK(IPI_IRQ) | EIEM_MASK(TIMER_IRQ);
+       }
 #else
+       claim_cpu_irqs();
        cpu_eiem = EIEM_MASK(TIMER_IRQ);
 #endif
         set_eiem(cpu_eiem);    /* EIEM : enable all external intr */
index 857c2f5..534abd4 100644 (file)
@@ -26,7 +26,7 @@
 #include <asm/asm-offsets.h>
 
 /* PSW bits we allow the debugger to modify */
-#define USER_PSW_BITS  (PSW_N | PSW_V | PSW_CB)
+#define USER_PSW_BITS  (PSW_N | PSW_B | PSW_V | PSW_CB)
 
 /*
  * Called by kernel/ptrace.c when detaching..
index 5379969..fd05170 100644 (file)
@@ -190,8 +190,10 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
        DBG(1,"get_sigframe: ka = %#lx, sp = %#lx, frame_size = %#lx\n",
                        (unsigned long)ka, sp, frame_size);
        
+       /* Align alternate stack and reserve 64 bytes for the signal
+          handler's frame marker.  */
        if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
-               sp = current->sas_ss_sp; /* Stacks grow up! */
+               sp = (current->sas_ss_sp + 0x7f) & ~0x3f; /* Stacks grow up! */
 
        DBG(1,"get_sigframe: Returning sp = %#lx\n", (unsigned long)sp);
        return (void __user *) sp; /* Stacks grow up.  Fun. */
index 9071e09..933423f 100644 (file)
     Sgl_isinexact_to_fix(sgl_value,exponent)
 
 #define Duint_from_sgl_mantissa(sgl_value,exponent,dresultA,dresultB)  \
-  {Sall(sgl_value) <<= SGL_EXP_LENGTH;  /*  left-justify  */           \
+  {unsigned int val = Sall(sgl_value) << SGL_EXP_LENGTH;               \
     if (exponent <= 31) {                                              \
-       Dintp1(dresultA) = 0;                                           \
-       Dintp2(dresultB) = (unsigned)Sall(sgl_value) >> (31 - exponent); \
+       Dintp1(dresultA) = 0;                                           \
+       Dintp2(dresultB) = val >> (31 - exponent);                      \
     }                                                                  \
     else {                                                             \
-       Dintp1(dresultA) = Sall(sgl_value) >> (63 - exponent);          \
-       Dintp2(dresultB) = Sall(sgl_value) << (exponent - 31);          \
+       Dintp1(dresultA) = val >> (63 - exponent);                      \
+       Dintp2(dresultB) = exponent <= 62 ? val << (exponent - 31) : 0; \
     }                                                                  \
-    Sall(sgl_value) >>= SGL_EXP_LENGTH;  /* return to original */      \
   }
 
 #define Duint_setzero(dresultA,dresultB)       \
index b0855e5..9d9cddc 100644 (file)
@@ -39,6 +39,7 @@
 #define OP_31_XOP_TRAP      4
 #define OP_31_XOP_LWZX      23
 #define OP_31_XOP_TRAP_64   68
+#define OP_31_XOP_DCBF      86
 #define OP_31_XOP_LBZX      87
 #define OP_31_XOP_STWX      151
 #define OP_31_XOP_STBX      215
@@ -374,6 +375,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
                        emulated = kvmppc_emulate_mtspr(vcpu, sprn, rs);
                        break;
 
+               case OP_31_XOP_DCBF:
                case OP_31_XOP_DCBI:
                        /* Do nothing. The guest is performing dcbi because
                         * hardware DMA is not snooped by the dcache, but
index ccce0ed..379814b 100644 (file)
@@ -71,7 +71,7 @@ GCOV_PROFILE := n
 $(obj)/bzImage: asflags-y  := $(SVGA_MODE)
 
 quiet_cmd_image = BUILD   $@
-cmd_image = $(obj)/tools/build $(obj)/setup.bin $(obj)/vmlinux.bin > $@
+cmd_image = $(obj)/tools/build $(obj)/setup.bin $(obj)/vmlinux.bin $(obj)/zoffset.h > $@
 
 $(obj)/bzImage: $(obj)/setup.bin $(obj)/vmlinux.bin $(obj)/tools/build FORCE
        $(call if_changed,image)
@@ -92,7 +92,7 @@ targets += voffset.h
 $(obj)/voffset.h: vmlinux FORCE
        $(call if_changed,voffset)
 
-sed-zoffset := -e 's/^\([0-9a-fA-F]*\) . \(startup_32\|input_data\|_end\|z_.*\)$$/\#define ZO_\2 0x\1/p'
+sed-zoffset := -e 's/^\([0-9a-fA-F]*\) . \(startup_32\|startup_64\|efi_pe_entry\|efi_stub_entry\|input_data\|_end\|z_.*\)$$/\#define ZO_\2 0x\1/p'
 
 quiet_cmd_zoffset = ZOFFSET $@
       cmd_zoffset = $(NM) $< | sed -n $(sed-zoffset) > $@
index b0098ba..f8fa411 100644 (file)
@@ -295,10 +295,15 @@ static efi_status_t setup_efi_pci(struct boot_params *params)
                if (!pci)
                        continue;
 
+#ifdef CONFIG_X86_64
                status = efi_call_phys4(pci->attributes, pci,
                                        EfiPciIoAttributeOperationGet, 0,
                                        &attributes);
-
+#else
+               status = efi_call_phys5(pci->attributes, pci,
+                                       EfiPciIoAttributeOperationGet, 0, 0,
+                                       &attributes);
+#endif
                if (status != EFI_SUCCESS)
                        continue;
 
@@ -429,10 +434,9 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
                         * Once we've found a GOP supporting ConOut,
                         * don't bother looking any further.
                         */
+                       first_gop = gop;
                        if (conout_found)
                                break;
-
-                       first_gop = gop;
                }
        }
 
index aa4aaf1..1e3184f 100644 (file)
@@ -35,11 +35,11 @@ ENTRY(startup_32)
 #ifdef CONFIG_EFI_STUB
        jmp     preferred_addr
 
-       .balign 0x10
        /*
         * We don't need the return address, so set up the stack so
-        * efi_main() can find its arugments.
+        * efi_main() can find its arguments.
         */
+ENTRY(efi_pe_entry)
        add     $0x4, %esp
 
        call    make_boot_params
@@ -50,8 +50,10 @@ ENTRY(startup_32)
        pushl   %eax
        pushl   %esi
        pushl   %ecx
+       sub     $0x4, %esp
 
-       .org 0x30,0x90
+ENTRY(efi_stub_entry)
+       add     $0x4, %esp
        call    efi_main
        cmpl    $0, %eax
        movl    %eax, %esi
index 2c4b171..f5d1aaa 100644 (file)
@@ -201,12 +201,12 @@ ENTRY(startup_64)
         */
 #ifdef CONFIG_EFI_STUB
        /*
-        * The entry point for the PE/COFF executable is 0x210, so only
-        * legacy boot loaders will execute this jmp.
+        * The entry point for the PE/COFF executable is efi_pe_entry, so
+        * only legacy boot loaders will execute this jmp.
         */
        jmp     preferred_addr
 
-       .org 0x210
+ENTRY(efi_pe_entry)
        mov     %rcx, %rdi
        mov     %rdx, %rsi
        pushq   %rdi
@@ -218,7 +218,7 @@ ENTRY(startup_64)
        popq    %rsi
        popq    %rdi
 
-       .org 0x230,0x90
+ENTRY(efi_stub_entry)
        call    efi_main
        movq    %rax,%rsi
        cmpq    $0,%rax
index 8c132a6..944ce59 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/e820.h>
 #include <asm/page_types.h>
 #include <asm/setup.h>
+#include <asm/bootparam.h>
 #include "boot.h"
 #include "voffset.h"
 #include "zoffset.h"
@@ -255,6 +256,9 @@ section_table:
        # header, from the old boot sector.
 
        .section ".header", "a"
+       .globl  sentinel
+sentinel:      .byte 0xff, 0xff        /* Used to detect broken loaders */
+
        .globl  hdr
 hdr:
 setup_sects:   .byte 0                 /* Filled in by build.c */
@@ -279,7 +283,7 @@ _start:
        # Part 2 of the header, from the old setup.S
 
                .ascii  "HdrS"          # header signature
-               .word   0x020b          # header version number (>= 0x0105)
+               .word   0x020c          # header version number (>= 0x0105)
                                        # or else old loadlin-1.5 will fail)
                .globl realmode_swtch
 realmode_swtch:        .word   0, 0            # default_switch, SETUPSEG
@@ -297,13 +301,7 @@ type_of_loader:    .byte   0               # 0 means ancient bootloader, newer
 
 # flags, unused bits must be zero (RFU) bit within loadflags
 loadflags:
-LOADED_HIGH    = 1                     # If set, the kernel is loaded high
-CAN_USE_HEAP   = 0x80                  # If set, the loader also has set
-                                       # heap_end_ptr to tell how much
-                                       # space behind setup.S can be used for
-                                       # heap purposes.
-                                       # Only the loader knows what is free
-               .byte   LOADED_HIGH
+               .byte   LOADED_HIGH     # The kernel is to be loaded high
 
 setup_move_size: .word  0x8000         # size to move, when setup is not
                                        # loaded at 0x90000. We will move setup
@@ -369,7 +367,23 @@ relocatable_kernel:    .byte 1
 relocatable_kernel:    .byte 0
 #endif
 min_alignment:         .byte MIN_KERNEL_ALIGN_LG2      # minimum alignment
-pad3:                  .word 0
+
+xloadflags:
+#ifdef CONFIG_X86_64
+# define XLF0 XLF_KERNEL_64                    /* 64-bit kernel */
+#else
+# define XLF0 0
+#endif
+#ifdef CONFIG_EFI_STUB
+# ifdef CONFIG_X86_64
+#  define XLF23 XLF_EFI_HANDOVER_64            /* 64-bit EFI handover ok */
+# else
+#  define XLF23 XLF_EFI_HANDOVER_32            /* 32-bit EFI handover ok */
+# endif
+#else
+# define XLF23 0
+#endif
+                       .word XLF0 | XLF23
 
 cmdline_size:   .long   COMMAND_LINE_SIZE-1     #length of the command line,
                                                 #added with boot protocol
@@ -397,8 +411,13 @@ pref_address:              .quad LOAD_PHYSICAL_ADDR        # preferred load addr
 #define INIT_SIZE VO_INIT_SIZE
 #endif
 init_size:             .long INIT_SIZE         # kernel initialization size
-handover_offset:       .long 0x30              # offset to the handover
+handover_offset:
+#ifdef CONFIG_EFI_STUB
+                       .long 0x30              # offset to the handover
                                                # protocol entry point
+#else
+                       .long 0
+#endif
 
 # End of setup header #####################################################
 
index 03c0683..96a6c75 100644 (file)
@@ -13,7 +13,7 @@ SECTIONS
        .bstext         : { *(.bstext) }
        .bsdata         : { *(.bsdata) }
 
-       . = 497;
+       . = 495;
        .header         : { *(.header) }
        .entrytext      : { *(.entrytext) }
        .inittext       : { *(.inittext) }
index 4b8e165..94c5446 100644 (file)
@@ -52,6 +52,10 @@ int is_big_kernel;
 
 #define PECOFF_RELOC_RESERVE 0x20
 
+unsigned long efi_stub_entry;
+unsigned long efi_pe_entry;
+unsigned long startup_64;
+
 /*----------------------------------------------------------------------*/
 
 static const u32 crctab32[] = {
@@ -132,7 +136,7 @@ static void die(const char * str, ...)
 
 static void usage(void)
 {
-       die("Usage: build setup system [> image]");
+       die("Usage: build setup system [zoffset.h] [> image]");
 }
 
 #ifdef CONFIG_EFI_STUB
@@ -206,30 +210,54 @@ static void update_pecoff_text(unsigned int text_start, unsigned int file_sz)
         */
        put_unaligned_le32(file_sz - 512, &buf[pe_header + 0x1c]);
 
-#ifdef CONFIG_X86_32
        /*
-        * Address of entry point.
-        *
-        * The EFI stub entry point is +16 bytes from the start of
-        * the .text section.
+        * Address of entry point for PE/COFF executable
         */
-       put_unaligned_le32(text_start + 16, &buf[pe_header + 0x28]);
-#else
-       /*
-        * Address of entry point. startup_32 is at the beginning and
-        * the 64-bit entry point (startup_64) is always 512 bytes
-        * after. The EFI stub entry point is 16 bytes after that, as
-        * the first instruction allows legacy loaders to jump over
-        * the EFI stub initialisation
-        */
-       put_unaligned_le32(text_start + 528, &buf[pe_header + 0x28]);
-#endif /* CONFIG_X86_32 */
+       put_unaligned_le32(text_start + efi_pe_entry, &buf[pe_header + 0x28]);
 
        update_pecoff_section_header(".text", text_start, text_sz);
 }
 
 #endif /* CONFIG_EFI_STUB */
 
+
+/*
+ * Parse zoffset.h and find the entry points. We could just #include zoffset.h
+ * but that would mean tools/build would have to be rebuilt every time. It's
+ * not as if parsing it is hard...
+ */
+#define PARSE_ZOFS(p, sym) do { \
+       if (!strncmp(p, "#define ZO_" #sym " ", 11+sizeof(#sym)))       \
+               sym = strtoul(p + 11 + sizeof(#sym), NULL, 16);         \
+} while (0)
+
+static void parse_zoffset(char *fname)
+{
+       FILE *file;
+       char *p;
+       int c;
+
+       file = fopen(fname, "r");
+       if (!file)
+               die("Unable to open `%s': %m", fname);
+       c = fread(buf, 1, sizeof(buf) - 1, file);
+       if (ferror(file))
+               die("read-error on `zoffset.h'");
+       buf[c] = 0;
+
+       p = (char *)buf;
+
+       while (p && *p) {
+               PARSE_ZOFS(p, efi_stub_entry);
+               PARSE_ZOFS(p, efi_pe_entry);
+               PARSE_ZOFS(p, startup_64);
+
+               p = strchr(p, '\n');
+               while (p && (*p == '\r' || *p == '\n'))
+                       p++;
+       }
+}
+
 int main(int argc, char ** argv)
 {
        unsigned int i, sz, setup_sectors;
@@ -241,7 +269,19 @@ int main(int argc, char ** argv)
        void *kernel;
        u32 crc = 0xffffffffUL;
 
-       if (argc != 3)
+       /* Defaults for old kernel */
+#ifdef CONFIG_X86_32
+       efi_pe_entry = 0x10;
+       efi_stub_entry = 0x30;
+#else
+       efi_pe_entry = 0x210;
+       efi_stub_entry = 0x230;
+       startup_64 = 0x200;
+#endif
+
+       if (argc == 4)
+               parse_zoffset(argv[3]);
+       else if (argc != 3)
                usage();
 
        /* Copy the setup code */
@@ -299,6 +339,11 @@ int main(int argc, char ** argv)
 
 #ifdef CONFIG_EFI_STUB
        update_pecoff_text(setup_sectors * 512, sz + i + ((sys_size * 16) - sz));
+
+#ifdef CONFIG_X86_64 /* Yes, this is really how we defined it :( */
+       efi_stub_entry -= 0x200;
+#endif
+       put_unaligned_le32(efi_stub_entry, &buf[0x264]);
 #endif
 
        crc = partial_crc32(buf, i, crc);
index 92862cd..c15ddaf 100644 (file)
@@ -1,6 +1,31 @@
 #ifndef _ASM_X86_BOOTPARAM_H
 #define _ASM_X86_BOOTPARAM_H
 
+/* setup_data types */
+#define SETUP_NONE                     0
+#define SETUP_E820_EXT                 1
+#define SETUP_DTB                      2
+#define SETUP_PCI                      3
+
+/* ram_size flags */
+#define RAMDISK_IMAGE_START_MASK       0x07FF
+#define RAMDISK_PROMPT_FLAG            0x8000
+#define RAMDISK_LOAD_FLAG              0x4000
+
+/* loadflags */
+#define LOADED_HIGH    (1<<0)
+#define QUIET_FLAG     (1<<5)
+#define KEEP_SEGMENTS  (1<<6)
+#define CAN_USE_HEAP   (1<<7)
+
+/* xloadflags */
+#define XLF_KERNEL_64                  (1<<0)
+#define XLF_CAN_BE_LOADED_ABOVE_4G     (1<<1)
+#define XLF_EFI_HANDOVER_32            (1<<2)
+#define XLF_EFI_HANDOVER_64            (1<<3)
+
+#ifndef __ASSEMBLY__
+
 #include <linux/types.h>
 #include <linux/screen_info.h>
 #include <linux/apm_bios.h>
@@ -9,12 +34,6 @@
 #include <asm/ist.h>
 #include <video/edid.h>
 
-/* setup data types */
-#define SETUP_NONE                     0
-#define SETUP_E820_EXT                 1
-#define SETUP_DTB                      2
-#define SETUP_PCI                      3
-
 /* extensible setup data list node */
 struct setup_data {
        __u64 next;
@@ -28,9 +47,6 @@ struct setup_header {
        __u16   root_flags;
        __u32   syssize;
        __u16   ram_size;
-#define RAMDISK_IMAGE_START_MASK       0x07FF
-#define RAMDISK_PROMPT_FLAG            0x8000
-#define RAMDISK_LOAD_FLAG              0x4000
        __u16   vid_mode;
        __u16   root_dev;
        __u16   boot_flag;
@@ -42,10 +58,6 @@ struct setup_header {
        __u16   kernel_version;
        __u8    type_of_loader;
        __u8    loadflags;
-#define LOADED_HIGH    (1<<0)
-#define QUIET_FLAG     (1<<5)
-#define KEEP_SEGMENTS  (1<<6)
-#define CAN_USE_HEAP   (1<<7)
        __u16   setup_move_size;
        __u32   code32_start;
        __u32   ramdisk_image;
@@ -58,7 +70,8 @@ struct setup_header {
        __u32   initrd_addr_max;
        __u32   kernel_alignment;
        __u8    relocatable_kernel;
-       __u8    _pad2[3];
+       __u8    min_alignment;
+       __u16   xloadflags;
        __u32   cmdline_size;
        __u32   hardware_subarch;
        __u64   hardware_subarch_data;
@@ -106,7 +119,10 @@ struct boot_params {
        __u8  hd1_info[16];     /* obsolete! */         /* 0x090 */
        struct sys_desc_table sys_desc_table;           /* 0x0a0 */
        struct olpc_ofw_header olpc_ofw_header;         /* 0x0b0 */
-       __u8  _pad4[128];                               /* 0x0c0 */
+       __u32 ext_ramdisk_image;                        /* 0x0c0 */
+       __u32 ext_ramdisk_size;                         /* 0x0c4 */
+       __u32 ext_cmd_line_ptr;                         /* 0x0c8 */
+       __u8  _pad4[116];                               /* 0x0cc */
        struct edid_info edid_info;                     /* 0x140 */
        struct efi_info efi_info;                       /* 0x1c0 */
        __u32 alt_mem_k;                                /* 0x1e0 */
@@ -115,7 +131,20 @@ struct boot_params {
        __u8  eddbuf_entries;                           /* 0x1e9 */
        __u8  edd_mbr_sig_buf_entries;                  /* 0x1ea */
        __u8  kbd_status;                               /* 0x1eb */
-       __u8  _pad6[5];                                 /* 0x1ec */
+       __u8  _pad5[3];                                 /* 0x1ec */
+       /*
+        * The sentinel is set to a nonzero value (0xff) in header.S.
+        *
+        * A bootloader is supposed to only take setup_header and put
+        * it into a clean boot_params buffer. If it turns out that
+        * it is clumsy or too generous with the buffer, it most
+        * probably will pick up the sentinel variable too. The fact
+        * that this variable then is still 0xff will let kernel
+        * know that some variables in boot_params are invalid and
+        * kernel should zero out certain portions of boot_params.
+        */
+       __u8  sentinel;                                 /* 0x1ef */
+       __u8  _pad6[1];                                 /* 0x1f0 */
        struct setup_header hdr;    /* setup header */  /* 0x1f1 */
        __u8  _pad7[0x290-0x1f1-sizeof(struct setup_header)];
        __u32 edd_mbr_sig_buffer[EDD_MBR_SIG_MAX];      /* 0x290 */
@@ -134,6 +163,6 @@ enum {
        X86_NR_SUBARCHS,
 };
 
-
+#endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_X86_BOOTPARAM_H */
index 4428fd1..6774c17 100644 (file)
@@ -340,9 +340,6 @@ int x86_setup_perfctr(struct perf_event *event)
                /* BTS is currently only allowed for user-mode. */
                if (!attr->exclude_kernel)
                        return -EOPNOTSUPP;
-
-               if (!attr->exclude_guest)
-                       return -EOPNOTSUPP;
        }
 
        hwc->config |= config;
@@ -385,9 +382,6 @@ int x86_pmu_hw_config(struct perf_event *event)
        if (event->attr.precise_ip) {
                int precise = 0;
 
-               if (!event->attr.exclude_guest)
-                       return -EOPNOTSUPP;
-
                /* Support for constant skid */
                if (x86_pmu.pebs_active && !x86_pmu.pebs_broken) {
                        precise++;
index ff84d54..6ed91d9 100644 (file)
@@ -1065,7 +1065,6 @@ ENTRY(xen_failsafe_callback)
        lea 16(%esp),%esp
        CFI_ADJUST_CFA_OFFSET -16
        jz 5f
-       addl $16,%esp
        jmp iret_exc
 5:     pushl_cfi $-1 /* orig_ax = -1 => not a system call */
        SAVE_ALL
index cd3b243..9b4d51d 100644 (file)
@@ -165,10 +165,11 @@ void set_task_blockstep(struct task_struct *task, bool on)
         * Ensure irq/preemption can't change debugctl in between.
         * Note also that both TIF_BLOCKSTEP and debugctl should
         * be changed atomically wrt preemption.
-        * FIXME: this means that set/clear TIF_BLOCKSTEP is simply
-        * wrong if task != current, SIGKILL can wakeup the stopped
-        * tracee and set/clear can play with the running task, this
-        * can confuse the next __switch_to_xtra().
+        *
+        * NOTE: this means that set/clear TIF_BLOCKSTEP is only safe if
+        * task is current or it can't be running, otherwise we can race
+        * with __switch_to_xtra(). We rely on ptrace_freeze_traced() but
+        * PTRACE_KILL is not safe.
         */
        local_irq_disable();
        debugctl = get_debugctlmsr();
index 5a1847d..79d67bd 100644 (file)
@@ -814,12 +814,14 @@ int main(int argc, char **argv)
        read_relocs(fp);
        if (show_absolute_syms) {
                print_absolute_symbols();
-               return 0;
+               goto out;
        }
        if (show_absolute_relocs) {
                print_absolute_relocs();
-               return 0;
+               goto out;
        }
        emit_relocs(as_text, use_real_mode);
+out:
+       fclose(fp);
        return 0;
 }
index 4f7d259..34bc4ce 100644 (file)
@@ -432,13 +432,6 @@ static void __cpuinit xen_play_dead(void) /* used only with HOTPLUG_CPU */
        play_dead_common();
        HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL);
        cpu_bringup();
-       /*
-        * Balance out the preempt calls - as we are running in cpu_idle
-        * loop which has been called at bootup from cpu_bringup_and_idle.
-        * The cpucpu_bringup_and_idle called cpu_bringup which made a
-        * preempt_disable() So this preempt_enable will balance it out.
-        */
-       preempt_enable();
 }
 
 #else /* !CONFIG_HOTPLUG_CPU */
index 00a7836..46f80e2 100644 (file)
@@ -590,6 +590,9 @@ static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr,
        if (bit_width == 32 && bit_offset == 0 && (*paddr & 0x03) == 0 &&
            *access_bit_width < 32)
                *access_bit_width = 32;
+       else if (bit_width == 64 && bit_offset == 0 && (*paddr & 0x07) == 0 &&
+           *access_bit_width < 64)
+               *access_bit_width = 64;
 
        if ((bit_width + bit_offset) > *access_bit_width) {
                pr_warning(FW_BUG APEI_PFX
index f1a5da4..ed9a1cc 100644 (file)
@@ -958,6 +958,9 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr)
                return -EINVAL;
        }
 
+       if (!dev)
+               return -EINVAL;
+
        dev->cpu = pr->id;
 
        if (max_cstate == 0)
@@ -1149,6 +1152,7 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
                }
 
                /* Populate Updated C-state information */
+               acpi_processor_get_power_info(pr);
                acpi_processor_setup_cpuidle_states(pr);
 
                /* Enable all cpuidle devices */
index 836bfe0..53e7ac9 100644 (file)
@@ -340,6 +340,13 @@ static void amd_fixup_frequency(struct acpi_processor_px *px, int i)
        if ((boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model < 10)
            || boot_cpu_data.x86 == 0x11) {
                rdmsr(MSR_AMD_PSTATE_DEF_BASE + index, lo, hi);
+               /*
+                * MSR C001_0064+:
+                * Bit 63: PstateEn. Read-write. If set, the P-state is valid.
+                */
+               if (!(hi & BIT(31)))
+                       return;
+
                fid = lo & 0x3f;
                did = (lo >> 6) & 7;
                if (boot_cpu_data.x86 == 0x10)
index 7862d17..4979127 100644 (file)
@@ -53,6 +53,7 @@
 
 enum {
        AHCI_PCI_BAR_STA2X11    = 0,
+       AHCI_PCI_BAR_ENMOTUS    = 2,
        AHCI_PCI_BAR_STANDARD   = 5,
 };
 
@@ -410,6 +411,9 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci },   /* ASM1061 */
        { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci },   /* ASM1062 */
 
+       /* Enmotus */
+       { PCI_DEVICE(0x1c44, 0x8000), board_ahci },
+
        /* Generic, PCI class code for AHCI */
        { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
          PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci },
@@ -1098,9 +1102,11 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                dev_info(&pdev->dev,
                         "PDC42819 can only drive SATA devices with this driver\n");
 
-       /* The Connext uses non-standard BAR */
+       /* Both Connext and Enmotus devices use non-standard BARs */
        if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == 0xCC06)
                ahci_pci_bar = AHCI_PCI_BAR_STA2X11;
+       else if (pdev->vendor == 0x1c44 && pdev->device == 0x8000)
+               ahci_pci_bar = AHCI_PCI_BAR_ENMOTUS;
 
        /* acquire resources */
        rc = pcim_enable_device(pdev);
index 320712a..6cd7805 100644 (file)
@@ -1951,13 +1951,13 @@ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep)
        /* Use the nominal value 10 ms if the read MDAT is zero,
         * the nominal value of DETO is 20 ms.
         */
-       if (dev->sata_settings[ATA_LOG_DEVSLP_VALID] &
+       if (dev->devslp_timing[ATA_LOG_DEVSLP_VALID] &
            ATA_LOG_DEVSLP_VALID_MASK) {
-               mdat = dev->sata_settings[ATA_LOG_DEVSLP_MDAT] &
+               mdat = dev->devslp_timing[ATA_LOG_DEVSLP_MDAT] &
                       ATA_LOG_DEVSLP_MDAT_MASK;
                if (!mdat)
                        mdat = 10;
-               deto = dev->sata_settings[ATA_LOG_DEVSLP_DETO];
+               deto = dev->devslp_timing[ATA_LOG_DEVSLP_DETO];
                if (!deto)
                        deto = 20;
        } else {
index 9e8b99a..46cd3f4 100644 (file)
@@ -2325,24 +2325,28 @@ int ata_dev_configure(struct ata_device *dev)
                        }
                }
 
-               /* check and mark DevSlp capability */
-               if (ata_id_has_devslp(dev->id))
-                       dev->flags |= ATA_DFLAG_DEVSLP;
-
-               /* Obtain SATA Settings page from Identify Device Data Log,
-                * which contains DevSlp timing variables etc.
-                * Exclude old devices with ata_id_has_ncq()
+               /* Check and mark DevSlp capability. Get DevSlp timing variables
+                * from SATA Settings page of Identify Device Data Log.
                 */
-               if (ata_id_has_ncq(dev->id)) {
+               if (ata_id_has_devslp(dev->id)) {
+                       u8 sata_setting[ATA_SECT_SIZE];
+                       int i, j;
+
+                       dev->flags |= ATA_DFLAG_DEVSLP;
                        err_mask = ata_read_log_page(dev,
                                                     ATA_LOG_SATA_ID_DEV_DATA,
                                                     ATA_LOG_SATA_SETTINGS,
-                                                    dev->sata_settings,
+                                                    sata_setting,
                                                     1);
                        if (err_mask)
                                ata_dev_dbg(dev,
                                            "failed to get Identify Device Data, Emask 0x%x\n",
                                            err_mask);
+                       else
+                               for (i = 0; i < ATA_LOG_DEVSLP_SIZE; i++) {
+                                       j = ATA_LOG_DEVSLP_OFFSET + i;
+                                       dev->devslp_timing[i] = sata_setting[j];
+                               }
                }
 
                dev->cdb_len = 16;
index bf039b0..bcf4437 100644 (file)
@@ -2094,7 +2094,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev,
  */
 static inline int ata_eh_worth_retry(struct ata_queued_cmd *qc)
 {
-       if (qc->flags & AC_ERR_MEDIA)
+       if (qc->err_mask & AC_ERR_MEDIA)
                return 0;       /* don't retry media errors */
        if (qc->flags & ATA_QCFLAG_IO)
                return 1;       /* otherwise retry anything from fs stack */
index 46a213a..d9a6c94 100644 (file)
@@ -121,8 +121,6 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map,
                c->max = p - 1;
                list_add_tail(&c->list,
                              &map->debugfs_off_cache);
-       } else {
-               return base;
        }
 
        /*
index 42d5cb0..f00b059 100644 (file)
@@ -1106,7 +1106,7 @@ EXPORT_SYMBOL_GPL(regmap_raw_write);
  * @val_count: Number of registers to write
  *
  * This function is intended to be used for writing a large block of
- * data to be device either in single transfer or multiple transfer.
+ * data to the device either in single transfer or multiple transfer.
  *
  * A value of zero will be returned on success, a negative errno will
  * be returned in error cases.
index 9d8409c..8ad21a2 100644 (file)
@@ -889,6 +889,7 @@ static void virtblk_remove(struct virtio_device *vdev)
 {
        struct virtio_blk *vblk = vdev->priv;
        int index = vblk->index;
+       int refc;
 
        /* Prevent config work handler from accessing the device. */
        mutex_lock(&vblk->config_lock);
@@ -903,11 +904,15 @@ static void virtblk_remove(struct virtio_device *vdev)
 
        flush_work(&vblk->config_work);
 
+       refc = atomic_read(&disk_to_dev(vblk->disk)->kobj.kref.refcount);
        put_disk(vblk->disk);
        mempool_destroy(vblk->pool);
        vdev->config->del_vqs(vdev);
        kfree(vblk);
-       ida_simple_remove(&vd_index_ida, index);
+
+       /* Only free device id if we don't have any users */
+       if (refc == 1)
+               ida_simple_remove(&vd_index_ida, index);
 }
 
 #ifdef CONFIG_PM
index ff00457..9dd2551 100644 (file)
@@ -124,7 +124,7 @@ void __init of_cpu_clk_setup(struct device_node *node)
 
        clks = kzalloc(ncpus * sizeof(*clks), GFP_KERNEL);
        if (WARN_ON(!clks))
-               return;
+               goto clks_out;
 
        for_each_node_by_type(dn, "cpu") {
                struct clk_init_data init;
@@ -134,11 +134,11 @@ void __init of_cpu_clk_setup(struct device_node *node)
                int cpu, err;
 
                if (WARN_ON(!clk_name))
-                       return;
+                       goto bail_out;
 
                err = of_property_read_u32(dn, "reg", &cpu);
                if (WARN_ON(err))
-                       return;
+                       goto bail_out;
 
                sprintf(clk_name, "cpu%d", cpu);
                parent_clk = of_clk_get(node, 0);
@@ -167,6 +167,9 @@ void __init of_cpu_clk_setup(struct device_node *node)
        return;
 bail_out:
        kfree(clks);
+       while(ncpus--)
+               kfree(cpuclk[ncpus].clk_name);
+clks_out:
        kfree(cpuclk);
 }
 
index 934854a..7227cd7 100644 (file)
@@ -106,7 +106,7 @@ config X86_POWERNOW_K7_ACPI
 config X86_POWERNOW_K8
        tristate "AMD Opteron/Athlon64 PowerNow!"
        select CPU_FREQ_TABLE
-       depends on ACPI && ACPI_PROCESSOR
+       depends on ACPI && ACPI_PROCESSOR && X86_ACPI_CPUFREQ
        help
          This adds the CPUFreq driver for K8/early Opteron/Athlon64 processors.
          Support for K10 and newer processors is now in acpi-cpufreq.
index 0d048f6..7b0d49d 100644 (file)
@@ -1030,4 +1030,11 @@ MODULE_PARM_DESC(acpi_pstate_strict,
 late_initcall(acpi_cpufreq_init);
 module_exit(acpi_cpufreq_exit);
 
+static const struct x86_cpu_id acpi_cpufreq_ids[] = {
+       X86_FEATURE_MATCH(X86_FEATURE_ACPI),
+       X86_FEATURE_MATCH(X86_FEATURE_HW_PSTATE),
+       {}
+};
+MODULE_DEVICE_TABLE(x86cpu, acpi_cpufreq_ids);
+
 MODULE_ALIAS("acpi");
index 52bf36d..debc5a7 100644 (file)
@@ -71,12 +71,15 @@ static int cpu0_set_target(struct cpufreq_policy *policy,
        }
 
        if (cpu_reg) {
+               rcu_read_lock();
                opp = opp_find_freq_ceil(cpu_dev, &freq_Hz);
                if (IS_ERR(opp)) {
+                       rcu_read_unlock();
                        pr_err("failed to find OPP for %ld\n", freq_Hz);
                        return PTR_ERR(opp);
                }
                volt = opp_get_voltage(opp);
+               rcu_read_unlock();
                tol = volt * voltage_tolerance / 100;
                volt_old = regulator_get_voltage(cpu_reg);
        }
@@ -236,12 +239,14 @@ static int cpu0_cpufreq_driver_init(void)
                 */
                for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++)
                        ;
+               rcu_read_lock();
                opp = opp_find_freq_exact(cpu_dev,
                                freq_table[0].frequency * 1000, true);
                min_uV = opp_get_voltage(opp);
                opp = opp_find_freq_exact(cpu_dev,
                                freq_table[i-1].frequency * 1000, true);
                max_uV = opp_get_voltage(opp);
+               rcu_read_unlock();
                ret = regulator_set_voltage_time(cpu_reg, min_uV, max_uV);
                if (ret > 0)
                        transition_latency += ret * 1000;
index 1f3417a..97102b0 100644 (file)
@@ -110,13 +110,16 @@ static int omap_target(struct cpufreq_policy *policy,
        freq = ret;
 
        if (mpu_reg) {
+               rcu_read_lock();
                opp = opp_find_freq_ceil(mpu_dev, &freq);
                if (IS_ERR(opp)) {
+                       rcu_read_unlock();
                        dev_err(mpu_dev, "%s: unable to find MPU OPP for %d\n",
                                __func__, freqs.new);
                        return -EINVAL;
                }
                volt = opp_get_voltage(opp);
+               rcu_read_unlock();
                tol = volt * OPP_TOLERANCE / 100;
                volt_old = regulator_get_voltage(mpu_reg);
        }
index 53766f3..3b36797 100644 (file)
@@ -994,6 +994,11 @@ module_exit(devfreq_exit);
  * @freq:      The frequency given to target function
  * @flags:     Flags handed from devfreq framework.
  *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. The reason for the same is that the opp pointer which is
+ * returned will remain valid for use with opp_get_{voltage, freq} only while
+ * under the locked area. The pointer returned must be used prior to unlocking
+ * with rcu_read_unlock() to maintain the integrity of the pointer.
  */
 struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq,
                                    u32 flags)
index 80c745e..46d94e9 100644 (file)
@@ -73,6 +73,16 @@ enum busclk_level_idx {
 #define EX4210_LV_NUM  (LV_2 + 1)
 #define EX4x12_LV_NUM  (LV_4 + 1)
 
+/**
+ * struct busfreq_opp_info - opp information for bus
+ * @rate:      Frequency in hertz
+ * @volt:      Voltage in microvolts corresponding to this OPP
+ */
+struct busfreq_opp_info {
+       unsigned long rate;
+       unsigned long volt;
+};
+
 struct busfreq_data {
        enum exynos4_busf_type type;
        struct device *dev;
@@ -80,7 +90,7 @@ struct busfreq_data {
        bool disabled;
        struct regulator *vdd_int;
        struct regulator *vdd_mif; /* Exynos4412/4212 only */
-       struct opp *curr_opp;
+       struct busfreq_opp_info curr_oppinfo;
        struct exynos4_ppmu dmc[2];
 
        struct notifier_block pm_notifier;
@@ -296,13 +306,14 @@ static unsigned int exynos4x12_clkdiv_sclkip[][3] = {
 };
 
 
-static int exynos4210_set_busclk(struct busfreq_data *data, struct opp *opp)
+static int exynos4210_set_busclk(struct busfreq_data *data,
+                                struct busfreq_opp_info *oppi)
 {
        unsigned int index;
        unsigned int tmp;
 
        for (index = LV_0; index < EX4210_LV_NUM; index++)
-               if (opp_get_freq(opp) == exynos4210_busclk_table[index].clk)
+               if (oppi->rate == exynos4210_busclk_table[index].clk)
                        break;
 
        if (index == EX4210_LV_NUM)
@@ -361,13 +372,14 @@ static int exynos4210_set_busclk(struct busfreq_data *data, struct opp *opp)
        return 0;
 }
 
-static int exynos4x12_set_busclk(struct busfreq_data *data, struct opp *opp)
+static int exynos4x12_set_busclk(struct busfreq_data *data,
+                                struct busfreq_opp_info *oppi)
 {
        unsigned int index;
        unsigned int tmp;
 
        for (index = LV_0; index < EX4x12_LV_NUM; index++)
-               if (opp_get_freq(opp) == exynos4x12_mifclk_table[index].clk)
+               if (oppi->rate == exynos4x12_mifclk_table[index].clk)
                        break;
 
        if (index == EX4x12_LV_NUM)
@@ -576,11 +588,12 @@ static int exynos4x12_get_intspec(unsigned long mifclk)
        return -EINVAL;
 }
 
-static int exynos4_bus_setvolt(struct busfreq_data *data, struct opp *opp,
-                              struct opp *oldopp)
+static int exynos4_bus_setvolt(struct busfreq_data *data,
+                              struct busfreq_opp_info *oppi,
+                              struct busfreq_opp_info *oldoppi)
 {
        int err = 0, tmp;
-       unsigned long volt = opp_get_voltage(opp);
+       unsigned long volt = oppi->volt;
 
        switch (data->type) {
        case TYPE_BUSF_EXYNOS4210:
@@ -595,11 +608,11 @@ static int exynos4_bus_setvolt(struct busfreq_data *data, struct opp *opp,
                if (err)
                        break;
 
-               tmp = exynos4x12_get_intspec(opp_get_freq(opp));
+               tmp = exynos4x12_get_intspec(oppi->rate);
                if (tmp < 0) {
                        err = tmp;
                        regulator_set_voltage(data->vdd_mif,
-                                             opp_get_voltage(oldopp),
+                                             oldoppi->volt,
                                              MAX_SAFEVOLT);
                        break;
                }
@@ -609,7 +622,7 @@ static int exynos4_bus_setvolt(struct busfreq_data *data, struct opp *opp,
                /*  Try to recover */
                if (err)
                        regulator_set_voltage(data->vdd_mif,
-                                             opp_get_voltage(oldopp),
+                                             oldoppi->volt,
                                              MAX_SAFEVOLT);
                break;
        default:
@@ -626,17 +639,26 @@ static int exynos4_bus_target(struct device *dev, unsigned long *_freq,
        struct platform_device *pdev = container_of(dev, struct platform_device,
                                                    dev);
        struct busfreq_data *data = platform_get_drvdata(pdev);
-       struct opp *opp = devfreq_recommended_opp(dev, _freq, flags);
-       unsigned long freq = opp_get_freq(opp);
-       unsigned long old_freq = opp_get_freq(data->curr_opp);
+       struct opp *opp;
+       unsigned long freq;
+       unsigned long old_freq = data->curr_oppinfo.rate;
+       struct busfreq_opp_info new_oppinfo;
 
-       if (IS_ERR(opp))
+       rcu_read_lock();
+       opp = devfreq_recommended_opp(dev, _freq, flags);
+       if (IS_ERR(opp)) {
+               rcu_read_unlock();
                return PTR_ERR(opp);
+       }
+       new_oppinfo.rate = opp_get_freq(opp);
+       new_oppinfo.volt = opp_get_voltage(opp);
+       rcu_read_unlock();
+       freq = new_oppinfo.rate;
 
        if (old_freq == freq)
                return 0;
 
-       dev_dbg(dev, "targetting %lukHz %luuV\n", freq, opp_get_voltage(opp));
+       dev_dbg(dev, "targetting %lukHz %luuV\n", freq, new_oppinfo.volt);
 
        mutex_lock(&data->lock);
 
@@ -644,17 +666,18 @@ static int exynos4_bus_target(struct device *dev, unsigned long *_freq,
                goto out;
 
        if (old_freq < freq)
-               err = exynos4_bus_setvolt(data, opp, data->curr_opp);
+               err = exynos4_bus_setvolt(data, &new_oppinfo,
+                                         &data->curr_oppinfo);
        if (err)
                goto out;
 
        if (old_freq != freq) {
                switch (data->type) {
                case TYPE_BUSF_EXYNOS4210:
-                       err = exynos4210_set_busclk(data, opp);
+                       err = exynos4210_set_busclk(data, &new_oppinfo);
                        break;
                case TYPE_BUSF_EXYNOS4x12:
-                       err = exynos4x12_set_busclk(data, opp);
+                       err = exynos4x12_set_busclk(data, &new_oppinfo);
                        break;
                default:
                        err = -EINVAL;
@@ -664,11 +687,12 @@ static int exynos4_bus_target(struct device *dev, unsigned long *_freq,
                goto out;
 
        if (old_freq > freq)
-               err = exynos4_bus_setvolt(data, opp, data->curr_opp);
+               err = exynos4_bus_setvolt(data, &new_oppinfo,
+                                         &data->curr_oppinfo);
        if (err)
                goto out;
 
-       data->curr_opp = opp;
+       data->curr_oppinfo = new_oppinfo;
 out:
        mutex_unlock(&data->lock);
        return err;
@@ -702,7 +726,7 @@ static int exynos4_bus_get_dev_status(struct device *dev,
 
        exynos4_read_ppmu(data);
        busier_dmc = exynos4_get_busier_dmc(data);
-       stat->current_frequency = opp_get_freq(data->curr_opp);
+       stat->current_frequency = data->curr_oppinfo.rate;
 
        if (busier_dmc)
                addr = S5P_VA_DMC1;
@@ -933,6 +957,7 @@ static int exynos4_busfreq_pm_notifier_event(struct notifier_block *this,
        struct busfreq_data *data = container_of(this, struct busfreq_data,
                                                 pm_notifier);
        struct opp *opp;
+       struct busfreq_opp_info new_oppinfo;
        unsigned long maxfreq = ULONG_MAX;
        int err = 0;
 
@@ -943,18 +968,29 @@ static int exynos4_busfreq_pm_notifier_event(struct notifier_block *this,
 
                data->disabled = true;
 
+               rcu_read_lock();
                opp = opp_find_freq_floor(data->dev, &maxfreq);
+               if (IS_ERR(opp)) {
+                       rcu_read_unlock();
+                       dev_err(data->dev, "%s: unable to find a min freq\n",
+                               __func__);
+                       return PTR_ERR(opp);
+               }
+               new_oppinfo.rate = opp_get_freq(opp);
+               new_oppinfo.volt = opp_get_voltage(opp);
+               rcu_read_unlock();
 
-               err = exynos4_bus_setvolt(data, opp, data->curr_opp);
+               err = exynos4_bus_setvolt(data, &new_oppinfo,
+                                         &data->curr_oppinfo);
                if (err)
                        goto unlock;
 
                switch (data->type) {
                case TYPE_BUSF_EXYNOS4210:
-                       err = exynos4210_set_busclk(data, opp);
+                       err = exynos4210_set_busclk(data, &new_oppinfo);
                        break;
                case TYPE_BUSF_EXYNOS4x12:
-                       err = exynos4x12_set_busclk(data, opp);
+                       err = exynos4x12_set_busclk(data, &new_oppinfo);
                        break;
                default:
                        err = -EINVAL;
@@ -962,7 +998,7 @@ static int exynos4_busfreq_pm_notifier_event(struct notifier_block *this,
                if (err)
                        goto unlock;
 
-               data->curr_opp = opp;
+               data->curr_oppinfo = new_oppinfo;
 unlock:
                mutex_unlock(&data->lock);
                if (err)
@@ -1027,13 +1063,17 @@ static int exynos4_busfreq_probe(struct platform_device *pdev)
                }
        }
 
+       rcu_read_lock();
        opp = opp_find_freq_floor(dev, &exynos4_devfreq_profile.initial_freq);
        if (IS_ERR(opp)) {
+               rcu_read_unlock();
                dev_err(dev, "Invalid initial frequency %lu kHz.\n",
                        exynos4_devfreq_profile.initial_freq);
                return PTR_ERR(opp);
        }
-       data->curr_opp = opp;
+       data->curr_oppinfo.rate = opp_get_freq(opp);
+       data->curr_oppinfo.volt = opp_get_voltage(opp);
+       rcu_read_unlock();
 
        platform_set_drvdata(pdev, data);
 
index dbf0e6f..a7dcf78 100644 (file)
@@ -684,9 +684,8 @@ static int imxdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
                        break;
                }
 
-               imxdmac->hw_chaining = 1;
-               if (!imxdma_hw_chain(imxdmac))
-                       return -EINVAL;
+               imxdmac->hw_chaining = 0;
+
                imxdmac->ccr_from_device = (mode | IMX_DMA_TYPE_FIFO) |
                        ((IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR) << 2) |
                        CCR_REN;
index e5fc944..3e9d669 100644 (file)
@@ -951,7 +951,7 @@ static int ioat_xor_val_self_test(struct ioatdma_device *device)
                        goto free_resources;
                }
        }
-       dma_sync_single_for_device(dev, dest_dma, PAGE_SIZE, DMA_TO_DEVICE);
+       dma_sync_single_for_device(dev, dest_dma, PAGE_SIZE, DMA_FROM_DEVICE);
 
        /* skip validate if the capability is not present */
        if (!dma_has_cap(DMA_XOR_VAL, dma_chan->device->cap_mask))
index c39e61b..3cad856 100644 (file)
@@ -266,6 +266,7 @@ static struct tegra_dma_desc *tegra_dma_desc_get(
                if (async_tx_test_ack(&dma_desc->txd)) {
                        list_del(&dma_desc->node);
                        spin_unlock_irqrestore(&tdc->lock, flags);
+                       dma_desc->txd.flags = 0;
                        return dma_desc;
                }
        }
@@ -1050,7 +1051,9 @@ struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic(
                                        TEGRA_APBDMA_AHBSEQ_WRAP_SHIFT;
        ahb_seq |= TEGRA_APBDMA_AHBSEQ_BUS_WIDTH_32;
 
-       csr |= TEGRA_APBDMA_CSR_FLOW | TEGRA_APBDMA_CSR_IE_EOC;
+       csr |= TEGRA_APBDMA_CSR_FLOW;
+       if (flags & DMA_PREP_INTERRUPT)
+               csr |= TEGRA_APBDMA_CSR_IE_EOC;
        csr |= tdc->dma_sconfig.slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT;
 
        apb_seq |= TEGRA_APBDMA_APBSEQ_WRAP_WORD_1;
@@ -1095,7 +1098,8 @@ struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic(
                mem += len;
        }
        sg_req->last_sg = true;
-       dma_desc->txd.flags = 0;
+       if (flags & DMA_CTRL_ACK)
+               dma_desc->txd.flags = DMA_CTRL_ACK;
 
        /*
         * Make sure that mode should not be conflicting with currently
index 7d9bd94..6819d63 100644 (file)
@@ -547,7 +547,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
        mvchip->membase = devm_request_and_ioremap(&pdev->dev, res);
        if (! mvchip->membase) {
                dev_err(&pdev->dev, "Cannot ioremap\n");
-               kfree(mvchip->chip.label);
                return -ENOMEM;
        }
 
@@ -557,14 +556,12 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
                res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
                if (! res) {
                        dev_err(&pdev->dev, "Cannot get memory resource\n");
-                       kfree(mvchip->chip.label);
                        return -ENODEV;
                }
 
                mvchip->percpu_membase = devm_request_and_ioremap(&pdev->dev, res);
                if (! mvchip->percpu_membase) {
                        dev_err(&pdev->dev, "Cannot ioremap\n");
-                       kfree(mvchip->chip.label);
                        return -ENOMEM;
                }
        }
@@ -625,7 +622,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
        mvchip->irqbase = irq_alloc_descs(-1, 0, ngpios, -1);
        if (mvchip->irqbase < 0) {
                dev_err(&pdev->dev, "no irqs\n");
-               kfree(mvchip->chip.label);
                return -ENOMEM;
        }
 
@@ -633,7 +629,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
                                    mvchip->membase, handle_level_irq);
        if (! gc) {
                dev_err(&pdev->dev, "Cannot allocate generic irq_chip\n");
-               kfree(mvchip->chip.label);
                return -ENOMEM;
        }
 
@@ -668,7 +663,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
                irq_remove_generic_chip(gc, IRQ_MSK(ngpios), IRQ_NOREQUEST,
                                        IRQ_LEVEL | IRQ_NOPROBE);
                kfree(gc);
-               kfree(mvchip->chip.label);
                return -ENODEV;
        }
 
index 01f7fe9..76be7ee 100644 (file)
@@ -32,7 +32,6 @@
 
 #include <mach/hardware.h>
 #include <mach/map.h>
-#include <mach/regs-clock.h>
 #include <mach/regs-gpio.h>
 
 #include <plat/cpu.h>
@@ -446,7 +445,7 @@ static struct samsung_gpio_cfg s3c24xx_gpiocfg_banka = {
 };
 #endif
 
-#if defined(CONFIG_ARCH_EXYNOS4) || defined(CONFIG_ARCH_EXYNOS5)
+#if defined(CONFIG_ARCH_EXYNOS4) || defined(CONFIG_SOC_EXYNOS5250)
 static struct samsung_gpio_cfg exynos_gpio_cfg = {
        .set_pull       = exynos_gpio_setpull,
        .get_pull       = exynos_gpio_getpull,
@@ -2446,7 +2445,7 @@ static struct samsung_gpio_chip exynos4_gpios_3[] = {
 };
 #endif
 
-#ifdef CONFIG_ARCH_EXYNOS5
+#ifdef CONFIG_SOC_EXYNOS5250
 static struct samsung_gpio_chip exynos5_gpios_1[] = {
        {
                .chip   = {
@@ -2614,7 +2613,7 @@ static struct samsung_gpio_chip exynos5_gpios_1[] = {
 };
 #endif
 
-#ifdef CONFIG_ARCH_EXYNOS5
+#ifdef CONFIG_SOC_EXYNOS5250
 static struct samsung_gpio_chip exynos5_gpios_2[] = {
        {
                .chip   = {
@@ -2675,7 +2674,7 @@ static struct samsung_gpio_chip exynos5_gpios_2[] = {
 };
 #endif
 
-#ifdef CONFIG_ARCH_EXYNOS5
+#ifdef CONFIG_SOC_EXYNOS5250
 static struct samsung_gpio_chip exynos5_gpios_3[] = {
        {
                .chip   = {
@@ -2711,7 +2710,7 @@ static struct samsung_gpio_chip exynos5_gpios_3[] = {
 };
 #endif
 
-#ifdef CONFIG_ARCH_EXYNOS5
+#ifdef CONFIG_SOC_EXYNOS5250
 static struct samsung_gpio_chip exynos5_gpios_4[] = {
        {
                .chip   = {
@@ -3010,7 +3009,7 @@ static __init int samsung_gpiolib_init(void)
        int i, nr_chips;
        int group = 0;
 
-#ifdef CONFIG_PINCTRL_SAMSUNG
+#if defined(CONFIG_PINCTRL_EXYNOS) || defined(CONFIG_PINCTRL_EXYNOS5440)
        /*
        * This gpio driver includes support for device tree support and there
        * are platforms using it. In order to maintain compatibility with those
@@ -3026,6 +3025,7 @@ static __init int samsung_gpiolib_init(void)
        static const struct of_device_id exynos_pinctrl_ids[] = {
                { .compatible = "samsung,pinctrl-exynos4210", },
                { .compatible = "samsung,pinctrl-exynos4x12", },
+               { .compatible = "samsung,pinctrl-exynos5440", },
        };
        for_each_matching_node(pctrl_np, exynos_pinctrl_ids)
                if (pctrl_np && of_device_is_available(pctrl_np))
index e6a11ca..7944d30 100644 (file)
@@ -641,6 +641,7 @@ static void i915_ring_error_state(struct seq_file *m,
        seq_printf(m, "%s command stream:\n", ring_str(ring));
        seq_printf(m, "  HEAD: 0x%08x\n", error->head[ring]);
        seq_printf(m, "  TAIL: 0x%08x\n", error->tail[ring]);
+       seq_printf(m, "  CTL: 0x%08x\n", error->ctl[ring]);
        seq_printf(m, "  ACTHD: 0x%08x\n", error->acthd[ring]);
        seq_printf(m, "  IPEIR: 0x%08x\n", error->ipeir[ring]);
        seq_printf(m, "  IPEHR: 0x%08x\n", error->ipehr[ring]);
@@ -693,6 +694,8 @@ static int i915_error_state(struct seq_file *m, void *unused)
        seq_printf(m, "EIR: 0x%08x\n", error->eir);
        seq_printf(m, "IER: 0x%08x\n", error->ier);
        seq_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er);
+       seq_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake);
+       seq_printf(m, "DERRMR: 0x%08x\n", error->derrmr);
        seq_printf(m, "CCID: 0x%08x\n", error->ccid);
 
        for (i = 0; i < dev_priv->num_fence_regs; i++)
index ed30595..12ab3bd 100644 (file)
@@ -188,10 +188,13 @@ struct drm_i915_error_state {
        u32 pgtbl_er;
        u32 ier;
        u32 ccid;
+       u32 derrmr;
+       u32 forcewake;
        bool waiting[I915_NUM_RINGS];
        u32 pipestat[I915_MAX_PIPES];
        u32 tail[I915_NUM_RINGS];
        u32 head[I915_NUM_RINGS];
+       u32 ctl[I915_NUM_RINGS];
        u32 ipeir[I915_NUM_RINGS];
        u32 ipehr[I915_NUM_RINGS];
        u32 instdone[I915_NUM_RINGS];
index d6a994a..26d08bb 100644 (file)
@@ -539,6 +539,8 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
        total = 0;
        for (i = 0; i < count; i++) {
                struct drm_i915_gem_relocation_entry __user *user_relocs;
+               u64 invalid_offset = (u64)-1;
+               int j;
 
                user_relocs = (void __user *)(uintptr_t)exec[i].relocs_ptr;
 
@@ -549,6 +551,25 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
                        goto err;
                }
 
+               /* As we do not update the known relocation offsets after
+                * relocating (due to the complexities in lock handling),
+                * we need to mark them as invalid now so that we force the
+                * relocation processing next time. Just in case the target
+                * object is evicted and then rebound into its old
+                * presumed_offset before the next execbuffer - if that
+                * happened we would make the mistake of assuming that the
+                * relocations were valid.
+                */
+               for (j = 0; j < exec[i].relocation_count; j++) {
+                       if (copy_to_user(&user_relocs[j].presumed_offset,
+                                        &invalid_offset,
+                                        sizeof(invalid_offset))) {
+                               ret = -EFAULT;
+                               mutex_lock(&dev->struct_mutex);
+                               goto err;
+                       }
+               }
+
                reloc_offset[i] = total;
                total += exec[i].relocation_count;
        }
index 2220dec..fe84338 100644 (file)
@@ -1157,6 +1157,7 @@ static void i915_record_ring_state(struct drm_device *dev,
        error->acthd[ring->id] = intel_ring_get_active_head(ring);
        error->head[ring->id] = I915_READ_HEAD(ring);
        error->tail[ring->id] = I915_READ_TAIL(ring);
+       error->ctl[ring->id] = I915_READ_CTL(ring);
 
        error->cpu_ring_head[ring->id] = ring->head;
        error->cpu_ring_tail[ring->id] = ring->tail;
@@ -1251,6 +1252,16 @@ static void i915_capture_error_state(struct drm_device *dev)
        else
                error->ier = I915_READ(IER);
 
+       if (INTEL_INFO(dev)->gen >= 6)
+               error->derrmr = I915_READ(DERRMR);
+
+       if (IS_VALLEYVIEW(dev))
+               error->forcewake = I915_READ(FORCEWAKE_VLV);
+       else if (INTEL_INFO(dev)->gen >= 7)
+               error->forcewake = I915_READ(FORCEWAKE_MT);
+       else if (INTEL_INFO(dev)->gen == 6)
+               error->forcewake = I915_READ(FORCEWAKE);
+
        for_each_pipe(pipe)
                error->pipestat[pipe] = I915_READ(PIPESTAT(pipe));
 
index 186ee5c..b401788 100644 (file)
 #define GEN7_ERR_INT   0x44040
 #define   ERR_INT_MMIO_UNCLAIMED (1<<13)
 
+#define DERRMR         0x44050
+
 /* GM45+ chicken bits -- debug workaround bits that may be required
  * for various sorts of correct behavior.  The top 16 bits of each are
  * the enables for writing to the corresponding low bit.
index 1b63d55..fb3715b 100644 (file)
@@ -2579,7 +2579,8 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect
 
 static void
 intel_dp_init_panel_power_sequencer(struct drm_device *dev,
-                                   struct intel_dp *intel_dp)
+                                   struct intel_dp *intel_dp,
+                                   struct edp_power_seq *out)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct edp_power_seq cur, vbt, spec, final;
@@ -2650,16 +2651,35 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev,
        intel_dp->panel_power_cycle_delay = get_delay(t11_t12);
 #undef get_delay
 
+       DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n",
+                     intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay,
+                     intel_dp->panel_power_cycle_delay);
+
+       DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n",
+                     intel_dp->backlight_on_delay, intel_dp->backlight_off_delay);
+
+       if (out)
+               *out = final;
+}
+
+static void
+intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
+                                             struct intel_dp *intel_dp,
+                                             struct edp_power_seq *seq)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 pp_on, pp_off, pp_div;
+
        /* And finally store the new values in the power sequencer. */
-       pp_on = (final.t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) |
-               (final.t8 << PANEL_LIGHT_ON_DELAY_SHIFT);
-       pp_off = (final.t9 << PANEL_LIGHT_OFF_DELAY_SHIFT) |
-                (final.t10 << PANEL_POWER_DOWN_DELAY_SHIFT);
+       pp_on = (seq->t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) |
+               (seq->t8 << PANEL_LIGHT_ON_DELAY_SHIFT);
+       pp_off = (seq->t9 << PANEL_LIGHT_OFF_DELAY_SHIFT) |
+                (seq->t10 << PANEL_POWER_DOWN_DELAY_SHIFT);
        /* Compute the divisor for the pp clock, simply match the Bspec
         * formula. */
        pp_div = ((100 * intel_pch_rawclk(dev))/2 - 1)
                        << PP_REFERENCE_DIVIDER_SHIFT;
-       pp_div |= (DIV_ROUND_UP(final.t11_t12, 1000)
+       pp_div |= (DIV_ROUND_UP(seq->t11_t12, 1000)
                        << PANEL_POWER_CYCLE_DELAY_SHIFT);
 
        /* Haswell doesn't have any port selection bits for the panel
@@ -2675,14 +2695,6 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev,
        I915_WRITE(PCH_PP_OFF_DELAYS, pp_off);
        I915_WRITE(PCH_PP_DIVISOR, pp_div);
 
-
-       DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n",
-                     intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay,
-                     intel_dp->panel_power_cycle_delay);
-
-       DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n",
-                     intel_dp->backlight_on_delay, intel_dp->backlight_off_delay);
-
        DRM_DEBUG_KMS("panel power sequencer register settings: PP_ON %#x, PP_OFF %#x, PP_DIV %#x\n",
                      I915_READ(PCH_PP_ON_DELAYS),
                      I915_READ(PCH_PP_OFF_DELAYS),
@@ -2699,6 +2711,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
        struct drm_device *dev = intel_encoder->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_display_mode *fixed_mode = NULL;
+       struct edp_power_seq power_seq = { 0 };
        enum port port = intel_dig_port->port;
        const char *name = NULL;
        int type;
@@ -2771,7 +2784,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
        }
 
        if (is_edp(intel_dp))
-               intel_dp_init_panel_power_sequencer(dev, intel_dp);
+               intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
 
        intel_dp_i2c_init(intel_dp, intel_connector, name);
 
@@ -2798,6 +2811,10 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
                        return;
                }
 
+               /* We now know it's not a ghost, init power sequence regs. */
+               intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
+                                                             &power_seq);
+
                ironlake_edp_panel_vdd_on(intel_dp);
                edid = drm_get_edid(connector, &intel_dp->adapter);
                if (edid) {
index e83a117..3280cff 100644 (file)
@@ -4250,7 +4250,8 @@ static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
 static void __gen6_gt_force_wake_mt_reset(struct drm_i915_private *dev_priv)
 {
        I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(0xffff));
-       POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */
+       /* something from same cacheline, but !FORCEWAKE_MT */
+       POSTING_READ(ECOBUS);
 }
 
 static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
@@ -4267,7 +4268,8 @@ static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
                DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n");
 
        I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL));
-       POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */
+       /* something from same cacheline, but !FORCEWAKE_MT */
+       POSTING_READ(ECOBUS);
 
        if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1),
                            FORCEWAKE_ACK_TIMEOUT_MS))
@@ -4304,14 +4306,16 @@ void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv)
 static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
 {
        I915_WRITE_NOTRACE(FORCEWAKE, 0);
-       /* gen6_gt_check_fifodbg doubles as the POSTING_READ */
+       /* something from same cacheline, but !FORCEWAKE */
+       POSTING_READ(ECOBUS);
        gen6_gt_check_fifodbg(dev_priv);
 }
 
 static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv)
 {
        I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
-       /* gen6_gt_check_fifodbg doubles as the POSTING_READ */
+       /* something from same cacheline, but !FORCEWAKE_MT */
+       POSTING_READ(ECOBUS);
        gen6_gt_check_fifodbg(dev_priv);
 }
 
@@ -4351,6 +4355,8 @@ int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
 static void vlv_force_wake_reset(struct drm_i915_private *dev_priv)
 {
        I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(0xffff));
+       /* something from same cacheline, but !FORCEWAKE_VLV */
+       POSTING_READ(FORCEWAKE_ACK_VLV);
 }
 
 static void vlv_force_wake_get(struct drm_i915_private *dev_priv)
@@ -4371,7 +4377,8 @@ static void vlv_force_wake_get(struct drm_i915_private *dev_priv)
 static void vlv_force_wake_put(struct drm_i915_private *dev_priv)
 {
        I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
-       /* The below doubles as a POSTING_READ */
+       /* something from same cacheline, but !FORCEWAKE_VLV */
+       POSTING_READ(FORCEWAKE_ACK_VLV);
        gen6_gt_check_fifodbg(dev_priv);
 }
 
index 061fa0a..4d0e60a 100644 (file)
@@ -2401,6 +2401,12 @@ static int evergreen_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
 {
        struct evergreen_mc_save save;
 
+       if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE))
+               reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE);
+
+       if (RREG32(DMA_STATUS_REG) & DMA_IDLE)
+               reset_mask &= ~RADEON_RESET_DMA;
+
        if (reset_mask == 0)
                return 0;
 
index 896f1cb..59acabb 100644 (file)
@@ -1409,6 +1409,12 @@ static int cayman_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
 {
        struct evergreen_mc_save save;
 
+       if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE))
+               reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE);
+
+       if (RREG32(DMA_STATUS_REG) & DMA_IDLE)
+               reset_mask &= ~RADEON_RESET_DMA;
+
        if (reset_mask == 0)
                return 0;
 
index 537e259..3cb9d60 100644 (file)
@@ -1378,6 +1378,12 @@ static int r600_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
 {
        struct rv515_mc_save save;
 
+       if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE))
+               reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE);
+
+       if (RREG32(DMA_STATUS_REG) & DMA_IDLE)
+               reset_mask &= ~RADEON_RESET_DMA;
+
        if (reset_mask == 0)
                return 0;
 
index 34e5230..a08f657 100644 (file)
@@ -324,7 +324,6 @@ struct radeon_bo {
        struct list_head                list;
        /* Protected by tbo.reserved */
        u32                             placements[3];
-       u32                             busy_placements[3];
        struct ttm_placement            placement;
        struct ttm_buffer_object        tbo;
        struct ttm_bo_kmap_obj          kmap;
@@ -654,6 +653,8 @@ struct radeon_ring {
        u32                     ptr_reg_mask;
        u32                     nop;
        u32                     idx;
+       u64                     last_semaphore_signal_addr;
+       u64                     last_semaphore_wait_addr;
 };
 
 /*
index dff6cf7..d9bf96e 100644 (file)
  *   2.26.0 - r600-eg: fix htile size computation
  *   2.27.0 - r600-SI: Add CS ioctl support for async DMA
  *   2.28.0 - r600-eg: Add MEM_WRITE packet support
+ *   2.29.0 - R500 FP16 color clear registers
  */
 #define KMS_DRIVER_MAJOR       2
-#define KMS_DRIVER_MINOR       28
+#define KMS_DRIVER_MINOR       29
 #define KMS_DRIVER_PATCHLEVEL  0
 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
 int radeon_driver_unload_kms(struct drm_device *dev);
index 883c95d..d3aface 100644 (file)
@@ -84,6 +84,7 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain)
        rbo->placement.fpfn = 0;
        rbo->placement.lpfn = 0;
        rbo->placement.placement = rbo->placements;
+       rbo->placement.busy_placement = rbo->placements;
        if (domain & RADEON_GEM_DOMAIN_VRAM)
                rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED |
                                        TTM_PL_FLAG_VRAM;
@@ -104,14 +105,6 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain)
        if (!c)
                rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
        rbo->placement.num_placement = c;
-
-       c = 0;
-       rbo->placement.busy_placement = rbo->busy_placements;
-       if (rbo->rdev->flags & RADEON_IS_AGP) {
-               rbo->busy_placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_TT;
-       } else {
-               rbo->busy_placements[c++] = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_TT;
-       }
        rbo->placement.num_busy_placement = c;
 }
 
@@ -357,6 +350,7 @@ int radeon_bo_list_validate(struct list_head *head)
 {
        struct radeon_bo_list *lobj;
        struct radeon_bo *bo;
+       u32 domain;
        int r;
 
        r = ttm_eu_reserve_buffers(head);
@@ -366,9 +360,17 @@ int radeon_bo_list_validate(struct list_head *head)
        list_for_each_entry(lobj, head, tv.head) {
                bo = lobj->bo;
                if (!bo->pin_count) {
+                       domain = lobj->wdomain ? lobj->wdomain : lobj->rdomain;
+                       
+               retry:
+                       radeon_ttm_placement_from_domain(bo, domain);
                        r = ttm_bo_validate(&bo->tbo, &bo->placement,
                                                true, false);
                        if (unlikely(r)) {
+                               if (r != -ERESTARTSYS && domain == RADEON_GEM_DOMAIN_VRAM) {
+                                       domain |= RADEON_GEM_DOMAIN_GTT;
+                                       goto retry;
+                               }
                                return r;
                        }
                }
index 141f2b6..2430d80 100644 (file)
@@ -784,6 +784,8 @@ static int radeon_debugfs_ring_info(struct seq_file *m, void *data)
        }
        seq_printf(m, "driver's copy of the wptr: 0x%08x [%5d]\n", ring->wptr, ring->wptr);
        seq_printf(m, "driver's copy of the rptr: 0x%08x [%5d]\n", ring->rptr, ring->rptr);
+       seq_printf(m, "last semaphore signal addr : 0x%016llx\n", ring->last_semaphore_signal_addr);
+       seq_printf(m, "last semaphore wait addr   : 0x%016llx\n", ring->last_semaphore_wait_addr);
        seq_printf(m, "%u free dwords in ring\n", ring->ring_free_dw);
        seq_printf(m, "%u dwords in ring\n", count);
        /* print 8 dw before current rptr as often it's the last executed
index 97f3ece..8dcc20f 100644 (file)
@@ -95,6 +95,10 @@ int radeon_semaphore_sync_rings(struct radeon_device *rdev,
        /* we assume caller has already allocated space on waiters ring */
        radeon_semaphore_emit_wait(rdev, waiter, semaphore);
 
+       /* for debugging lockup only, used by sysfs debug files */
+       rdev->ring[signaler].last_semaphore_signal_addr = semaphore->gpu_addr;
+       rdev->ring[waiter].last_semaphore_wait_addr = semaphore->gpu_addr;
+
        return 0;
 }
 
index 911a8fb..78d5e99 100644 (file)
@@ -324,6 +324,8 @@ rv515 0x6d40
 0x46AC US_OUT_FMT_2
 0x46B0 US_OUT_FMT_3
 0x46B4 US_W_FMT
+0x46C0 RB3D_COLOR_CLEAR_VALUE_AR
+0x46C4 RB3D_COLOR_CLEAR_VALUE_GB
 0x4BC0 FG_FOG_BLEND
 0x4BC4 FG_FOG_FACTOR
 0x4BC8 FG_FOG_COLOR_R
index 3240a3d..ae8b482 100644 (file)
@@ -2215,6 +2215,12 @@ static int si_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
 {
        struct evergreen_mc_save save;
 
+       if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE))
+               reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE);
+
+       if (RREG32(DMA_STATUS_REG) & DMA_IDLE)
+               reset_mask &= ~RADEON_RESET_DMA;
+
        if (reset_mask == 0)
                return 0;
 
index 33d20be..52b20b1 100644 (file)
@@ -434,6 +434,7 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo,
                        bo->mem = tmp_mem;
                        bdev->driver->move_notify(bo, mem);
                        bo->mem = *mem;
+                       *mem = tmp_mem;
                }
 
                goto out_err;
index d73d6e3..44420fc 100644 (file)
@@ -344,8 +344,12 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo,
 
        if (ttm->state == tt_unpopulated) {
                ret = ttm->bdev->driver->ttm_tt_populate(ttm);
-               if (ret)
+               if (ret) {
+                       /* if we fail here don't nuke the mm node
+                        * as the bo still owns it */
+                       old_copy.mm_node = NULL;
                        goto out1;
+               }
        }
 
        add = 0;
@@ -371,8 +375,11 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo,
                                                   prot);
                } else
                        ret = ttm_copy_io_page(new_iomap, old_iomap, page);
-               if (ret)
+               if (ret) {
+                       /* failing here, means keep old copy as-is */
+                       old_copy.mm_node = NULL;
                        goto out1;
+               }
        }
        mb();
 out2:
index f6c0011..dd289fd 100644 (file)
@@ -403,7 +403,7 @@ struct dm_info_header {
  */
 
 struct dm_info_msg {
-       struct dm_info_header header;
+       struct dm_header hdr;
        __u32 reserved;
        __u32 info_size;
        __u8  info[];
@@ -503,13 +503,17 @@ static void hot_add_req(struct hv_dynmem_device *dm, struct dm_hot_add *msg)
 
 static void process_info(struct hv_dynmem_device *dm, struct dm_info_msg *msg)
 {
-       switch (msg->header.type) {
+       struct dm_info_header *info_hdr;
+
+       info_hdr = (struct dm_info_header *)msg->info;
+
+       switch (info_hdr->type) {
        case INFO_TYPE_MAX_PAGE_CNT:
                pr_info("Received INFO_TYPE_MAX_PAGE_CNT\n");
-               pr_info("Data Size is %d\n", msg->header.data_size);
+               pr_info("Data Size is %d\n", info_hdr->data_size);
                break;
        default:
-               pr_info("Received Unknown type: %d\n", msg->header.type);
+               pr_info("Received Unknown type: %d\n", info_hdr->type);
        }
 }
 
@@ -879,7 +883,7 @@ static int balloon_probe(struct hv_device *dev,
                        balloon_onchannelcallback, dev);
 
        if (ret)
-               return ret;
+               goto probe_error0;
 
        dm_device.dev = dev;
        dm_device.state = DM_INITIALIZING;
@@ -891,7 +895,7 @@ static int balloon_probe(struct hv_device *dev,
                 kthread_run(dm_thread_func, &dm_device, "hv_balloon");
        if (IS_ERR(dm_device.thread)) {
                ret = PTR_ERR(dm_device.thread);
-               goto probe_error0;
+               goto probe_error1;
        }
 
        hv_set_drvdata(dev, &dm_device);
@@ -914,12 +918,12 @@ static int balloon_probe(struct hv_device *dev,
                                VM_PKT_DATA_INBAND,
                                VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
        if (ret)
-               goto probe_error1;
+               goto probe_error2;
 
        t = wait_for_completion_timeout(&dm_device.host_event, 5*HZ);
        if (t == 0) {
                ret = -ETIMEDOUT;
-               goto probe_error1;
+               goto probe_error2;
        }
 
        /*
@@ -928,7 +932,7 @@ static int balloon_probe(struct hv_device *dev,
         */
        if (dm_device.state == DM_INIT_ERROR) {
                ret = -ETIMEDOUT;
-               goto probe_error1;
+               goto probe_error2;
        }
        /*
         * Now submit our capabilities to the host.
@@ -961,12 +965,12 @@ static int balloon_probe(struct hv_device *dev,
                                VM_PKT_DATA_INBAND,
                                VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
        if (ret)
-               goto probe_error1;
+               goto probe_error2;
 
        t = wait_for_completion_timeout(&dm_device.host_event, 5*HZ);
        if (t == 0) {
                ret = -ETIMEDOUT;
-               goto probe_error1;
+               goto probe_error2;
        }
 
        /*
@@ -975,18 +979,20 @@ static int balloon_probe(struct hv_device *dev,
         */
        if (dm_device.state == DM_INIT_ERROR) {
                ret = -ETIMEDOUT;
-               goto probe_error1;
+               goto probe_error2;
        }
 
        dm_device.state = DM_INITIALIZED;
 
        return 0;
 
-probe_error1:
+probe_error2:
        kthread_stop(dm_device.thread);
 
-probe_error0:
+probe_error1:
        vmbus_close(dev->channel);
+probe_error0:
+       kfree(send_buffer);
        return ret;
 }
 
@@ -999,6 +1005,7 @@ static int balloon_remove(struct hv_device *dev)
 
        vmbus_close(dev->channel);
        kthread_stop(dm->thread);
+       kfree(send_buffer);
 
        return 0;
 }
index cbba7db..f5258c2 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/io.h>
 #include <linux/pm_runtime.h>
 #include <linux/delay.h>
+#include <linux/module.h>
 #include "i2c-designware-core.h"
 
 /*
@@ -725,3 +726,6 @@ u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev)
        return dw_readl(dev, DW_IC_COMP_PARAM_1);
 }
 EXPORT_SYMBOL_GPL(i2c_dw_read_comp_param);
+
+MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter core");
+MODULE_LICENSE("GPL");
index 1b1a936..d6abaf2 100644 (file)
@@ -127,7 +127,7 @@ struct mxs_i2c_dev {
        struct device *dev;
        void __iomem *regs;
        struct completion cmd_complete;
-       u32 cmd_err;
+       int cmd_err;
        struct i2c_adapter adapter;
        const struct mxs_i2c_speed_config *speed;
 
@@ -316,7 +316,7 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
        if (msg->len == 0)
                return -EINVAL;
 
-       init_completion(&i2c->cmd_complete);
+       INIT_COMPLETION(i2c->cmd_complete);
        i2c->cmd_err = 0;
 
        ret = mxs_i2c_dma_setup_xfer(adap, msg, flags);
@@ -473,6 +473,8 @@ static int mxs_i2c_probe(struct platform_device *pdev)
        i2c->dev = dev;
        i2c->speed = &mxs_i2c_95kHz_config;
 
+       init_completion(&i2c->cmd_complete);
+
        if (dev->of_node) {
                err = mxs_i2c_get_ofdata(i2c);
                if (err)
index 20d41bf..4cc2f05 100644 (file)
@@ -803,7 +803,7 @@ static int errata_omap3_i462(struct omap_i2c_dev *dev)
                        if (stat & OMAP_I2C_STAT_AL) {
                                dev_err(dev->dev, "Arbitration lost\n");
                                dev->cmd_err |= OMAP_I2C_STAT_AL;
-                               omap_i2c_ack_stat(dev, OMAP_I2C_STAT_NACK);
+                               omap_i2c_ack_stat(dev, OMAP_I2C_STAT_AL);
                        }
 
                        return -EIO;
@@ -963,7 +963,7 @@ omap_i2c_isr_thread(int this_irq, void *dev_id)
                                i2c_omap_errata_i207(dev, stat);
 
                        omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RDR);
-                       break;
+                       continue;
                }
 
                if (stat & OMAP_I2C_STAT_RRDY) {
@@ -989,7 +989,7 @@ omap_i2c_isr_thread(int this_irq, void *dev_id)
                                break;
 
                        omap_i2c_ack_stat(dev, OMAP_I2C_STAT_XDR);
-                       break;
+                       continue;
                }
 
                if (stat & OMAP_I2C_STAT_XRDY) {
index 3f1818b..e03381a 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/slab.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
+#include <linux/of_i2c.h>
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/io.h>
@@ -328,6 +329,7 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev)
        adap->algo = &i2c_sirfsoc_algo;
        adap->algo_data = siic;
 
+       adap->dev.of_node = pdev->dev.of_node;
        adap->dev.parent = &pdev->dev;
        adap->nr = pdev->id;
 
@@ -371,6 +373,8 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev)
 
        clk_disable(clk);
 
+       of_i2c_register_devices(adap);
+
        dev_info(&pdev->dev, " I2C adapter ready to operate\n");
 
        return 0;
index 1e44d04..a43c0ce 100644 (file)
@@ -167,7 +167,7 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev)
        }
 
        mux->busses = devm_kzalloc(&pdev->dev,
-                                  sizeof(mux->busses) * mux->pdata->bus_count,
+                                  sizeof(*mux->busses) * mux->pdata->bus_count,
                                   GFP_KERNEL);
        if (!mux->busses) {
                dev_err(&pdev->dev, "Cannot allocate busses\n");
index 4ba384f..2df9414 100644 (file)
@@ -448,8 +448,6 @@ static int intel_idle_probe(void)
        else
                on_each_cpu(__setup_broadcast_timer, (void *)true, 1);
 
-       register_cpu_notifier(&cpu_hotplug_notifier);
-
        pr_debug(PREFIX "v" INTEL_IDLE_VERSION
                " model 0x%X\n", boot_cpu_data.x86_model);
 
@@ -612,6 +610,7 @@ static int __init intel_idle_init(void)
                        return retval;
                }
        }
+       register_cpu_notifier(&cpu_hotplug_notifier);
 
        return 0;
 }
index 8a8d42f..d4e7567 100644 (file)
@@ -556,7 +556,7 @@ static int m5mols_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        mutex_lock(&info->lock);
 
        format = __find_format(info, fh, fmt->which, info->res_type);
-       if (!format)
+       if (format)
                fmt->format = *format;
        else
                ret = -EINVAL;
index 1cf8293..4a980e0 100644 (file)
@@ -23,8 +23,8 @@
 #include <linux/slab.h>
 #include <linux/videodev2.h>
 #include <linux/of.h>
+#include <linux/platform_data/imx-iram.h>
 
-#include <mach/iram.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
index e0d73a6..8dac175 100644 (file)
@@ -35,9 +35,6 @@
 #include <linux/vmalloc.h>
 #include <media/v4l2-dev.h>
 #include <media/v4l2-ioctl.h>
-#include <plat/iommu.h>
-#include <plat/iovmm.h>
-#include <plat/omap-pm.h>
 
 #include "ispvideo.h"
 #include "isp.h"
index 4ab99f3..b4a68ec 100644 (file)
@@ -593,7 +593,7 @@ static int __fimc_md_create_flite_source_links(struct fimc_md *fmd)
 {
        struct media_entity *source, *sink;
        unsigned int flags = MEDIA_LNK_FL_ENABLED;
-       int i, ret;
+       int i, ret = 0;
 
        for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) {
                struct fimc_lite *fimc = fmd->fimc_lite[i];
index 379f574..681bc6b 100644 (file)
@@ -412,62 +412,48 @@ leave_handle_frame:
 }
 
 /* Error handling for interrupt */
-static void s5p_mfc_handle_error(struct s5p_mfc_ctx *ctx,
-                                unsigned int reason, unsigned int err)
+static void s5p_mfc_handle_error(struct s5p_mfc_dev *dev,
+               struct s5p_mfc_ctx *ctx, unsigned int reason, unsigned int err)
 {
-       struct s5p_mfc_dev *dev;
        unsigned long flags;
 
-       /* If no context is available then all necessary
-        * processing has been done. */
-       if (ctx == NULL)
-               return;
-
-       dev = ctx->dev;
        mfc_err("Interrupt Error: %08x\n", err);
-       s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
-       wake_up_dev(dev, reason, err);
 
-       /* Error recovery is dependent on the state of context */
-       switch (ctx->state) {
-       case MFCINST_INIT:
-               /* This error had to happen while acquireing instance */
-       case MFCINST_GOT_INST:
-               /* This error had to happen while parsing the header */
-       case MFCINST_HEAD_PARSED:
-               /* This error had to happen while setting dst buffers */
-       case MFCINST_RETURN_INST:
-               /* This error had to happen while releasing instance */
-               clear_work_bit(ctx);
-               wake_up_ctx(ctx, reason, err);
-               if (test_and_clear_bit(0, &dev->hw_lock) == 0)
-                       BUG();
-               s5p_mfc_clock_off();
-               ctx->state = MFCINST_ERROR;
-               break;
-       case MFCINST_FINISHING:
-       case MFCINST_FINISHED:
-       case MFCINST_RUNNING:
-               /* It is higly probable that an error occured
-                * while decoding a frame */
-               clear_work_bit(ctx);
-               ctx->state = MFCINST_ERROR;
-               /* Mark all dst buffers as having an error */
-               spin_lock_irqsave(&dev->irqlock, flags);
-               s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue,
-                               &ctx->vq_dst);
-               /* Mark all src buffers as having an error */
-               s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue,
-                               &ctx->vq_src);
-               spin_unlock_irqrestore(&dev->irqlock, flags);
-               if (test_and_clear_bit(0, &dev->hw_lock) == 0)
-                       BUG();
-               s5p_mfc_clock_off();
-               break;
-       default:
-               mfc_err("Encountered an error interrupt which had not been handled\n");
-               break;
+       if (ctx != NULL) {
+               /* Error recovery is dependent on the state of context */
+               switch (ctx->state) {
+               case MFCINST_RES_CHANGE_INIT:
+               case MFCINST_RES_CHANGE_FLUSH:
+               case MFCINST_RES_CHANGE_END:
+               case MFCINST_FINISHING:
+               case MFCINST_FINISHED:
+               case MFCINST_RUNNING:
+                       /* It is higly probable that an error occured
+                        * while decoding a frame */
+                       clear_work_bit(ctx);
+                       ctx->state = MFCINST_ERROR;
+                       /* Mark all dst buffers as having an error */
+                       spin_lock_irqsave(&dev->irqlock, flags);
+                       s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue,
+                                               &ctx->dst_queue, &ctx->vq_dst);
+                       /* Mark all src buffers as having an error */
+                       s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue,
+                                               &ctx->src_queue, &ctx->vq_src);
+                       spin_unlock_irqrestore(&dev->irqlock, flags);
+                       wake_up_ctx(ctx, reason, err);
+                       break;
+               default:
+                       clear_work_bit(ctx);
+                       ctx->state = MFCINST_ERROR;
+                       wake_up_ctx(ctx, reason, err);
+                       break;
+               }
        }
+       if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+               BUG();
+       s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
+       s5p_mfc_clock_off();
+       wake_up_dev(dev, reason, err);
        return;
 }
 
@@ -632,7 +618,7 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv)
                                dev->warn_start)
                        s5p_mfc_handle_frame(ctx, reason, err);
                else
-                       s5p_mfc_handle_error(ctx, reason, err);
+                       s5p_mfc_handle_error(dev, ctx, reason, err);
                clear_bit(0, &dev->enter_suspend);
                break;
 
index 40ad668..3773a8a 100644 (file)
@@ -381,6 +381,7 @@ static const struct sd_desc sd_desc = {
 /* -- module initialisation -- */
 static const struct usb_device_id device_table[] = {
        {USB_DEVICE(0x045e, 0x02ae)},
+       {USB_DEVICE(0x045e, 0x02bf)},
        {}
 };
 
index 70511d5..1220340 100644 (file)
@@ -496,7 +496,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
        }
 }
 
-static void i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
+static void i2c_w(struct gspca_dev *gspca_dev, const u8 *buf)
 {
        int retry = 60;
 
@@ -504,16 +504,19 @@ static void i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
                return;
 
        /* is i2c ready */
-       reg_w(gspca_dev, 0x08, buffer, 8);
+       reg_w(gspca_dev, 0x08, buf, 8);
        while (retry--) {
                if (gspca_dev->usb_err < 0)
                        return;
-               msleep(10);
+               msleep(1);
                reg_r(gspca_dev, 0x08);
                if (gspca_dev->usb_buf[0] & 0x04) {
                        if (gspca_dev->usb_buf[0] & 0x08) {
                                dev_err(gspca_dev->v4l2_dev.dev,
-                                       "i2c write error\n");
+                                       "i2c error writing %02x %02x %02x %02x"
+                                       " %02x %02x %02x %02x\n",
+                                       buf[0], buf[1], buf[2], buf[3],
+                                       buf[4], buf[5], buf[6], buf[7]);
                                gspca_dev->usb_err = -EIO;
                        }
                        return;
@@ -530,7 +533,7 @@ static void i2c_w_vector(struct gspca_dev *gspca_dev,
        for (;;) {
                if (gspca_dev->usb_err < 0)
                        return;
-               reg_w(gspca_dev, 0x08, *buffer, 8);
+               i2c_w(gspca_dev, *buffer);
                len -= 8;
                if (len <= 0)
                        break;
index 5a86047..36307a9 100644 (file)
@@ -1550,6 +1550,7 @@ static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
                        0,
                        gspca_dev->usb_buf, 8,
                        500);
+       msleep(2);
        if (ret < 0) {
                pr_err("i2c_w1 err %d\n", ret);
                gspca_dev->usb_err = ret;
index 2bb7613..d5baab1 100644 (file)
@@ -1431,8 +1431,10 @@ int uvc_ctrl_set(struct uvc_video_chain *chain,
        int ret;
 
        ctrl = uvc_find_control(chain, xctrl->id, &mapping);
-       if (ctrl == NULL || (ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR) == 0)
+       if (ctrl == NULL)
                return -EINVAL;
+       if (!(ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR))
+               return -EACCES;
 
        /* Clamp out of range values. */
        switch (mapping->v4l2_type) {
index f2ee8c6..68d59b5 100644 (file)
@@ -657,8 +657,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
                        ret = uvc_ctrl_get(chain, ctrl);
                        if (ret < 0) {
                                uvc_ctrl_rollback(handle);
-                               ctrls->error_idx = ret == -ENOENT
-                                                ? ctrls->count : i;
+                               ctrls->error_idx = i;
                                return ret;
                        }
                }
@@ -686,8 +685,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
                        ret = uvc_ctrl_set(chain, ctrl);
                        if (ret < 0) {
                                uvc_ctrl_rollback(handle);
-                               ctrls->error_idx = (ret == -ENOENT &&
-                                                   cmd == VIDIOC_S_EXT_CTRLS)
+                               ctrls->error_idx = cmd == VIDIOC_S_EXT_CTRLS
                                                 ? ctrls->count : i;
                                return ret;
                        }
index 9f81be2..e02c479 100644 (file)
@@ -921,8 +921,10 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
                 * In videobuf we use our internal V4l2_planes struct for
                 * single-planar buffers as well, for simplicity.
                 */
-               if (V4L2_TYPE_IS_OUTPUT(b->type))
+               if (V4L2_TYPE_IS_OUTPUT(b->type)) {
                        v4l2_planes[0].bytesused = b->bytesused;
+                       v4l2_planes[0].data_offset = 0;
+               }
 
                if (b->memory == V4L2_MEMORY_USERPTR) {
                        v4l2_planes[0].m.userptr = b->m.userptr;
index e5d8f63..77048b1 100644 (file)
@@ -313,19 +313,11 @@ static void vexpress_sysreg_config_complete(unsigned long data)
 }
 
 
-void __init vexpress_sysreg_early_init(void __iomem *base)
+void __init vexpress_sysreg_setup(struct device_node *node)
 {
-       struct device_node *node = of_find_compatible_node(NULL, NULL,
-                       "arm,vexpress-sysreg");
-
-       if (node)
-               base = of_iomap(node, 0);
-
-       if (WARN_ON(!base))
+       if (WARN_ON(!vexpress_sysreg_base))
                return;
 
-       vexpress_sysreg_base = base;
-
        if (readl(vexpress_sysreg_base + SYS_MISC) & SYS_MISC_MASTERSITE)
                vexpress_master_site = VEXPRESS_SITE_DB2;
        else
@@ -336,9 +328,23 @@ void __init vexpress_sysreg_early_init(void __iomem *base)
        WARN_ON(!vexpress_sysreg_config_bridge);
 }
 
+void __init vexpress_sysreg_early_init(void __iomem *base)
+{
+       vexpress_sysreg_base = base;
+       vexpress_sysreg_setup(NULL);
+}
+
 void __init vexpress_sysreg_of_early_init(void)
 {
-       vexpress_sysreg_early_init(NULL);
+       struct device_node *node = of_find_compatible_node(NULL, NULL,
+                       "arm,vexpress-sysreg");
+
+       if (node) {
+               vexpress_sysreg_base = of_iomap(node, 0);
+               vexpress_sysreg_setup(node);
+       } else {
+               pr_info("vexpress-sysreg: No Device Tree node found.");
+       }
 }
 
 
@@ -426,9 +432,11 @@ static int vexpress_sysreg_probe(struct platform_device *pdev)
                return -EBUSY;
        }
 
-       if (!vexpress_sysreg_base)
+       if (!vexpress_sysreg_base) {
                vexpress_sysreg_base = devm_ioremap(&pdev->dev, res->start,
                                resource_size(res));
+               vexpress_sysreg_setup(pdev->dev.of_node);
+       }
 
        if (!vexpress_sysreg_base) {
                dev_err(&pdev->dev, "Failed to obtain base address!\n");
index 9ff942a..83269f1 100644 (file)
@@ -468,6 +468,11 @@ long st_kim_start(void *kim_data)
                if (pdata->chip_enable)
                        pdata->chip_enable(kim_gdata);
 
+               /* Configure BT nShutdown to HIGH state */
+               gpio_set_value(kim_gdata->nshutdown, GPIO_LOW);
+               mdelay(5);      /* FIXME: a proper toggle */
+               gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH);
+               mdelay(100);
                /* re-initialize the completion */
                INIT_COMPLETION(kim_gdata->ldisc_installed);
                /* send notification to UIM */
@@ -509,7 +514,8 @@ long st_kim_start(void *kim_data)
  *     (b) upon failure to either install ldisc or download firmware.
  *     The function is responsible to (a) notify UIM about un-installation,
  *     (b) flush UART if the ldisc was installed.
- *     (c) invoke platform's chip disabling routine.
+ *     (c) reset BT_EN - pull down nshutdown at the end.
+ *     (d) invoke platform's chip disabling routine.
  */
 long st_kim_stop(void *kim_data)
 {
@@ -541,6 +547,13 @@ long st_kim_stop(void *kim_data)
                err = -ETIMEDOUT;
        }
 
+       /* By default configure BT nShutdown to LOW state */
+       gpio_set_value(kim_gdata->nshutdown, GPIO_LOW);
+       mdelay(1);
+       gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH);
+       mdelay(1);
+       gpio_set_value(kim_gdata->nshutdown, GPIO_LOW);
+
        /* platform specific disable */
        if (pdata->chip_disable)
                pdata->chip_disable(kim_gdata);
@@ -733,6 +746,20 @@ static int kim_probe(struct platform_device *pdev)
        /* refer to itself */
        kim_gdata->core_data->kim_data = kim_gdata;
 
+       /* Claim the chip enable nShutdown gpio from the system */
+       kim_gdata->nshutdown = pdata->nshutdown_gpio;
+       err = gpio_request(kim_gdata->nshutdown, "kim");
+       if (unlikely(err)) {
+               pr_err(" gpio %ld request failed ", kim_gdata->nshutdown);
+               return err;
+       }
+
+       /* Configure nShutdown GPIO as output=0 */
+       err = gpio_direction_output(kim_gdata->nshutdown, 0);
+       if (unlikely(err)) {
+               pr_err(" unable to configure gpio %ld", kim_gdata->nshutdown);
+               return err;
+       }
        /* get reference of pdev for request_firmware
         */
        kim_gdata->kim_pdev = pdev;
@@ -779,10 +806,18 @@ err_core_init:
 
 static int kim_remove(struct platform_device *pdev)
 {
+       /* free the GPIOs requested */
+       struct ti_st_plat_data  *pdata = pdev->dev.platform_data;
        struct kim_data_s       *kim_gdata;
 
        kim_gdata = dev_get_drvdata(&pdev->dev);
 
+       /* Free the Bluetooth/FM/GPIO
+        * nShutdown gpio from the system
+        */
+       gpio_free(pdata->nshutdown_gpio);
+       pr_info("nshutdown GPIO Freed");
+
        debugfs_remove_recursive(kim_debugfs_dir);
        sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp);
        pr_info("sysfs entries removed");
index de4c20b..f8dd361 100644 (file)
@@ -50,8 +50,6 @@ struct mvsd_host {
        struct timer_list timer;
        struct mmc_host *mmc;
        struct device *dev;
-       struct resource *res;
-       int irq;
        struct clk *clk;
        int gpio_card_detect;
        int gpio_write_protect;
@@ -718,10 +716,6 @@ static int __init mvsd_probe(struct platform_device *pdev)
        if (!r || irq < 0 || !mvsd_data)
                return -ENXIO;
 
-       r = request_mem_region(r->start, SZ_1K, DRIVER_NAME);
-       if (!r)
-               return -EBUSY;
-
        mmc = mmc_alloc_host(sizeof(struct mvsd_host), &pdev->dev);
        if (!mmc) {
                ret = -ENOMEM;
@@ -731,8 +725,8 @@ static int __init mvsd_probe(struct platform_device *pdev)
        host = mmc_priv(mmc);
        host->mmc = mmc;
        host->dev = &pdev->dev;
-       host->res = r;
        host->base_clock = mvsd_data->clock / 2;
+       host->clk = ERR_PTR(-EINVAL);
 
        mmc->ops = &mvsd_ops;
 
@@ -752,7 +746,7 @@ static int __init mvsd_probe(struct platform_device *pdev)
 
        spin_lock_init(&host->lock);
 
-       host->base = ioremap(r->start, SZ_4K);
+       host->base = devm_request_and_ioremap(&pdev->dev, r);
        if (!host->base) {
                ret = -ENOMEM;
                goto out;
@@ -765,44 +759,45 @@ static int __init mvsd_probe(struct platform_device *pdev)
 
        mvsd_power_down(host);
 
-       ret = request_irq(irq, mvsd_irq, 0, DRIVER_NAME, host);
+       ret = devm_request_irq(&pdev->dev, irq, mvsd_irq, 0, DRIVER_NAME, host);
        if (ret) {
                pr_err("%s: cannot assign irq %d\n", DRIVER_NAME, irq);
                goto out;
-       } else
-               host->irq = irq;
+       }
 
        /* Not all platforms can gate the clock, so it is not
           an error if the clock does not exists. */
-       host->clk = clk_get(&pdev->dev, NULL);
-       if (!IS_ERR(host->clk)) {
+       host->clk = devm_clk_get(&pdev->dev, NULL);
+       if (!IS_ERR(host->clk))
                clk_prepare_enable(host->clk);
-       }
 
        if (mvsd_data->gpio_card_detect) {
-               ret = gpio_request(mvsd_data->gpio_card_detect,
-                                  DRIVER_NAME " cd");
+               ret = devm_gpio_request_one(&pdev->dev,
+                                           mvsd_data->gpio_card_detect,
+                                           GPIOF_IN, DRIVER_NAME " cd");
                if (ret == 0) {
-                       gpio_direction_input(mvsd_data->gpio_card_detect);
                        irq = gpio_to_irq(mvsd_data->gpio_card_detect);
-                       ret = request_irq(irq, mvsd_card_detect_irq,
-                                         IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING,
-                                         DRIVER_NAME " cd", host);
+                       ret = devm_request_irq(&pdev->dev, irq,
+                                              mvsd_card_detect_irq,
+                                              IRQ_TYPE_EDGE_RISING |
+                                              IRQ_TYPE_EDGE_FALLING,
+                                              DRIVER_NAME " cd", host);
                        if (ret == 0)
                                host->gpio_card_detect =
                                        mvsd_data->gpio_card_detect;
                        else
-                               gpio_free(mvsd_data->gpio_card_detect);
+                               devm_gpio_free(&pdev->dev,
+                                              mvsd_data->gpio_card_detect);
                }
        }
        if (!host->gpio_card_detect)
                mmc->caps |= MMC_CAP_NEEDS_POLL;
 
        if (mvsd_data->gpio_write_protect) {
-               ret = gpio_request(mvsd_data->gpio_write_protect,
-                                  DRIVER_NAME " wp");
+               ret = devm_gpio_request_one(&pdev->dev,
+                                           mvsd_data->gpio_write_protect,
+                                           GPIOF_IN, DRIVER_NAME " wp");
                if (ret == 0) {
-                       gpio_direction_input(mvsd_data->gpio_write_protect);
                        host->gpio_write_protect =
                                mvsd_data->gpio_write_protect;
                }
@@ -824,26 +819,11 @@ static int __init mvsd_probe(struct platform_device *pdev)
        return 0;
 
 out:
-       if (host) {
-               if (host->irq)
-                       free_irq(host->irq, host);
-               if (host->gpio_card_detect) {
-                       free_irq(gpio_to_irq(host->gpio_card_detect), host);
-                       gpio_free(host->gpio_card_detect);
-               }
-               if (host->gpio_write_protect)
-                       gpio_free(host->gpio_write_protect);
-               if (host->base)
-                       iounmap(host->base);
-       }
-       if (r)
-               release_resource(r);
-       if (mmc)
-               if (!IS_ERR_OR_NULL(host->clk)) {
+       if (mmc) {
+               if (!IS_ERR(host->clk))
                        clk_disable_unprepare(host->clk);
-                       clk_put(host->clk);
-               }
                mmc_free_host(mmc);
+       }
 
        return ret;
 }
@@ -852,28 +832,16 @@ static int __exit mvsd_remove(struct platform_device *pdev)
 {
        struct mmc_host *mmc = platform_get_drvdata(pdev);
 
-       if (mmc) {
-               struct mvsd_host *host = mmc_priv(mmc);
+       struct mvsd_host *host = mmc_priv(mmc);
 
-               if (host->gpio_card_detect) {
-                       free_irq(gpio_to_irq(host->gpio_card_detect), host);
-                       gpio_free(host->gpio_card_detect);
-               }
-               mmc_remove_host(mmc);
-               free_irq(host->irq, host);
-               if (host->gpio_write_protect)
-                       gpio_free(host->gpio_write_protect);
-               del_timer_sync(&host->timer);
-               mvsd_power_down(host);
-               iounmap(host->base);
-               release_resource(host->res);
+       mmc_remove_host(mmc);
+       del_timer_sync(&host->timer);
+       mvsd_power_down(host);
+
+       if (!IS_ERR(host->clk))
+               clk_disable_unprepare(host->clk);
+       mmc_free_host(mmc);
 
-               if (!IS_ERR(host->clk)) {
-                       clk_disable_unprepare(host->clk);
-                       clk_put(host->clk);
-               }
-               mmc_free_host(mmc);
-       }
        platform_set_drvdata(pdev, NULL);
        return 0;
 }
index 26ffd3e..2c113de 100644 (file)
@@ -44,7 +44,6 @@ extern bool pciehp_poll_mode;
 extern int pciehp_poll_time;
 extern bool pciehp_debug;
 extern bool pciehp_force;
-extern struct workqueue_struct *pciehp_wq;
 
 #define dbg(format, arg...)                                            \
 do {                                                                   \
@@ -78,6 +77,7 @@ struct slot {
        struct hotplug_slot *hotplug_slot;
        struct delayed_work work;       /* work for button event */
        struct mutex lock;
+       struct workqueue_struct *wq;
 };
 
 struct event_info {
index 916bf4f..939bd1d 100644 (file)
@@ -42,7 +42,6 @@ bool pciehp_debug;
 bool pciehp_poll_mode;
 int pciehp_poll_time;
 bool pciehp_force;
-struct workqueue_struct *pciehp_wq;
 
 #define DRIVER_VERSION "0.4"
 #define DRIVER_AUTHOR  "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
@@ -340,18 +339,13 @@ static int __init pcied_init(void)
 {
        int retval = 0;
 
-       pciehp_wq = alloc_workqueue("pciehp", 0, 0);
-       if (!pciehp_wq)
-               return -ENOMEM;
-
        pciehp_firmware_init();
        retval = pcie_port_service_register(&hpdriver_portdrv);
        dbg("pcie_port_service_register = %d\n", retval);
        info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
-       if (retval) {
-               destroy_workqueue(pciehp_wq);
+       if (retval)
                dbg("Failure to register service\n");
-       }
+
        return retval;
 }
 
@@ -359,7 +353,6 @@ static void __exit pcied_cleanup(void)
 {
        dbg("unload_pciehpd()\n");
        pcie_port_service_unregister(&hpdriver_portdrv);
-       destroy_workqueue(pciehp_wq);
        info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
 }
 
index 27f4429..38f0186 100644 (file)
@@ -49,7 +49,7 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
        info->p_slot = p_slot;
        INIT_WORK(&info->work, interrupt_event_handler);
 
-       queue_work(pciehp_wq, &info->work);
+       queue_work(p_slot->wq, &info->work);
 
        return 0;
 }
@@ -344,7 +344,7 @@ void pciehp_queue_pushbutton_work(struct work_struct *work)
                kfree(info);
                goto out;
        }
-       queue_work(pciehp_wq, &info->work);
+       queue_work(p_slot->wq, &info->work);
  out:
        mutex_unlock(&p_slot->lock);
 }
@@ -377,7 +377,7 @@ static void handle_button_press_event(struct slot *p_slot)
                if (ATTN_LED(ctrl))
                        pciehp_set_attention_status(p_slot, 0);
 
-               queue_delayed_work(pciehp_wq, &p_slot->work, 5*HZ);
+               queue_delayed_work(p_slot->wq, &p_slot->work, 5*HZ);
                break;
        case BLINKINGOFF_STATE:
        case BLINKINGON_STATE:
@@ -439,7 +439,7 @@ static void handle_surprise_event(struct slot *p_slot)
        else
                p_slot->state = POWERON_STATE;
 
-       queue_work(pciehp_wq, &info->work);
+       queue_work(p_slot->wq, &info->work);
 }
 
 static void interrupt_event_handler(struct work_struct *work)
index 13b2eaf..5127f3f 100644 (file)
@@ -773,23 +773,32 @@ static void pcie_shutdown_notification(struct controller *ctrl)
 static int pcie_init_slot(struct controller *ctrl)
 {
        struct slot *slot;
+       char name[32];
 
        slot = kzalloc(sizeof(*slot), GFP_KERNEL);
        if (!slot)
                return -ENOMEM;
 
+       snprintf(name, sizeof(name), "pciehp-%u", PSN(ctrl));
+       slot->wq = alloc_workqueue(name, 0, 0);
+       if (!slot->wq)
+               goto abort;
+
        slot->ctrl = ctrl;
        mutex_init(&slot->lock);
        INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work);
        ctrl->slot = slot;
        return 0;
+abort:
+       kfree(slot);
+       return -ENOMEM;
 }
 
 static void pcie_cleanup_slot(struct controller *ctrl)
 {
        struct slot *slot = ctrl->slot;
        cancel_delayed_work(&slot->work);
-       flush_workqueue(pciehp_wq);
+       destroy_workqueue(slot->wq);
        kfree(slot);
 }
 
index ca64932..b849f99 100644 (file)
@@ -46,8 +46,6 @@
 extern bool shpchp_poll_mode;
 extern int shpchp_poll_time;
 extern bool shpchp_debug;
-extern struct workqueue_struct *shpchp_wq;
-extern struct workqueue_struct *shpchp_ordered_wq;
 
 #define dbg(format, arg...)                                            \
 do {                                                                   \
@@ -91,6 +89,7 @@ struct slot {
        struct list_head        slot_list;
        struct delayed_work work;       /* work for button event */
        struct mutex lock;
+       struct workqueue_struct *wq;
        u8 hp_slot;
 };
 
index b6de307..3100c52 100644 (file)
@@ -39,8 +39,6 @@
 bool shpchp_debug;
 bool shpchp_poll_mode;
 int shpchp_poll_time;
-struct workqueue_struct *shpchp_wq;
-struct workqueue_struct *shpchp_ordered_wq;
 
 #define DRIVER_VERSION "0.4"
 #define DRIVER_AUTHOR  "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
@@ -129,6 +127,14 @@ static int init_slots(struct controller *ctrl)
                slot->device = ctrl->slot_device_offset + i;
                slot->hpc_ops = ctrl->hpc_ops;
                slot->number = ctrl->first_slot + (ctrl->slot_num_inc * i);
+
+               snprintf(name, sizeof(name), "shpchp-%d", slot->number);
+               slot->wq = alloc_workqueue(name, 0, 0);
+               if (!slot->wq) {
+                       retval = -ENOMEM;
+                       goto error_info;
+               }
+
                mutex_init(&slot->lock);
                INIT_DELAYED_WORK(&slot->work, shpchp_queue_pushbutton_work);
 
@@ -148,7 +154,7 @@ static int init_slots(struct controller *ctrl)
                if (retval) {
                        ctrl_err(ctrl, "pci_hp_register failed with error %d\n",
                                 retval);
-                       goto error_info;
+                       goto error_slotwq;
                }
 
                get_power_status(hotplug_slot, &info->power_status);
@@ -160,6 +166,8 @@ static int init_slots(struct controller *ctrl)
        }
 
        return 0;
+error_slotwq:
+       destroy_workqueue(slot->wq);
 error_info:
        kfree(info);
 error_hpslot:
@@ -180,8 +188,7 @@ void cleanup_slots(struct controller *ctrl)
                slot = list_entry(tmp, struct slot, slot_list);
                list_del(&slot->slot_list);
                cancel_delayed_work(&slot->work);
-               flush_workqueue(shpchp_wq);
-               flush_workqueue(shpchp_ordered_wq);
+               destroy_workqueue(slot->wq);
                pci_hp_deregister(slot->hotplug_slot);
        }
 }
@@ -364,25 +371,12 @@ static struct pci_driver shpc_driver = {
 
 static int __init shpcd_init(void)
 {
-       int retval = 0;
-
-       shpchp_wq = alloc_ordered_workqueue("shpchp", 0);
-       if (!shpchp_wq)
-               return -ENOMEM;
-
-       shpchp_ordered_wq = alloc_ordered_workqueue("shpchp_ordered", 0);
-       if (!shpchp_ordered_wq) {
-               destroy_workqueue(shpchp_wq);
-               return -ENOMEM;
-       }
+       int retval;
 
        retval = pci_register_driver(&shpc_driver);
        dbg("%s: pci_register_driver = %d\n", __func__, retval);
        info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
-       if (retval) {
-               destroy_workqueue(shpchp_ordered_wq);
-               destroy_workqueue(shpchp_wq);
-       }
+
        return retval;
 }
 
@@ -390,8 +384,6 @@ static void __exit shpcd_cleanup(void)
 {
        dbg("unload_shpchpd()\n");
        pci_unregister_driver(&shpc_driver);
-       destroy_workqueue(shpchp_ordered_wq);
-       destroy_workqueue(shpchp_wq);
        info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
 }
 
index f9b5a52..5849927 100644 (file)
@@ -51,7 +51,7 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
        info->p_slot = p_slot;
        INIT_WORK(&info->work, interrupt_event_handler);
 
-       queue_work(shpchp_wq, &info->work);
+       queue_work(p_slot->wq, &info->work);
 
        return 0;
 }
@@ -453,7 +453,7 @@ void shpchp_queue_pushbutton_work(struct work_struct *work)
                kfree(info);
                goto out;
        }
-       queue_work(shpchp_ordered_wq, &info->work);
+       queue_work(p_slot->wq, &info->work);
  out:
        mutex_unlock(&p_slot->lock);
 }
@@ -501,7 +501,7 @@ static void handle_button_press_event(struct slot *p_slot)
                p_slot->hpc_ops->green_led_blink(p_slot);
                p_slot->hpc_ops->set_attention_status(p_slot, 0);
 
-               queue_delayed_work(shpchp_wq, &p_slot->work, 5*HZ);
+               queue_delayed_work(p_slot->wq, &p_slot->work, 5*HZ);
                break;
        case BLINKINGOFF_STATE:
        case BLINKINGON_STATE:
index 6c8bc58..fde4a32 100644 (file)
@@ -82,4 +82,4 @@ endchoice
 
 config PCIE_PME
        def_bool y
-       depends on PCIEPORTBUS && PM_RUNTIME && EXPERIMENTAL && ACPI
+       depends on PCIEPORTBUS && PM_RUNTIME && ACPI
index 421bbc5..564d97f 100644 (file)
@@ -630,6 +630,7 @@ static void aer_recover_work_func(struct work_struct *work)
                        continue;
                }
                do_recovery(pdev, entry.severity);
+               pci_dev_put(pdev);
        }
 }
 #endif
index b52630b..8474b6a 100644 (file)
@@ -771,6 +771,9 @@ void pcie_clear_aspm(struct pci_bus *bus)
 {
        struct pci_dev *child;
 
+       if (aspm_force)
+               return;
+
        /*
         * Clear any ASPM setup that the firmware has carried out on this bus
         */
index fb31b45..c5ceb9d 100644 (file)
@@ -239,7 +239,7 @@ static irqreturn_t mxs_lradc_trigger_handler(int irq, void *p)
        struct mxs_lradc *lradc = iio_priv(iio);
        const uint32_t chan_value = LRADC_CH_ACCUMULATE |
                ((LRADC_DELAY_TIMER_LOOP - 1) << LRADC_CH_NUM_SAMPLES_OFFSET);
-       int i, j = 0;
+       unsigned int i, j = 0;
 
        for_each_set_bit(i, iio->active_scan_mask, iio->masklength) {
                lradc->buffer[j] = readl(lradc->base + LRADC_CH(j));
index 3525a68..41d7350 100644 (file)
@@ -69,7 +69,7 @@ static int adis16080_spi_read(struct iio_dev *indio_dev,
        ret = spi_read(st->us, st->buf, 2);
 
        if (ret == 0)
-               *val = ((st->buf[0] & 0xF) << 8) | st->buf[1];
+               *val = sign_extend32(((st->buf[0] & 0xF) << 8) | st->buf[1], 11);
        mutex_unlock(&st->buf_lock);
 
        return ret;
index 131afd0..9464f38 100644 (file)
@@ -3054,7 +3054,7 @@ static int init_mp_dev(struct pci_dev *pcidev, mppcibrd_t brd)
                                sbdev->nr_ports = ((portnum_hex/16)*10) + (portnum_hex % 16);
                        }
                        break;
-#ifdef CONFIG_PARPORT
+#ifdef CONFIG_PARPORT_PC
                case PCI_DEVICE_ID_MP2S1P :
                        sbdev->nr_ports = 2;
 
index 6b2ec39..806cbf7 100644 (file)
@@ -90,7 +90,6 @@ typedef struct tagSRSNCapObject {
 } SRSNCapObject, *PSRSNCapObject;
 
 // BSS info(AP)
-#pragma pack(1)
 typedef struct tagKnownBSS {
     // BSS info
     BOOL            bActive;
index 5d8faf9..e0d2b07 100644 (file)
@@ -34,7 +34,6 @@
 #include "device.h"
 
 /*---------------------  Export Definitions -------------------------*/
-#pragma pack(1)
 typedef struct tagSINTData {
        BYTE byTSR0;
        BYTE byPkt0;
index 22710ce..ae6e2d2 100644 (file)
@@ -95,13 +95,12 @@ typedef enum tagWZONETYPE {
 // Ioctl interface structure
 // Command structure
 //
-#pragma pack(1)
 typedef struct tagSCmdRequest {
        u8 name[16];
        void    *data;
        u16         wResult;
        u16     wCmdCode;
-} SCmdRequest, *PSCmdRequest;
+} __packed SCmdRequest, *PSCmdRequest;
 
 //
 // Scan
@@ -111,7 +110,7 @@ typedef struct tagSCmdScan {
 
     u8     ssid[SSID_MAXLEN + 2];
 
-} SCmdScan, *PSCmdScan;
+} __packed SCmdScan, *PSCmdScan;
 
 //
 // BSS Join
@@ -126,7 +125,7 @@ typedef struct tagSCmdBSSJoin {
     BOOL    bPSEnable;
     BOOL    bShareKeyAuth;
 
-} SCmdBSSJoin, *PSCmdBSSJoin;
+} __packed SCmdBSSJoin, *PSCmdBSSJoin;
 
 //
 // Zonetype Setting
@@ -137,7 +136,7 @@ typedef struct tagSCmdZoneTypeSet {
  BOOL       bWrite;
  WZONETYPE  ZoneType;
 
-} SCmdZoneTypeSet, *PSCmdZoneTypeSet;
+} __packed SCmdZoneTypeSet, *PSCmdZoneTypeSet;
 
 typedef struct tagSWPAResult {
          char  ifname[100];
@@ -145,7 +144,7 @@ typedef struct tagSWPAResult {
        u8 key_mgmt;
        u8 eap_type;
          BOOL authenticated;
-} SWPAResult, *PSWPAResult;
+} __packed SWPAResult, *PSWPAResult;
 
 typedef struct tagSCmdStartAP {
 
@@ -157,7 +156,7 @@ typedef struct tagSCmdStartAP {
     BOOL    bShareKeyAuth;
     u8      byBasicRate;
 
-} SCmdStartAP, *PSCmdStartAP;
+} __packed SCmdStartAP, *PSCmdStartAP;
 
 typedef struct tagSCmdSetWEP {
 
@@ -167,7 +166,7 @@ typedef struct tagSCmdSetWEP {
     BOOL    bWepKeyAvailable[WEP_NKEYS];
     u32     auWepKeyLength[WEP_NKEYS];
 
-} SCmdSetWEP, *PSCmdSetWEP;
+} __packed SCmdSetWEP, *PSCmdSetWEP;
 
 typedef struct tagSBSSIDItem {
 
@@ -180,14 +179,14 @@ typedef struct tagSBSSIDItem {
     BOOL    bWEPOn;
     u32     uRSSI;
 
-} SBSSIDItem;
+} __packed SBSSIDItem;
 
 
 typedef struct tagSBSSIDList {
 
        u32                 uItem;
        SBSSIDItem      sBSSIDList[0];
-} SBSSIDList, *PSBSSIDList;
+} __packed SBSSIDList, *PSBSSIDList;
 
 
 typedef struct tagSNodeItem {
@@ -208,7 +207,7 @@ typedef struct tagSNodeItem {
     u32            uTxAttempts;
     u16            wFailureRatio;
 
-} SNodeItem;
+} __packed SNodeItem;
 
 
 typedef struct tagSNodeList {
@@ -216,7 +215,7 @@ typedef struct tagSNodeList {
        u32                 uItem;
        SNodeItem       sNodeList[0];
 
-} SNodeList, *PSNodeList;
+} __packed SNodeList, *PSNodeList;
 
 
 typedef struct tagSCmdLinkStatus {
@@ -229,7 +228,7 @@ typedef struct tagSCmdLinkStatus {
     u32     uChannel;
     u32     uLinkRate;
 
-} SCmdLinkStatus, *PSCmdLinkStatus;
+} __packed SCmdLinkStatus, *PSCmdLinkStatus;
 
 //
 // 802.11 counter
@@ -247,7 +246,7 @@ typedef struct tagSDot11MIBCount {
     u32 ReceivedFragmentCount;
     u32 MulticastReceivedFrameCount;
     u32 FCSErrorCount;
-} SDot11MIBCount, *PSDot11MIBCount;
+} __packed SDot11MIBCount, *PSDot11MIBCount;
 
 
 
@@ -355,13 +354,13 @@ typedef struct tagSStatMIBCount {
     u32   ullTxBroadcastBytes[2];
     u32   ullTxMulticastBytes[2];
     u32   ullTxDirectedBytes[2];
-} SStatMIBCount, *PSStatMIBCount;
+} __packed SStatMIBCount, *PSStatMIBCount;
 
 typedef struct tagSCmdValue {
 
     u32     dwValue;
 
-} SCmdValue,  *PSCmdValue;
+} __packed SCmdValue,  *PSCmdValue;
 
 //
 // hostapd & viawget ioctl related
@@ -431,7 +430,7 @@ struct viawget_hostapd_param {
                        u8 ssid[32];
                } scan_req;
        } u;
-};
+} __packed;
 
 /*---------------------  Export Classes  ----------------------------*/
 
index 959c886..2522dde 100644 (file)
@@ -67,12 +67,11 @@ enum {
 
 
 
-#pragma pack(1)
 typedef struct viawget_wpa_header {
        u8 type;
        u16 req_ie_len;
        u16 resp_ie_len;
-} viawget_wpa_header;
+} __packed viawget_wpa_header;
 
 struct viawget_wpa_param {
        u32 cmd;
@@ -113,9 +112,8 @@ struct viawget_wpa_param {
                        u8 *buf;
                } scan_results;
        } u;
-};
+} __packed;
 
-#pragma pack(1)
 struct viawget_scan_result {
        u8 bssid[6];
        u8 ssid[32];
@@ -130,7 +128,7 @@ struct viawget_scan_result {
        int noise;
        int level;
        int maxrate;
-};
+} __packed;
 
 /*---------------------  Export Classes  ----------------------------*/
 
index 4efa9bc..89bfd85 100644 (file)
@@ -406,7 +406,7 @@ int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp)
        /* SSID */
        req->ssid.status = P80211ENUM_msgitem_status_data_ok;
        req->ssid.data.len = le16_to_cpu(item->ssid.len);
-       req->ssid.data.len = min_t(u16, req->ssid.data.len, WLAN_BSSID_LEN);
+       req->ssid.data.len = min_t(u16, req->ssid.data.len, WLAN_SSID_MAXLEN);
        memcpy(req->ssid.data.data, item->ssid.data, req->ssid.data.len);
 
        /* supported rates */
index be6a373..79ff3a5 100644 (file)
@@ -441,6 +441,8 @@ static int pty_bsd_ioctl(struct tty_struct *tty,
                return pty_get_pktmode(tty, (int __user *)arg);
        case TIOCSIG:    /* Send signal to other side of pty */
                return pty_signal(tty, (int) arg);
+       case TIOCGPTN: /* TTY returns ENOTTY, but glibc expects EINVAL here */
+               return -EINVAL;
        }
        return -ENOIOCTLCMD;
 }
index d085e3a..f932043 100644 (file)
@@ -300,6 +300,12 @@ static const struct serial8250_config uart_config[] = {
                                  UART_FCR_R_TRIG_00 | UART_FCR_T_TRIG_00,
                .flags          = UART_CAP_FIFO,
        },
+       [PORT_BRCM_TRUMANAGE] = {
+               .name           = "TruManage",
+               .fifo_size      = 1,
+               .tx_loadsz      = 1024,
+               .flags          = UART_CAP_HFIFO,
+       },
        [PORT_8250_CIR] = {
                .name           = "CIR port"
        }
@@ -1490,6 +1496,11 @@ void serial8250_tx_chars(struct uart_8250_port *up)
                port->icount.tx++;
                if (uart_circ_empty(xmit))
                        break;
+               if (up->capabilities & UART_CAP_HFIFO) {
+                       if ((serial_port_in(port, UART_LSR) & BOTH_EMPTY) !=
+                           BOTH_EMPTY)
+                               break;
+               }
        } while (--count > 0);
 
        if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
index 3b4ea84..12caa12 100644 (file)
@@ -40,6 +40,7 @@ struct serial8250_config {
 #define UART_CAP_AFE   (1 << 11)       /* MCR-based hw flow control */
 #define UART_CAP_UUE   (1 << 12)       /* UART needs IER bit 6 set (Xscale) */
 #define UART_CAP_RTOIE (1 << 13)       /* UART needs IER bit 4 set (Xscale, Tegra) */
+#define UART_CAP_HFIFO (1 << 14)       /* UART has a "hidden" FIFO */
 
 #define UART_BUG_QUOT  (1 << 0)        /* UART has buggy quot LSB */
 #define UART_BUG_TXEN  (1 << 1)        /* UART has buggy TX IIR status */
index 1d0dba2..096d2ef 100644 (file)
@@ -79,7 +79,7 @@ static int dw8250_handle_irq(struct uart_port *p)
        } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
                /* Clear the USR and write the LCR again. */
                (void)p->serial_in(p, UART_USR);
-               p->serial_out(p, d->last_lcr, UART_LCR);
+               p->serial_out(p, UART_LCR, d->last_lcr);
 
                return 1;
        }
index 26b9dc0..a27a98e 100644 (file)
@@ -1085,6 +1085,18 @@ pci_omegapci_setup(struct serial_private *priv,
        return setup_port(priv, port, 2, idx * 8, 0);
 }
 
+static int
+pci_brcm_trumanage_setup(struct serial_private *priv,
+                        const struct pciserial_board *board,
+                        struct uart_8250_port *port, int idx)
+{
+       int ret = pci_default_setup(priv, board, port, idx);
+
+       port->port.type = PORT_BRCM_TRUMANAGE;
+       port->port.flags = (port->port.flags | UPF_FIXED_PORT | UPF_FIXED_TYPE);
+       return ret;
+}
+
 static int skip_tx_en_setup(struct serial_private *priv,
                        const struct pciserial_board *board,
                        struct uart_8250_port *port, int idx)
@@ -1301,9 +1313,10 @@ pci_wch_ch353_setup(struct serial_private *priv,
 #define PCI_VENDOR_ID_AGESTAR          0x5372
 #define PCI_DEVICE_ID_AGESTAR_9375     0x6872
 #define PCI_VENDOR_ID_ASIX             0x9710
-#define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0019
 #define PCI_DEVICE_ID_COMMTECH_4224PCIE        0x0020
 #define PCI_DEVICE_ID_COMMTECH_4228PCIE        0x0021
+#define PCI_DEVICE_ID_COMMTECH_4222PCIE        0x0022
+#define PCI_DEVICE_ID_BROADCOM_TRUMANAGE 0x160a
 
 
 /* Unknown vendors/cards - this should not be in linux/pci_ids.h */
@@ -1953,6 +1966,17 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
                .subdevice      = PCI_ANY_ID,
                .setup          = pci_xr17v35x_setup,
        },
+       /*
+        * Broadcom TruManage (NetXtreme)
+        */
+       {
+               .vendor         = PCI_VENDOR_ID_BROADCOM,
+               .device         = PCI_DEVICE_ID_BROADCOM_TRUMANAGE,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = pci_brcm_trumanage_setup,
+       },
+
        /*
         * Default "match everything" terminator entry
         */
@@ -2148,6 +2172,7 @@ enum pci_board_num_t {
        pbn_ce4100_1_115200,
        pbn_omegapci,
        pbn_NETMOS9900_2s_115200,
+       pbn_brcm_trumanage,
 };
 
 /*
@@ -2246,7 +2271,7 @@ static struct pciserial_board pci_boards[] = {
 
        [pbn_b0_8_1152000_200] = {
                .flags          = FL_BASE0,
-               .num_ports      = 2,
+               .num_ports      = 8,
                .base_baud      = 1152000,
                .uart_offset    = 0x200,
        },
@@ -2892,6 +2917,12 @@ static struct pciserial_board pci_boards[] = {
                .num_ports      = 2,
                .base_baud      = 115200,
        },
+       [pbn_brcm_trumanage] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 1,
+               .reg_shift      = 2,
+               .base_baud      = 115200,
+       },
 };
 
 static const struct pci_device_id blacklist[] = {
@@ -4470,6 +4501,13 @@ static struct pci_device_id serial_pci_tbl[] = {
                PCI_ANY_ID, PCI_ANY_ID, 0, 0,
                pbn_omegapci },
 
+       /*
+        * Broadcom TruManage
+        */
+       {       PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BROADCOM_TRUMANAGE,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_brcm_trumanage },
+
        /*
         * AgeStar as-prs2-009
         */
index 675d94a..8cb6d8d 100644 (file)
@@ -637,6 +637,7 @@ static void ifx_port_shutdown(struct tty_port *port)
 
        clear_bit(IFX_SPI_STATE_IO_AVAILABLE, &ifx_dev->flags);
        mrdy_set_low(ifx_dev);
+       del_timer(&ifx_dev->spi_timer);
        clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags);
        tasklet_kill(&ifx_dev->io_work_tasklet);
 }
@@ -810,7 +811,8 @@ static void ifx_spi_io(unsigned long data)
                ifx_dev->spi_xfer.cs_change = 0;
                ifx_dev->spi_xfer.speed_hz = ifx_dev->spi_dev->max_speed_hz;
                /* ifx_dev->spi_xfer.speed_hz = 390625; */
-               ifx_dev->spi_xfer.bits_per_word = spi_bpw;
+               ifx_dev->spi_xfer.bits_per_word =
+                       ifx_dev->spi_dev->bits_per_word;
 
                ifx_dev->spi_xfer.tx_buf = ifx_dev->tx_buffer;
                ifx_dev->spi_xfer.rx_buf = ifx_dev->rx_buffer;
index 6db23b0..e55615e 100644 (file)
@@ -253,7 +253,7 @@ static void mxs_auart_tx_chars(struct mxs_auart_port *s)
        struct circ_buf *xmit = &s->port.state->xmit;
 
        if (auart_dma_enabled(s)) {
-               int i = 0;
+               u32 i = 0;
                int size;
                void *buffer = s->tx_dma_buf;
 
@@ -412,10 +412,12 @@ static void mxs_auart_set_mctrl(struct uart_port *u, unsigned mctrl)
 
        u32 ctrl = readl(u->membase + AUART_CTRL2);
 
-       ctrl &= ~AUART_CTRL2_RTSEN;
+       ctrl &= ~(AUART_CTRL2_RTSEN | AUART_CTRL2_RTS);
        if (mctrl & TIOCM_RTS) {
                if (tty_port_cts_enabled(&u->state->port))
                        ctrl |= AUART_CTRL2_RTSEN;
+               else
+                       ctrl |= AUART_CTRL2_RTS;
        }
 
        s->ctrl = mctrl;
index 12e5249..e514b3a 100644 (file)
@@ -1006,7 +1006,6 @@ static void s3c24xx_serial_resetport(struct uart_port *port,
 
        ucon &= ucon_mask;
        wr_regl(port, S3C2410_UCON,  ucon | cfg->ucon);
-       wr_regl(port, S3C2410_ULCON, cfg->ulcon);
 
        /* reset both fifos */
        wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
index 8fd1814..d5ed9f6 100644 (file)
@@ -604,7 +604,7 @@ static int vt8500_serial_probe(struct platform_device *pdev)
        vt8500_port->uart.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
 
        vt8500_port->clk = of_clk_get(pdev->dev.of_node, 0);
-       if (vt8500_port->clk) {
+       if (!IS_ERR(vt8500_port->clk)) {
                vt8500_port->uart.uartclk = clk_get_rate(vt8500_port->clk);
        } else {
                /* use the default of 24Mhz if not specified and warn */
index 2e43b33..2fdd767 100644 (file)
@@ -1605,6 +1605,7 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)
 
                if (epnum == 0 || epnum == 1) {
                        dep->endpoint.maxpacket = 512;
+                       dep->endpoint.maxburst = 1;
                        dep->endpoint.ops = &dwc3_gadget_ep0_ops;
                        if (!epnum)
                                dwc->gadget.ep0 = &dep->endpoint;
index 4a6961c..8c2f251 100644 (file)
@@ -1153,15 +1153,15 @@ static int ffs_fs_parse_opts(struct ffs_sb_fill_data *data, char *opts)
                                        pr_err("%s: unmapped value: %lu\n", opts, value);
                                        return -EINVAL;
                                }
-                       }
-                       else if (!memcmp(opts, "gid", 3))
+                       } else if (!memcmp(opts, "gid", 3)) {
                                data->perms.gid = make_kgid(current_user_ns(), value);
                                if (!gid_valid(data->perms.gid)) {
                                        pr_err("%s: unmapped value: %lu\n", opts, value);
                                        return -EINVAL;
                                }
-                       else
+                       } else {
                                goto invalid;
+                       }
                        break;
 
                default:
index 1b0f086..d3bd7b0 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/io.h>
 
-#include <mach/hardware.h>
-
 static struct clk *mxc_ahb_clk;
 static struct clk *mxc_per_clk;
 static struct clk *mxc_ipg_clk;
 
 /* workaround ENGcm09152 for i.MX35 */
-#define USBPHYCTRL_OTGBASE_OFFSET      0x608
+#define MX35_USBPHYCTRL_OFFSET         0x600
+#define USBPHYCTRL_OTGBASE_OFFSET      0x8
 #define USBPHYCTRL_EVDO                        (1 << 23)
 
 int fsl_udc_clk_init(struct platform_device *pdev)
@@ -59,7 +58,7 @@ int fsl_udc_clk_init(struct platform_device *pdev)
        clk_prepare_enable(mxc_per_clk);
 
        /* make sure USB_CLK is running at 60 MHz +/- 1000 Hz */
-       if (!cpu_is_mx51()) {
+       if (!strcmp(pdev->id_entry->name, "imx-udc-mx27")) {
                freq = clk_get_rate(mxc_per_clk);
                if (pdata->phy_mode != FSL_USB2_PHY_ULPI &&
                    (freq < 59999000 || freq > 60001000)) {
@@ -79,27 +78,40 @@ eclkrate:
        return ret;
 }
 
-void fsl_udc_clk_finalize(struct platform_device *pdev)
+int fsl_udc_clk_finalize(struct platform_device *pdev)
 {
        struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
-       if (cpu_is_mx35()) {
-               unsigned int v;
+       int ret = 0;
 
-               /* workaround ENGcm09152 for i.MX35 */
-               if (pdata->workaround & FLS_USB2_WORKAROUND_ENGCM09152) {
-                       v = readl(MX35_IO_ADDRESS(MX35_USB_BASE_ADDR +
-                                       USBPHYCTRL_OTGBASE_OFFSET));
-                       writel(v | USBPHYCTRL_EVDO,
-                               MX35_IO_ADDRESS(MX35_USB_BASE_ADDR +
-                                       USBPHYCTRL_OTGBASE_OFFSET));
+       /* workaround ENGcm09152 for i.MX35 */
+       if (pdata->workaround & FLS_USB2_WORKAROUND_ENGCM09152) {
+               unsigned int v;
+               struct resource *res = platform_get_resource
+                       (pdev, IORESOURCE_MEM, 0);
+               void __iomem *phy_regs = ioremap(res->start +
+                                               MX35_USBPHYCTRL_OFFSET, 512);
+               if (!phy_regs) {
+                       dev_err(&pdev->dev, "ioremap for phy address fails\n");
+                       ret = -EINVAL;
+                       goto ioremap_err;
                }
+
+               v = readl(phy_regs + USBPHYCTRL_OTGBASE_OFFSET);
+               writel(v | USBPHYCTRL_EVDO,
+                       phy_regs + USBPHYCTRL_OTGBASE_OFFSET);
+
+               iounmap(phy_regs);
        }
 
+
+ioremap_err:
        /* ULPI transceivers don't need usbpll */
        if (pdata->phy_mode == FSL_USB2_PHY_ULPI) {
                clk_disable_unprepare(mxc_per_clk);
                mxc_per_clk = NULL;
        }
+
+       return ret;
 }
 
 void fsl_udc_clk_release(void)
index c19f7f1..667275c 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/fsl_devices.h>
 #include <linux/dmapool.h>
 #include <linux/delay.h>
+#include <linux/of_device.h>
 
 #include <asm/byteorder.h>
 #include <asm/io.h>
@@ -2438,11 +2439,6 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
        unsigned int i;
        u32 dccparams;
 
-       if (strcmp(pdev->name, driver_name)) {
-               VDBG("Wrong device");
-               return -ENODEV;
-       }
-
        udc_controller = kzalloc(sizeof(struct fsl_udc), GFP_KERNEL);
        if (udc_controller == NULL) {
                ERR("malloc udc failed\n");
@@ -2547,7 +2543,9 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
                dr_controller_setup(udc_controller);
        }
 
-       fsl_udc_clk_finalize(pdev);
+       ret = fsl_udc_clk_finalize(pdev);
+       if (ret)
+               goto err_free_irq;
 
        /* Setup gadget structure */
        udc_controller->gadget.ops = &fsl_gadget_ops;
@@ -2756,22 +2754,32 @@ static int fsl_udc_otg_resume(struct device *dev)
 
        return fsl_udc_resume(NULL);
 }
-
 /*-------------------------------------------------------------------------
        Register entry point for the peripheral controller driver
 --------------------------------------------------------------------------*/
-
+static const struct platform_device_id fsl_udc_devtype[] = {
+       {
+               .name = "imx-udc-mx27",
+       }, {
+               .name = "imx-udc-mx51",
+       }, {
+               /* sentinel */
+       }
+};
+MODULE_DEVICE_TABLE(platform, fsl_udc_devtype);
 static struct platform_driver udc_driver = {
-       .remove  = __exit_p(fsl_udc_remove),
+       .remove         = __exit_p(fsl_udc_remove),
+       /* Just for FSL i.mx SoC currently */
+       .id_table       = fsl_udc_devtype,
        /* these suspend and resume are not usb suspend and resume */
-       .suspend = fsl_udc_suspend,
-       .resume  = fsl_udc_resume,
-       .driver  = {
-               .name = (char *)driver_name,
-               .owner = THIS_MODULE,
-               /* udc suspend/resume called from OTG driver */
-               .suspend = fsl_udc_otg_suspend,
-               .resume  = fsl_udc_otg_resume,
+       .suspend        = fsl_udc_suspend,
+       .resume         = fsl_udc_resume,
+       .driver         = {
+                       .name = (char *)driver_name,
+                       .owner = THIS_MODULE,
+                       /* udc suspend/resume called from OTG driver */
+                       .suspend = fsl_udc_otg_suspend,
+                       .resume  = fsl_udc_otg_resume,
        },
 };
 
index f61a967..c6703bb 100644 (file)
@@ -592,15 +592,16 @@ static inline struct ep_queue_head *get_qh_by_ep(struct fsl_ep *ep)
 struct platform_device;
 #ifdef CONFIG_ARCH_MXC
 int fsl_udc_clk_init(struct platform_device *pdev);
-void fsl_udc_clk_finalize(struct platform_device *pdev);
+int fsl_udc_clk_finalize(struct platform_device *pdev);
 void fsl_udc_clk_release(void);
 #else
 static inline int fsl_udc_clk_init(struct platform_device *pdev)
 {
        return 0;
 }
-static inline void fsl_udc_clk_finalize(struct platform_device *pdev)
+static inline int fsl_udc_clk_finalize(struct platform_device *pdev)
 {
+       return 0;
 }
 static inline void fsl_udc_clk_release(void)
 {
index d6bb128..3a21c5d 100644 (file)
@@ -148,7 +148,7 @@ config USB_EHCI_FSL
          Variation of ARC USB block used in some Freescale chips.
 
 config USB_EHCI_MXC
-       bool "Support for Freescale i.MX on-chip EHCI USB controller"
+       tristate "Support for Freescale i.MX on-chip EHCI USB controller"
        depends on USB_EHCI_HCD && ARCH_MXC
        select USB_EHCI_ROOT_HUB_TT
        ---help---
index 1eb4c30..001fbff 100644 (file)
@@ -26,6 +26,7 @@ obj-$(CONFIG_PCI)             += pci-quirks.o
 obj-$(CONFIG_USB_EHCI_HCD)     += ehci-hcd.o
 obj-$(CONFIG_USB_EHCI_PCI)     += ehci-pci.o
 obj-$(CONFIG_USB_EHCI_HCD_PLATFORM)    += ehci-platform.o
+obj-$(CONFIG_USB_EHCI_MXC)     += ehci-mxc.o
 
 obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o
 obj-$(CONFIG_USB_ISP116X_HCD)  += isp116x-hcd.o
index c97503b..09537b2 100644 (file)
@@ -74,10 +74,6 @@ static const char    hcd_name [] = "ehci_hcd";
 #undef VERBOSE_DEBUG
 #undef EHCI_URB_TRACE
 
-#ifdef DEBUG
-#define EHCI_STATS
-#endif
-
 /* magic numbers that can affect system performance */
 #define        EHCI_TUNE_CERR          3       /* 0-3 qtd retries; 0 == don't stop */
 #define        EHCI_TUNE_RL_HS         4       /* nak throttle; see 4.9 */
@@ -1250,11 +1246,6 @@ MODULE_LICENSE ("GPL");
 #define        PLATFORM_DRIVER         ehci_fsl_driver
 #endif
 
-#ifdef CONFIG_USB_EHCI_MXC
-#include "ehci-mxc.c"
-#define PLATFORM_DRIVER                ehci_mxc_driver
-#endif
-
 #ifdef CONFIG_USB_EHCI_SH
 #include "ehci-sh.c"
 #define PLATFORM_DRIVER                ehci_hcd_sh_driver
@@ -1352,7 +1343,8 @@ MODULE_LICENSE ("GPL");
 
 #if !IS_ENABLED(CONFIG_USB_EHCI_PCI) && \
        !IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \
-       !defined(CONFIG_USB_CHIPIDEA_HOST) && \
+       !IS_ENABLED(CONFIG_USB_CHIPIDEA_HOST) && \
+       !IS_ENABLED(CONFIG_USB_EHCI_MXC) && \
        !defined(PLATFORM_DRIVER) && \
        !defined(PS3_SYSTEM_BUS_DRIVER) && \
        !defined(OF_PLATFORM_DRIVER) && \
index ec7f5d2..dedb80b 100644 (file)
  * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
 #include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
 
 #include <linux/platform_data/usb-ehci-mxc.h>
 
 #include <asm/mach-types.h>
 
+#include "ehci.h"
+
+#define DRIVER_DESC "Freescale On-Chip EHCI Host driver"
+
+static const char hcd_name[] = "ehci-mxc";
+
 #define ULPI_VIEWPORT_OFFSET   0x170
 
 struct ehci_mxc_priv {
        struct clk *usbclk, *ahbclk, *phyclk;
-       struct usb_hcd *hcd;
 };
 
-/* called during probe() after chip reset completes */
-static int ehci_mxc_setup(struct usb_hcd *hcd)
-{
-       hcd->has_tt = 1;
-
-       return ehci_setup(hcd);
-}
+static struct hc_driver __read_mostly ehci_mxc_hc_driver;
 
-static const struct hc_driver ehci_mxc_hc_driver = {
-       .description = hcd_name,
-       .product_desc = "Freescale On-Chip EHCI Host Controller",
-       .hcd_priv_size = sizeof(struct ehci_hcd),
-
-       /*
-        * generic hardware linkage
-        */
-       .irq = ehci_irq,
-       .flags = HCD_USB2 | HCD_MEMORY,
-
-       /*
-        * basic lifecycle operations
-        */
-       .reset = ehci_mxc_setup,
-       .start = ehci_run,
-       .stop = ehci_stop,
-       .shutdown = ehci_shutdown,
-
-       /*
-        * managing i/o requests and associated device resources
-        */
-       .urb_enqueue = ehci_urb_enqueue,
-       .urb_dequeue = ehci_urb_dequeue,
-       .endpoint_disable = ehci_endpoint_disable,
-       .endpoint_reset = ehci_endpoint_reset,
-
-       /*
-        * scheduling support
-        */
-       .get_frame_number = ehci_get_frame,
-
-       /*
-        * root hub support
-        */
-       .hub_status_data = ehci_hub_status_data,
-       .hub_control = ehci_hub_control,
-       .bus_suspend = ehci_bus_suspend,
-       .bus_resume = ehci_bus_resume,
-       .relinquish_port = ehci_relinquish_port,
-       .port_handed_over = ehci_port_handed_over,
-
-       .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
+static const struct ehci_driver_overrides ehci_mxc_overrides __initdata = {
+       .extra_priv_size =      sizeof(struct ehci_mxc_priv),
 };
 
 static int ehci_mxc_drv_probe(struct platform_device *pdev)
@@ -112,12 +75,6 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
        if (!hcd)
                return -ENOMEM;
 
-       priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
-       if (!priv) {
-               ret = -ENOMEM;
-               goto err_alloc;
-       }
-
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
                dev_err(dev, "Found HC with no register addr. Check setup!\n");
@@ -135,6 +92,10 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
                goto err_alloc;
        }
 
+       hcd->has_tt = 1;
+       ehci = hcd_to_ehci(hcd);
+       priv = (struct ehci_mxc_priv *) ehci->priv;
+
        /* enable clocks */
        priv->usbclk = devm_clk_get(&pdev->dev, "ipg");
        if (IS_ERR(priv->usbclk)) {
@@ -169,8 +130,6 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
                mdelay(10);
        }
 
-       ehci = hcd_to_ehci(hcd);
-
        /* EHCI registers start at offset 0x100 */
        ehci->caps = hcd->regs + 0x100;
        ehci->regs = hcd->regs + 0x100 +
@@ -198,8 +157,7 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
                }
        }
 
-       priv->hcd = hcd;
-       platform_set_drvdata(pdev, priv);
+       platform_set_drvdata(pdev, hcd);
 
        ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
        if (ret)
@@ -244,8 +202,11 @@ err_alloc:
 static int __exit ehci_mxc_drv_remove(struct platform_device *pdev)
 {
        struct mxc_usbh_platform_data *pdata = pdev->dev.platform_data;
-       struct ehci_mxc_priv *priv = platform_get_drvdata(pdev);
-       struct usb_hcd *hcd = priv->hcd;
+       struct usb_hcd *hcd = platform_get_drvdata(pdev);
+       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+       struct ehci_mxc_priv *priv = (struct ehci_mxc_priv *) ehci->priv;
+
+       usb_remove_hcd(hcd);
 
        if (pdata && pdata->exit)
                pdata->exit(pdev);
@@ -253,23 +214,20 @@ static int __exit ehci_mxc_drv_remove(struct platform_device *pdev)
        if (pdata->otg)
                usb_phy_shutdown(pdata->otg);
 
-       usb_remove_hcd(hcd);
-       usb_put_hcd(hcd);
-       platform_set_drvdata(pdev, NULL);
-
        clk_disable_unprepare(priv->usbclk);
        clk_disable_unprepare(priv->ahbclk);
 
        if (priv->phyclk)
                clk_disable_unprepare(priv->phyclk);
 
+       usb_put_hcd(hcd);
+       platform_set_drvdata(pdev, NULL);
        return 0;
 }
 
 static void ehci_mxc_drv_shutdown(struct platform_device *pdev)
 {
-       struct ehci_mxc_priv *priv = platform_get_drvdata(pdev);
-       struct usb_hcd *hcd = priv->hcd;
+       struct usb_hcd *hcd = platform_get_drvdata(pdev);
 
        if (hcd->driver->shutdown)
                hcd->driver->shutdown(hcd);
@@ -279,9 +237,31 @@ MODULE_ALIAS("platform:mxc-ehci");
 
 static struct platform_driver ehci_mxc_driver = {
        .probe = ehci_mxc_drv_probe,
-       .remove = __exit_p(ehci_mxc_drv_remove),
+       .remove = ehci_mxc_drv_remove,
        .shutdown = ehci_mxc_drv_shutdown,
        .driver = {
                   .name = "mxc-ehci",
        },
 };
+
+static int __init ehci_mxc_init(void)
+{
+       if (usb_disabled())
+               return -ENODEV;
+
+       pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+
+       ehci_init_driver(&ehci_mxc_hc_driver, &ehci_mxc_overrides);
+       return platform_driver_register(&ehci_mxc_driver);
+}
+module_init(ehci_mxc_init);
+
+static void __exit ehci_mxc_cleanup(void)
+{
+       platform_driver_unregister(&ehci_mxc_driver);
+}
+module_exit(ehci_mxc_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Sascha Hauer");
+MODULE_LICENSE("GPL");
index 9dadc71..36c3a82 100644 (file)
@@ -38,6 +38,10 @@ typedef __u16 __bitwise __hc16;
 #endif
 
 /* statistics can be kept for tuning/monitoring */
+#ifdef DEBUG
+#define EHCI_STATS
+#endif
+
 struct ehci_stats {
        /* irq usage */
        unsigned long           normal;
@@ -221,6 +225,9 @@ struct ehci_hcd {                   /* one per controller */
 #ifdef DEBUG
        struct dentry           *debug_dir;
 #endif
+
+       /* platform-specific data -- must come last */
+       unsigned long           priv[0] __aligned(sizeof(s64));
 };
 
 /* convert between an HCD pointer and the corresponding EHCI_HCD */
index 4b9e9ab..4f64d24 100644 (file)
@@ -447,6 +447,10 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd)
                return IRQ_NONE;
        uhci_writew(uhci, status, USBSTS);              /* Clear it */
 
+       spin_lock(&uhci->lock);
+       if (unlikely(!uhci->is_initialized))    /* not yet configured */
+               goto done;
+
        if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) {
                if (status & USBSTS_HSE)
                        dev_err(uhci_dev(uhci), "host system error, "
@@ -455,7 +459,6 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd)
                        dev_err(uhci_dev(uhci), "host controller process "
                                        "error, something bad happened!\n");
                if (status & USBSTS_HCH) {
-                       spin_lock(&uhci->lock);
                        if (uhci->rh_state >= UHCI_RH_RUNNING) {
                                dev_err(uhci_dev(uhci),
                                        "host controller halted, "
@@ -473,15 +476,15 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd)
                                 * pending unlinks */
                                mod_timer(&hcd->rh_timer, jiffies);
                        }
-                       spin_unlock(&uhci->lock);
                }
        }
 
-       if (status & USBSTS_RD)
+       if (status & USBSTS_RD) {
+               spin_unlock(&uhci->lock);
                usb_hcd_poll_rh_status(hcd);
-       else {
-               spin_lock(&uhci->lock);
+       } else {
                uhci_scan_schedule(uhci);
+ done:
                spin_unlock(&uhci->lock);
        }
 
@@ -662,9 +665,9 @@ static int uhci_start(struct usb_hcd *hcd)
         */
        mb();
 
+       spin_lock_irq(&uhci->lock);
        configure_hc(uhci);
        uhci->is_initialized = 1;
-       spin_lock_irq(&uhci->lock);
        start_rh(uhci);
        spin_unlock_irq(&uhci->lock);
        return 0;
index 0968dd7..f522000 100644 (file)
@@ -105,7 +105,7 @@ static void cppi_reset_tx(struct cppi_tx_stateram __iomem *tx, u32 ptr)
        musb_writel(&tx->tx_complete, 0, ptr);
 }
 
-static void __init cppi_pool_init(struct cppi *cppi, struct cppi_channel *c)
+static void cppi_pool_init(struct cppi *cppi, struct cppi_channel *c)
 {
        int     j;
 
@@ -150,7 +150,7 @@ static void cppi_pool_free(struct cppi_channel *c)
        c->last_processed = NULL;
 }
 
-static int __init cppi_controller_start(struct dma_controller *c)
+static int cppi_controller_start(struct dma_controller *c)
 {
        struct cppi     *controller;
        void __iomem    *tibase;
index 58184f3..82afc4d 100644 (file)
@@ -530,6 +530,9 @@ static void chase_port(struct edgeport_port *port, unsigned long timeout,
        wait_queue_t wait;
        unsigned long flags;
 
+       if (!tty)
+               return;
+
        if (!timeout)
                timeout = (HZ * EDGE_CLOSING_WAIT)/100;
 
index 478adcf..0d9dac9 100644 (file)
@@ -449,6 +449,10 @@ static void option_instat_callback(struct urb *urb);
 #define PETATEL_VENDOR_ID                      0x1ff4
 #define PETATEL_PRODUCT_NP10T                  0x600e
 
+/* TP-LINK Incorporated products */
+#define TPLINK_VENDOR_ID                       0x2357
+#define TPLINK_PRODUCT_MA180                   0x0201
+
 /* some devices interfaces need special handling due to a number of reasons */
 enum option_blacklist_reason {
                OPTION_BLACKLIST_NONE = 0,
@@ -930,7 +934,8 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0254, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0257, 0xff, 0xff, 0xff), /* ZTE MF821 */
          .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0265, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0265, 0xff, 0xff, 0xff), /* ONDA MT8205 */
+         .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0284, 0xff, 0xff, 0xff), /* ZTE MF880 */
          .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0317, 0xff, 0xff, 0xff) },
@@ -1311,6 +1316,8 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x00, 0x00) },
        { USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) },
        { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T) },
+       { USB_DEVICE(TPLINK_VENDOR_ID, TPLINK_PRODUCT_MA180),
+         .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
index 4362d9e..f72323e 100644 (file)
@@ -240,17 +240,17 @@ ssize_t vfio_pci_mem_readwrite(struct vfio_pci_device *vdev, char __user *buf,
                        filled = 1;
                } else {
                        /* Drop writes, fill reads with FF */
+                       filled = min((size_t)(x_end - pos), count);
                        if (!iswrite) {
                                char val = 0xFF;
                                size_t i;
 
-                               for (i = 0; i < x_end - pos; i++) {
+                               for (i = 0; i < filled; i++) {
                                        if (put_user(val, buf + i))
                                                goto out;
                                }
                        }
 
-                       filled = x_end - pos;
                }
 
                count -= filled;
index 1252678..0abf2bf 100644 (file)
@@ -139,6 +139,7 @@ struct imxfb_info {
        struct clk              *clk_ahb;
        struct clk              *clk_per;
        enum imxfb_type         devtype;
+       bool                    enabled;
 
        /*
         * These are the addresses we mapped
@@ -536,6 +537,10 @@ static void imxfb_exit_backlight(struct imxfb_info *fbi)
 
 static void imxfb_enable_controller(struct imxfb_info *fbi)
 {
+
+       if (fbi->enabled)
+               return;
+
        pr_debug("Enabling LCD controller\n");
 
        writel(fbi->screen_dma, fbi->regs + LCDC_SSA);
@@ -556,6 +561,7 @@ static void imxfb_enable_controller(struct imxfb_info *fbi)
        clk_prepare_enable(fbi->clk_ipg);
        clk_prepare_enable(fbi->clk_ahb);
        clk_prepare_enable(fbi->clk_per);
+       fbi->enabled = true;
 
        if (fbi->backlight_power)
                fbi->backlight_power(1);
@@ -565,6 +571,9 @@ static void imxfb_enable_controller(struct imxfb_info *fbi)
 
 static void imxfb_disable_controller(struct imxfb_info *fbi)
 {
+       if (!fbi->enabled)
+               return;
+
        pr_debug("Disabling LCD controller\n");
 
        if (fbi->backlight_power)
@@ -575,6 +584,7 @@ static void imxfb_disable_controller(struct imxfb_info *fbi)
        clk_disable_unprepare(fbi->clk_per);
        clk_disable_unprepare(fbi->clk_ipg);
        clk_disable_unprepare(fbi->clk_ahb);
+       fbi->enabled = false;
 
        writel(0, fbi->regs + LCDC_RMCR);
 }
@@ -729,6 +739,8 @@ static int __init imxfb_init_fbinfo(struct platform_device *pdev)
 
        memset(fbi, 0, sizeof(struct imxfb_info));
 
+       fbi->devtype = pdev->id_entry->driver_data;
+
        strlcpy(info->fix.id, IMX_NAME, sizeof(info->fix.id));
 
        info->fix.type                  = FB_TYPE_PACKED_PIXELS;
@@ -789,7 +801,6 @@ static int __init imxfb_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        fbi = info->par;
-       fbi->devtype = pdev->id_entry->driver_data;
 
        if (!fb_mode)
                fb_mode = pdata->mode[0].mode.name;
index 4dcfced..084041d 100644 (file)
@@ -25,10 +25,10 @@ static void disable_hotplug_cpu(int cpu)
 static int vcpu_online(unsigned int cpu)
 {
        int err;
-       char dir[32], state[32];
+       char dir[16], state[16];
 
        sprintf(dir, "cpu/%u", cpu);
-       err = xenbus_scanf(XBT_NIL, dir, "availability", "%s", state);
+       err = xenbus_scanf(XBT_NIL, dir, "availability", "%15s", state);
        if (err != 1) {
                if (!xen_initial_domain())
                        printk(KERN_ERR "XENBUS: Unable to read cpu state\n");
index 2e22df2..3c8803f 100644 (file)
@@ -56,10 +56,15 @@ MODULE_PARM_DESC(limit, "Maximum number of grants that may be mapped by "
 static atomic_t pages_mapped = ATOMIC_INIT(0);
 
 static int use_ptemod;
+#define populate_freeable_maps use_ptemod
 
 struct gntdev_priv {
+       /* maps with visible offsets in the file descriptor */
        struct list_head maps;
-       /* lock protects maps from concurrent changes */
+       /* maps that are not visible; will be freed on munmap.
+        * Only populated if populate_freeable_maps == 1 */
+       struct list_head freeable_maps;
+       /* lock protects maps and freeable_maps */
        spinlock_t lock;
        struct mm_struct *mm;
        struct mmu_notifier mn;
@@ -193,7 +198,7 @@ static struct grant_map *gntdev_find_map_index(struct gntdev_priv *priv,
        return NULL;
 }
 
-static void gntdev_put_map(struct grant_map *map)
+static void gntdev_put_map(struct gntdev_priv *priv, struct grant_map *map)
 {
        if (!map)
                return;
@@ -208,6 +213,12 @@ static void gntdev_put_map(struct grant_map *map)
                evtchn_put(map->notify.event);
        }
 
+       if (populate_freeable_maps && priv) {
+               spin_lock(&priv->lock);
+               list_del(&map->next);
+               spin_unlock(&priv->lock);
+       }
+
        if (map->pages && !use_ptemod)
                unmap_grant_pages(map, 0, map->count);
        gntdev_free_map(map);
@@ -301,17 +312,10 @@ static int __unmap_grant_pages(struct grant_map *map, int offset, int pages)
 
        if (map->notify.flags & UNMAP_NOTIFY_CLEAR_BYTE) {
                int pgno = (map->notify.addr >> PAGE_SHIFT);
-               if (pgno >= offset && pgno < offset + pages && use_ptemod) {
-                       void __user *tmp = (void __user *)
-                               map->vma->vm_start + map->notify.addr;
-                       err = copy_to_user(tmp, &err, 1);
-                       if (err)
-                               return -EFAULT;
-                       map->notify.flags &= ~UNMAP_NOTIFY_CLEAR_BYTE;
-               } else if (pgno >= offset && pgno < offset + pages) {
-                       uint8_t *tmp = kmap(map->pages[pgno]);
+               if (pgno >= offset && pgno < offset + pages) {
+                       /* No need for kmap, pages are in lowmem */
+                       uint8_t *tmp = pfn_to_kaddr(page_to_pfn(map->pages[pgno]));
                        tmp[map->notify.addr & (PAGE_SIZE-1)] = 0;
-                       kunmap(map->pages[pgno]);
                        map->notify.flags &= ~UNMAP_NOTIFY_CLEAR_BYTE;
                }
        }
@@ -376,11 +380,24 @@ static void gntdev_vma_open(struct vm_area_struct *vma)
 static void gntdev_vma_close(struct vm_area_struct *vma)
 {
        struct grant_map *map = vma->vm_private_data;
+       struct file *file = vma->vm_file;
+       struct gntdev_priv *priv = file->private_data;
 
        pr_debug("gntdev_vma_close %p\n", vma);
-       map->vma = NULL;
+       if (use_ptemod) {
+               /* It is possible that an mmu notifier could be running
+                * concurrently, so take priv->lock to ensure that the vma won't
+                * vanishing during the unmap_grant_pages call, since we will
+                * spin here until that completes. Such a concurrent call will
+                * not do any unmapping, since that has been done prior to
+                * closing the vma, but it may still iterate the unmap_ops list.
+                */
+               spin_lock(&priv->lock);
+               map->vma = NULL;
+               spin_unlock(&priv->lock);
+       }
        vma->vm_private_data = NULL;
-       gntdev_put_map(map);
+       gntdev_put_map(priv, map);
 }
 
 static struct vm_operations_struct gntdev_vmops = {
@@ -390,33 +407,43 @@ static struct vm_operations_struct gntdev_vmops = {
 
 /* ------------------------------------------------------------------ */
 
+static void unmap_if_in_range(struct grant_map *map,
+                             unsigned long start, unsigned long end)
+{
+       unsigned long mstart, mend;
+       int err;
+
+       if (!map->vma)
+               return;
+       if (map->vma->vm_start >= end)
+               return;
+       if (map->vma->vm_end <= start)
+               return;
+       mstart = max(start, map->vma->vm_start);
+       mend   = min(end,   map->vma->vm_end);
+       pr_debug("map %d+%d (%lx %lx), range %lx %lx, mrange %lx %lx\n",
+                       map->index, map->count,
+                       map->vma->vm_start, map->vma->vm_end,
+                       start, end, mstart, mend);
+       err = unmap_grant_pages(map,
+                               (mstart - map->vma->vm_start) >> PAGE_SHIFT,
+                               (mend - mstart) >> PAGE_SHIFT);
+       WARN_ON(err);
+}
+
 static void mn_invl_range_start(struct mmu_notifier *mn,
                                struct mm_struct *mm,
                                unsigned long start, unsigned long end)
 {
        struct gntdev_priv *priv = container_of(mn, struct gntdev_priv, mn);
        struct grant_map *map;
-       unsigned long mstart, mend;
-       int err;
 
        spin_lock(&priv->lock);
        list_for_each_entry(map, &priv->maps, next) {
-               if (!map->vma)
-                       continue;
-               if (map->vma->vm_start >= end)
-                       continue;
-               if (map->vma->vm_end <= start)
-                       continue;
-               mstart = max(start, map->vma->vm_start);
-               mend   = min(end,   map->vma->vm_end);
-               pr_debug("map %d+%d (%lx %lx), range %lx %lx, mrange %lx %lx\n",
-                               map->index, map->count,
-                               map->vma->vm_start, map->vma->vm_end,
-                               start, end, mstart, mend);
-               err = unmap_grant_pages(map,
-                                       (mstart - map->vma->vm_start) >> PAGE_SHIFT,
-                                       (mend - mstart) >> PAGE_SHIFT);
-               WARN_ON(err);
+               unmap_if_in_range(map, start, end);
+       }
+       list_for_each_entry(map, &priv->freeable_maps, next) {
+               unmap_if_in_range(map, start, end);
        }
        spin_unlock(&priv->lock);
 }
@@ -445,6 +472,15 @@ static void mn_release(struct mmu_notifier *mn,
                err = unmap_grant_pages(map, /* offset */ 0, map->count);
                WARN_ON(err);
        }
+       list_for_each_entry(map, &priv->freeable_maps, next) {
+               if (!map->vma)
+                       continue;
+               pr_debug("map %d+%d (%lx %lx)\n",
+                               map->index, map->count,
+                               map->vma->vm_start, map->vma->vm_end);
+               err = unmap_grant_pages(map, /* offset */ 0, map->count);
+               WARN_ON(err);
+       }
        spin_unlock(&priv->lock);
 }
 
@@ -466,6 +502,7 @@ static int gntdev_open(struct inode *inode, struct file *flip)
                return -ENOMEM;
 
        INIT_LIST_HEAD(&priv->maps);
+       INIT_LIST_HEAD(&priv->freeable_maps);
        spin_lock_init(&priv->lock);
 
        if (use_ptemod) {
@@ -500,8 +537,9 @@ static int gntdev_release(struct inode *inode, struct file *flip)
        while (!list_empty(&priv->maps)) {
                map = list_entry(priv->maps.next, struct grant_map, next);
                list_del(&map->next);
-               gntdev_put_map(map);
+               gntdev_put_map(NULL /* already removed */, map);
        }
+       WARN_ON(!list_empty(&priv->freeable_maps));
 
        if (use_ptemod)
                mmu_notifier_unregister(&priv->mn, priv->mm);
@@ -529,14 +567,14 @@ static long gntdev_ioctl_map_grant_ref(struct gntdev_priv *priv,
 
        if (unlikely(atomic_add_return(op.count, &pages_mapped) > limit)) {
                pr_debug("can't map: over limit\n");
-               gntdev_put_map(map);
+               gntdev_put_map(NULL, map);
                return err;
        }
 
        if (copy_from_user(map->grants, &u->refs,
                           sizeof(map->grants[0]) * op.count) != 0) {
-               gntdev_put_map(map);
-               return err;
+               gntdev_put_map(NULL, map);
+               return -EFAULT;
        }
 
        spin_lock(&priv->lock);
@@ -565,11 +603,13 @@ static long gntdev_ioctl_unmap_grant_ref(struct gntdev_priv *priv,
        map = gntdev_find_map_index(priv, op.index >> PAGE_SHIFT, op.count);
        if (map) {
                list_del(&map->next);
+               if (populate_freeable_maps)
+                       list_add_tail(&map->next, &priv->freeable_maps);
                err = 0;
        }
        spin_unlock(&priv->lock);
        if (map)
-               gntdev_put_map(map);
+               gntdev_put_map(priv, map);
        return err;
 }
 
@@ -579,25 +619,31 @@ static long gntdev_ioctl_get_offset_for_vaddr(struct gntdev_priv *priv,
        struct ioctl_gntdev_get_offset_for_vaddr op;
        struct vm_area_struct *vma;
        struct grant_map *map;
+       int rv = -EINVAL;
 
        if (copy_from_user(&op, u, sizeof(op)) != 0)
                return -EFAULT;
        pr_debug("priv %p, offset for vaddr %lx\n", priv, (unsigned long)op.vaddr);
 
+       down_read(&current->mm->mmap_sem);
        vma = find_vma(current->mm, op.vaddr);
        if (!vma || vma->vm_ops != &gntdev_vmops)
-               return -EINVAL;
+               goto out_unlock;
 
        map = vma->vm_private_data;
        if (!map)
-               return -EINVAL;
+               goto out_unlock;
 
        op.offset = map->index << PAGE_SHIFT;
        op.count = map->count;
+       rv = 0;
 
-       if (copy_to_user(u, &op, sizeof(op)) != 0)
+ out_unlock:
+       up_read(&current->mm->mmap_sem);
+
+       if (rv == 0 && copy_to_user(u, &op, sizeof(op)) != 0)
                return -EFAULT;
-       return 0;
+       return rv;
 }
 
 static long gntdev_ioctl_notify(struct gntdev_priv *priv, void __user *u)
@@ -778,7 +824,7 @@ out_unlock_put:
 out_put_map:
        if (use_ptemod)
                map->vma = NULL;
-       gntdev_put_map(map);
+       gntdev_put_map(priv, map);
        return err;
 }
 
index 7038de5..157c0cc 100644 (file)
 /* External tools reserve first few grant table entries. */
 #define NR_RESERVED_ENTRIES 8
 #define GNTTAB_LIST_END 0xffffffff
-#define GREFS_PER_GRANT_FRAME \
-(grant_table_version == 1 ?                      \
-(PAGE_SIZE / sizeof(struct grant_entry_v1)) :   \
-(PAGE_SIZE / sizeof(union grant_entry_v2)))
 
 static grant_ref_t **gnttab_list;
 static unsigned int nr_grant_frames;
@@ -154,6 +150,7 @@ static struct gnttab_ops *gnttab_interface;
 static grant_status_t *grstatus;
 
 static int grant_table_version;
+static int grefs_per_grant_frame;
 
 static struct gnttab_free_callback *gnttab_free_callback_list;
 
@@ -767,12 +764,14 @@ static int grow_gnttab_list(unsigned int more_frames)
        unsigned int new_nr_grant_frames, extra_entries, i;
        unsigned int nr_glist_frames, new_nr_glist_frames;
 
+       BUG_ON(grefs_per_grant_frame == 0);
+
        new_nr_grant_frames = nr_grant_frames + more_frames;
-       extra_entries       = more_frames * GREFS_PER_GRANT_FRAME;
+       extra_entries       = more_frames * grefs_per_grant_frame;
 
-       nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP;
+       nr_glist_frames = (nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP;
        new_nr_glist_frames =
-               (new_nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP;
+               (new_nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP;
        for (i = nr_glist_frames; i < new_nr_glist_frames; i++) {
                gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_ATOMIC);
                if (!gnttab_list[i])
@@ -780,12 +779,12 @@ static int grow_gnttab_list(unsigned int more_frames)
        }
 
 
-       for (i = GREFS_PER_GRANT_FRAME * nr_grant_frames;
-            i < GREFS_PER_GRANT_FRAME * new_nr_grant_frames - 1; i++)
+       for (i = grefs_per_grant_frame * nr_grant_frames;
+            i < grefs_per_grant_frame * new_nr_grant_frames - 1; i++)
                gnttab_entry(i) = i + 1;
 
        gnttab_entry(i) = gnttab_free_head;
-       gnttab_free_head = GREFS_PER_GRANT_FRAME * nr_grant_frames;
+       gnttab_free_head = grefs_per_grant_frame * nr_grant_frames;
        gnttab_free_count += extra_entries;
 
        nr_grant_frames = new_nr_grant_frames;
@@ -957,7 +956,8 @@ EXPORT_SYMBOL_GPL(gnttab_unmap_refs);
 
 static unsigned nr_status_frames(unsigned nr_grant_frames)
 {
-       return (nr_grant_frames * GREFS_PER_GRANT_FRAME + SPP - 1) / SPP;
+       BUG_ON(grefs_per_grant_frame == 0);
+       return (nr_grant_frames * grefs_per_grant_frame + SPP - 1) / SPP;
 }
 
 static int gnttab_map_frames_v1(xen_pfn_t *frames, unsigned int nr_gframes)
@@ -1115,6 +1115,7 @@ static void gnttab_request_version(void)
        rc = HYPERVISOR_grant_table_op(GNTTABOP_set_version, &gsv, 1);
        if (rc == 0 && gsv.version == 2) {
                grant_table_version = 2;
+               grefs_per_grant_frame = PAGE_SIZE / sizeof(union grant_entry_v2);
                gnttab_interface = &gnttab_v2_ops;
        } else if (grant_table_version == 2) {
                /*
@@ -1127,17 +1128,17 @@ static void gnttab_request_version(void)
                panic("we need grant tables version 2, but only version 1 is available");
        } else {
                grant_table_version = 1;
+               grefs_per_grant_frame = PAGE_SIZE / sizeof(struct grant_entry_v1);
                gnttab_interface = &gnttab_v1_ops;
        }
        printk(KERN_INFO "Grant tables using version %d layout.\n",
                grant_table_version);
 }
 
-int gnttab_resume(void)
+static int gnttab_setup(void)
 {
        unsigned int max_nr_gframes;
 
-       gnttab_request_version();
        max_nr_gframes = gnttab_max_grant_frames();
        if (max_nr_gframes < nr_grant_frames)
                return -ENOSYS;
@@ -1160,6 +1161,12 @@ int gnttab_resume(void)
        return 0;
 }
 
+int gnttab_resume(void)
+{
+       gnttab_request_version();
+       return gnttab_setup();
+}
+
 int gnttab_suspend(void)
 {
        gnttab_interface->unmap_frames();
@@ -1171,9 +1178,10 @@ static int gnttab_expand(unsigned int req_entries)
        int rc;
        unsigned int cur, extra;
 
+       BUG_ON(grefs_per_grant_frame == 0);
        cur = nr_grant_frames;
-       extra = ((req_entries + (GREFS_PER_GRANT_FRAME-1)) /
-                GREFS_PER_GRANT_FRAME);
+       extra = ((req_entries + (grefs_per_grant_frame-1)) /
+                grefs_per_grant_frame);
        if (cur + extra > gnttab_max_grant_frames())
                return -ENOSPC;
 
@@ -1191,21 +1199,23 @@ int gnttab_init(void)
        unsigned int nr_init_grefs;
        int ret;
 
+       gnttab_request_version();
        nr_grant_frames = 1;
        boot_max_nr_grant_frames = __max_nr_grant_frames();
 
        /* Determine the maximum number of frames required for the
         * grant reference free list on the current hypervisor.
         */
+       BUG_ON(grefs_per_grant_frame == 0);
        max_nr_glist_frames = (boot_max_nr_grant_frames *
-                              GREFS_PER_GRANT_FRAME / RPP);
+                              grefs_per_grant_frame / RPP);
 
        gnttab_list = kmalloc(max_nr_glist_frames * sizeof(grant_ref_t *),
                              GFP_KERNEL);
        if (gnttab_list == NULL)
                return -ENOMEM;
 
-       nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP;
+       nr_glist_frames = (nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP;
        for (i = 0; i < nr_glist_frames; i++) {
                gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_KERNEL);
                if (gnttab_list[i] == NULL) {
@@ -1214,12 +1224,12 @@ int gnttab_init(void)
                }
        }
 
-       if (gnttab_resume() < 0) {
+       if (gnttab_setup() < 0) {
                ret = -ENODEV;
                goto ini_nomem;
        }
 
-       nr_init_grefs = nr_grant_frames * GREFS_PER_GRANT_FRAME;
+       nr_init_grefs = nr_grant_frames * grefs_per_grant_frame;
 
        for (i = NR_RESERVED_ENTRIES; i < nr_init_grefs - 1; i++)
                gnttab_entry(i) = i + 1;
index 0bbbccb..ca2b00e 100644 (file)
@@ -199,9 +199,6 @@ static long privcmd_ioctl_mmap(void __user *udata)
        LIST_HEAD(pagelist);
        struct mmap_mfn_state state;
 
-       if (!xen_initial_domain())
-               return -EPERM;
-
        /* We only support privcmd_ioctl_mmap_batch for auto translated. */
        if (xen_feature(XENFEAT_auto_translated_physmap))
                return -ENOSYS;
@@ -261,11 +258,12 @@ struct mmap_batch_state {
         *      -ENOENT if at least 1 -ENOENT has happened.
         */
        int global_error;
-       /* An array for individual errors */
-       int *err;
+       int version;
 
        /* User-space mfn array to store errors in the second pass for V1. */
        xen_pfn_t __user *user_mfn;
+       /* User-space int array to store errors in the second pass for V2. */
+       int __user *user_err;
 };
 
 /* auto translated dom0 note: if domU being created is PV, then mfn is
@@ -288,7 +286,19 @@ static int mmap_batch_fn(void *data, void *state)
                                         &cur_page);
 
        /* Store error code for second pass. */
-       *(st->err++) = ret;
+       if (st->version == 1) {
+               if (ret < 0) {
+                       /*
+                        * V1 encodes the error codes in the 32bit top nibble of the
+                        * mfn (with its known limitations vis-a-vis 64 bit callers).
+                        */
+                       *mfnp |= (ret == -ENOENT) ?
+                                               PRIVCMD_MMAPBATCH_PAGED_ERROR :
+                                               PRIVCMD_MMAPBATCH_MFN_ERROR;
+               }
+       } else { /* st->version == 2 */
+               *((int *) mfnp) = ret;
+       }
 
        /* And see if it affects the global_error. */
        if (ret < 0) {
@@ -305,20 +315,25 @@ static int mmap_batch_fn(void *data, void *state)
        return 0;
 }
 
-static int mmap_return_errors_v1(void *data, void *state)
+static int mmap_return_errors(void *data, void *state)
 {
-       xen_pfn_t *mfnp = data;
        struct mmap_batch_state *st = state;
-       int err = *(st->err++);
 
-       /*
-        * V1 encodes the error codes in the 32bit top nibble of the
-        * mfn (with its known limitations vis-a-vis 64 bit callers).
-        */
-       *mfnp |= (err == -ENOENT) ?
-                               PRIVCMD_MMAPBATCH_PAGED_ERROR :
-                               PRIVCMD_MMAPBATCH_MFN_ERROR;
-       return __put_user(*mfnp, st->user_mfn++);
+       if (st->version == 1) {
+               xen_pfn_t mfnp = *((xen_pfn_t *) data);
+               if (mfnp & PRIVCMD_MMAPBATCH_MFN_ERROR)
+                       return __put_user(mfnp, st->user_mfn++);
+               else
+                       st->user_mfn++;
+       } else { /* st->version == 2 */
+               int err = *((int *) data);
+               if (err)
+                       return __put_user(err, st->user_err++);
+               else
+                       st->user_err++;
+       }
+
+       return 0;
 }
 
 /* Allocate pfns that are then mapped with gmfns from foreign domid. Update
@@ -357,12 +372,8 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version)
        struct vm_area_struct *vma;
        unsigned long nr_pages;
        LIST_HEAD(pagelist);
-       int *err_array = NULL;
        struct mmap_batch_state state;
 
-       if (!xen_initial_domain())
-               return -EPERM;
-
        switch (version) {
        case 1:
                if (copy_from_user(&m, udata, sizeof(struct privcmd_mmapbatch)))
@@ -396,10 +407,12 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version)
                goto out;
        }
 
-       err_array = kcalloc(m.num, sizeof(int), GFP_KERNEL);
-       if (err_array == NULL) {
-               ret = -ENOMEM;
-               goto out;
+       if (version == 2) {
+               /* Zero error array now to only copy back actual errors. */
+               if (clear_user(m.err, sizeof(int) * m.num)) {
+                       ret = -EFAULT;
+                       goto out;
+               }
        }
 
        down_write(&mm->mmap_sem);
@@ -427,7 +440,7 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version)
        state.va            = m.addr;
        state.index         = 0;
        state.global_error  = 0;
-       state.err           = err_array;
+       state.version       = version;
 
        /* mmap_batch_fn guarantees ret == 0 */
        BUG_ON(traverse_pages(m.num, sizeof(xen_pfn_t),
@@ -435,21 +448,14 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version)
 
        up_write(&mm->mmap_sem);
 
-       if (version == 1) {
-               if (state.global_error) {
-                       /* Write back errors in second pass. */
-                       state.user_mfn = (xen_pfn_t *)m.arr;
-                       state.err      = err_array;
-                       ret = traverse_pages(m.num, sizeof(xen_pfn_t),
-                                            &pagelist, mmap_return_errors_v1, &state);
-               } else
-                       ret = 0;
-
-       } else if (version == 2) {
-               ret = __copy_to_user(m.err, err_array, m.num * sizeof(int));
-               if (ret)
-                       ret = -EFAULT;
-       }
+       if (state.global_error) {
+               /* Write back errors in second pass. */
+               state.user_mfn = (xen_pfn_t *)m.arr;
+               state.user_err = m.err;
+               ret = traverse_pages(m.num, sizeof(xen_pfn_t),
+                                                        &pagelist, mmap_return_errors, &state);
+       } else
+               ret = 0;
 
        /* If we have not had any EFAULT-like global errors then set the global
         * error to -ENOENT if necessary. */
@@ -457,7 +463,6 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version)
                ret = -ENOENT;
 
 out:
-       kfree(err_array);
        free_page_list(&pagelist);
 
        return ret;
index a7def01..f72af87 100644 (file)
@@ -124,7 +124,7 @@ static inline int xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev,
 static inline void xen_pcibk_release_pci_dev(struct xen_pcibk_device *pdev,
                                             struct pci_dev *dev)
 {
-       if (xen_pcibk_backend && xen_pcibk_backend->free)
+       if (xen_pcibk_backend && xen_pcibk_backend->release)
                return xen_pcibk_backend->release(pdev, dev);
 }
 
index cfe512f..780725a 100644 (file)
@@ -68,16 +68,6 @@ source "fs/quota/Kconfig"
 source "fs/autofs4/Kconfig"
 source "fs/fuse/Kconfig"
 
-config CUSE
-       tristate "Character device in Userspace support"
-       depends on FUSE_FS
-       help
-         This FUSE extension allows character devices to be
-         implemented in userspace.
-
-         If you want to develop or use userspace character device
-         based on CUSE, answer Y or M.
-
 config GENERIC_ACL
        bool
        select FS_POSIX_ACL
index 521e9d4..a8b8adc 100644 (file)
@@ -3997,7 +3997,7 @@ again:
         * We make the other tasks wait for the flush only when we can flush
         * all things.
         */
-       if (ret && flush == BTRFS_RESERVE_FLUSH_ALL) {
+       if (ret && flush != BTRFS_RESERVE_NO_FLUSH) {
                flushing = true;
                space_info->flush = 1;
        }
@@ -5560,7 +5560,7 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,
        int empty_cluster = 2 * 1024 * 1024;
        struct btrfs_space_info *space_info;
        int loop = 0;
-       int index = 0;
+       int index = __get_raid_index(data);
        int alloc_type = (data & BTRFS_BLOCK_GROUP_DATA) ?
                RESERVE_ALLOC_NO_ACCOUNT : RESERVE_ALLOC;
        bool found_uncached_bg = false;
@@ -6788,11 +6788,13 @@ static noinline int walk_up_proc(struct btrfs_trans_handle *trans,
                                                       &wc->flags[level]);
                        if (ret < 0) {
                                btrfs_tree_unlock_rw(eb, path->locks[level]);
+                               path->locks[level] = 0;
                                return ret;
                        }
                        BUG_ON(wc->refs[level] == 0);
                        if (wc->refs[level] == 1) {
                                btrfs_tree_unlock_rw(eb, path->locks[level]);
+                               path->locks[level] = 0;
                                return 1;
                        }
                }
index f169d6b..2e8cae6 100644 (file)
@@ -171,6 +171,10 @@ static int mergable_maps(struct extent_map *prev, struct extent_map *next)
        if (test_bit(EXTENT_FLAG_COMPRESSED, &prev->flags))
                return 0;
 
+       if (test_bit(EXTENT_FLAG_LOGGING, &prev->flags) ||
+           test_bit(EXTENT_FLAG_LOGGING, &next->flags))
+               return 0;
+
        if (extent_map_end(prev) == next->start &&
            prev->flags == next->flags &&
            prev->bdev == next->bdev &&
@@ -255,7 +259,8 @@ int unpin_extent_cache(struct extent_map_tree *tree, u64 start, u64 len,
        if (!em)
                goto out;
 
-       list_move(&em->list, &tree->modified_extents);
+       if (!test_bit(EXTENT_FLAG_LOGGING, &em->flags))
+               list_move(&em->list, &tree->modified_extents);
        em->generation = gen;
        clear_bit(EXTENT_FLAG_PINNED, &em->flags);
        em->mod_start = em->start;
@@ -280,6 +285,12 @@ out:
 
 }
 
+void clear_em_logging(struct extent_map_tree *tree, struct extent_map *em)
+{
+       clear_bit(EXTENT_FLAG_LOGGING, &em->flags);
+       try_merge_map(tree, em);
+}
+
 /**
  * add_extent_mapping - add new extent map to the extent tree
  * @tree:      tree to insert new map in
index 922943c..c6598c8 100644 (file)
@@ -69,6 +69,7 @@ void free_extent_map(struct extent_map *em);
 int __init extent_map_init(void);
 void extent_map_exit(void);
 int unpin_extent_cache(struct extent_map_tree *tree, u64 start, u64 len, u64 gen);
+void clear_em_logging(struct extent_map_tree *tree, struct extent_map *em);
 struct extent_map *search_extent_mapping(struct extent_map_tree *tree,
                                         u64 start, u64 len);
 #endif
index bd38cef..94aa53b 100644 (file)
@@ -460,8 +460,8 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode,
                if (!contig)
                        offset = page_offset(bvec->bv_page) + bvec->bv_offset;
 
-               if (!contig && (offset >= ordered->file_offset + ordered->len ||
-                   offset < ordered->file_offset)) {
+               if (offset >= ordered->file_offset + ordered->len ||
+                   offset < ordered->file_offset) {
                        unsigned long bytes_left;
                        sums->len = this_sum_bytes;
                        this_sum_bytes = 0;
index 77061bf..f76b1fd 100644 (file)
@@ -2241,6 +2241,7 @@ static int find_desired_extent(struct inode *inode, loff_t *offset, int whence)
        if (lockend <= lockstart)
                lockend = lockstart + root->sectorsize;
 
+       lockend--;
        len = lockend - lockstart + 1;
 
        len = max_t(u64, len, root->sectorsize);
@@ -2307,9 +2308,12 @@ static int find_desired_extent(struct inode *inode, loff_t *offset, int whence)
                                        }
                                }
 
-                               *offset = start;
-                               free_extent_map(em);
-                               break;
+                               if (!test_bit(EXTENT_FLAG_PREALLOC,
+                                             &em->flags)) {
+                                       *offset = start;
+                                       free_extent_map(em);
+                                       break;
+                               }
                        }
                }
 
index 59ea2e4..0be7a87 100644 (file)
@@ -1862,11 +1862,13 @@ int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group,
 {
        struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
        struct btrfs_free_space *info;
-       int ret = 0;
+       int ret;
+       bool re_search = false;
 
        spin_lock(&ctl->tree_lock);
 
 again:
+       ret = 0;
        if (!bytes)
                goto out_lock;
 
@@ -1879,17 +1881,17 @@ again:
                info = tree_search_offset(ctl, offset_to_bitmap(ctl, offset),
                                          1, 0);
                if (!info) {
-                       /* the tree logging code might be calling us before we
-                        * have fully loaded the free space rbtree for this
-                        * block group.  So it is possible the entry won't
-                        * be in the rbtree yet at all.  The caching code
-                        * will make sure not to put it in the rbtree if
-                        * the logging code has pinned it.
+                       /*
+                        * If we found a partial bit of our free space in a
+                        * bitmap but then couldn't find the other part this may
+                        * be a problem, so WARN about it.
                         */
+                       WARN_ON(re_search);
                        goto out_lock;
                }
        }
 
+       re_search = false;
        if (!info->bitmap) {
                unlink_free_space(ctl, info);
                if (offset == info->offset) {
@@ -1935,8 +1937,10 @@ again:
        }
 
        ret = remove_from_bitmap(ctl, info, &offset, &bytes);
-       if (ret == -EAGAIN)
+       if (ret == -EAGAIN) {
+               re_search = true;
                goto again;
+       }
        BUG_ON(ret); /* logic error */
 out_lock:
        spin_unlock(&ctl->tree_lock);
index 16d9e8e..cc93b23 100644 (file)
@@ -88,7 +88,7 @@ static unsigned char btrfs_type_by_mode[S_IFMT >> S_SHIFT] = {
        [S_IFLNK >> S_SHIFT]    = BTRFS_FT_SYMLINK,
 };
 
-static int btrfs_setsize(struct inode *inode, loff_t newsize);
+static int btrfs_setsize(struct inode *inode, struct iattr *attr);
 static int btrfs_truncate(struct inode *inode);
 static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent);
 static noinline int cow_file_range(struct inode *inode,
@@ -2478,6 +2478,18 @@ int btrfs_orphan_cleanup(struct btrfs_root *root)
                                continue;
                        }
                        nr_truncate++;
+
+                       /* 1 for the orphan item deletion. */
+                       trans = btrfs_start_transaction(root, 1);
+                       if (IS_ERR(trans)) {
+                               ret = PTR_ERR(trans);
+                               goto out;
+                       }
+                       ret = btrfs_orphan_add(trans, inode);
+                       btrfs_end_transaction(trans, root);
+                       if (ret)
+                               goto out;
+
                        ret = btrfs_truncate(inode);
                } else {
                        nr_unlink++;
@@ -3665,6 +3677,7 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size)
                                block_end - cur_offset, 0);
                if (IS_ERR(em)) {
                        err = PTR_ERR(em);
+                       em = NULL;
                        break;
                }
                last_byte = min(extent_map_end(em), block_end);
@@ -3748,16 +3761,27 @@ next:
        return err;
 }
 
-static int btrfs_setsize(struct inode *inode, loff_t newsize)
+static int btrfs_setsize(struct inode *inode, struct iattr *attr)
 {
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct btrfs_trans_handle *trans;
        loff_t oldsize = i_size_read(inode);
+       loff_t newsize = attr->ia_size;
+       int mask = attr->ia_valid;
        int ret;
 
        if (newsize == oldsize)
                return 0;
 
+       /*
+        * The regular truncate() case without ATTR_CTIME and ATTR_MTIME is a
+        * special case where we need to update the times despite not having
+        * these flags set.  For all other operations the VFS set these flags
+        * explicitly if it wants a timestamp update.
+        */
+       if (newsize != oldsize && (!(mask & (ATTR_CTIME | ATTR_MTIME))))
+               inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb);
+
        if (newsize > oldsize) {
                truncate_pagecache(inode, oldsize, newsize);
                ret = btrfs_cont_expand(inode, oldsize, newsize);
@@ -3783,9 +3807,34 @@ static int btrfs_setsize(struct inode *inode, loff_t newsize)
                        set_bit(BTRFS_INODE_ORDERED_DATA_CLOSE,
                                &BTRFS_I(inode)->runtime_flags);
 
+               /*
+                * 1 for the orphan item we're going to add
+                * 1 for the orphan item deletion.
+                */
+               trans = btrfs_start_transaction(root, 2);
+               if (IS_ERR(trans))
+                       return PTR_ERR(trans);
+
+               /*
+                * We need to do this in case we fail at _any_ point during the
+                * actual truncate.  Once we do the truncate_setsize we could
+                * invalidate pages which forces any outstanding ordered io to
+                * be instantly completed which will give us extents that need
+                * to be truncated.  If we fail to get an orphan inode down we
+                * could have left over extents that were never meant to live,
+                * so we need to garuntee from this point on that everything
+                * will be consistent.
+                */
+               ret = btrfs_orphan_add(trans, inode);
+               btrfs_end_transaction(trans, root);
+               if (ret)
+                       return ret;
+
                /* we don't support swapfiles, so vmtruncate shouldn't fail */
                truncate_setsize(inode, newsize);
                ret = btrfs_truncate(inode);
+               if (ret && inode->i_nlink)
+                       btrfs_orphan_del(NULL, inode);
        }
 
        return ret;
@@ -3805,7 +3854,7 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
                return err;
 
        if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) {
-               err = btrfs_setsize(inode, attr->ia_size);
+               err = btrfs_setsize(inode, attr);
                if (err)
                        return err;
        }
@@ -5572,10 +5621,13 @@ struct extent_map *btrfs_get_extent_fiemap(struct inode *inode, struct page *pag
                return em;
        if (em) {
                /*
-                * if our em maps to a hole, there might
-                * actually be delalloc bytes behind it
+                * if our em maps to
+                * -  a hole or
+                * -  a pre-alloc extent,
+                * there might actually be delalloc bytes behind it.
                 */
-               if (em->block_start != EXTENT_MAP_HOLE)
+               if (em->block_start != EXTENT_MAP_HOLE &&
+                   !test_bit(EXTENT_FLAG_PREALLOC, &em->flags))
                        return em;
                else
                        hole_em = em;
@@ -5657,6 +5709,8 @@ struct extent_map *btrfs_get_extent_fiemap(struct inode *inode, struct page *pag
                         */
                        em->block_start = hole_em->block_start;
                        em->block_len = hole_len;
+                       if (test_bit(EXTENT_FLAG_PREALLOC, &hole_em->flags))
+                               set_bit(EXTENT_FLAG_PREALLOC, &em->flags);
                } else {
                        em->start = range_start;
                        em->len = found;
@@ -6915,11 +6969,9 @@ static int btrfs_truncate(struct inode *inode)
 
        /*
         * 1 for the truncate slack space
-        * 1 for the orphan item we're going to add
-        * 1 for the orphan item deletion
         * 1 for updating the inode.
         */
-       trans = btrfs_start_transaction(root, 4);
+       trans = btrfs_start_transaction(root, 2);
        if (IS_ERR(trans)) {
                err = PTR_ERR(trans);
                goto out;
@@ -6930,12 +6982,6 @@ static int btrfs_truncate(struct inode *inode)
                                      min_size);
        BUG_ON(ret);
 
-       ret = btrfs_orphan_add(trans, inode);
-       if (ret) {
-               btrfs_end_transaction(trans, root);
-               goto out;
-       }
-
        /*
         * setattr is responsible for setting the ordered_data_close flag,
         * but that is only tested during the last file release.  That
@@ -7004,12 +7050,6 @@ static int btrfs_truncate(struct inode *inode)
                ret = btrfs_orphan_del(trans, inode);
                if (ret)
                        err = ret;
-       } else if (ret && inode->i_nlink > 0) {
-               /*
-                * Failed to do the truncate, remove us from the in memory
-                * orphan list.
-                */
-               ret = btrfs_orphan_del(NULL, inode);
        }
 
        if (trans) {
@@ -7531,41 +7571,61 @@ void btrfs_wait_and_free_delalloc_work(struct btrfs_delalloc_work *work)
  */
 int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput)
 {
-       struct list_head *head = &root->fs_info->delalloc_inodes;
        struct btrfs_inode *binode;
        struct inode *inode;
        struct btrfs_delalloc_work *work, *next;
        struct list_head works;
+       struct list_head splice;
        int ret = 0;
 
        if (root->fs_info->sb->s_flags & MS_RDONLY)
                return -EROFS;
 
        INIT_LIST_HEAD(&works);
-
+       INIT_LIST_HEAD(&splice);
+again:
        spin_lock(&root->fs_info->delalloc_lock);
-       while (!list_empty(head)) {
-               binode = list_entry(head->next, struct btrfs_inode,
+       list_splice_init(&root->fs_info->delalloc_inodes, &splice);
+       while (!list_empty(&splice)) {
+               binode = list_entry(splice.next, struct btrfs_inode,
                                    delalloc_inodes);
+
+               list_del_init(&binode->delalloc_inodes);
+
                inode = igrab(&binode->vfs_inode);
                if (!inode)
-                       list_del_init(&binode->delalloc_inodes);
+                       continue;
+
+               list_add_tail(&binode->delalloc_inodes,
+                             &root->fs_info->delalloc_inodes);
                spin_unlock(&root->fs_info->delalloc_lock);
-               if (inode) {
-                       work = btrfs_alloc_delalloc_work(inode, 0, delay_iput);
-                       if (!work) {
-                               ret = -ENOMEM;
-                               goto out;
-                       }
-                       list_add_tail(&work->list, &works);
-                       btrfs_queue_worker(&root->fs_info->flush_workers,
-                                          &work->work);
+
+               work = btrfs_alloc_delalloc_work(inode, 0, delay_iput);
+               if (unlikely(!work)) {
+                       ret = -ENOMEM;
+                       goto out;
                }
+               list_add_tail(&work->list, &works);
+               btrfs_queue_worker(&root->fs_info->flush_workers,
+                                  &work->work);
+
                cond_resched();
                spin_lock(&root->fs_info->delalloc_lock);
        }
        spin_unlock(&root->fs_info->delalloc_lock);
 
+       list_for_each_entry_safe(work, next, &works, list) {
+               list_del_init(&work->list);
+               btrfs_wait_and_free_delalloc_work(work);
+       }
+
+       spin_lock(&root->fs_info->delalloc_lock);
+       if (!list_empty(&root->fs_info->delalloc_inodes)) {
+               spin_unlock(&root->fs_info->delalloc_lock);
+               goto again;
+       }
+       spin_unlock(&root->fs_info->delalloc_lock);
+
        /* the filemap_flush will queue IO into the worker threads, but
         * we have to make sure the IO is actually started and that
         * ordered extents get created before we return
@@ -7578,11 +7638,18 @@ int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput)
                    atomic_read(&root->fs_info->async_delalloc_pages) == 0));
        }
        atomic_dec(&root->fs_info->async_submit_draining);
+       return 0;
 out:
        list_for_each_entry_safe(work, next, &works, list) {
                list_del_init(&work->list);
                btrfs_wait_and_free_delalloc_work(work);
        }
+
+       if (!list_empty_careful(&splice)) {
+               spin_lock(&root->fs_info->delalloc_lock);
+               list_splice_tail(&splice, &root->fs_info->delalloc_inodes);
+               spin_unlock(&root->fs_info->delalloc_lock);
+       }
        return ret;
 }
 
index 4b45167..5b22d45 100644 (file)
@@ -1339,7 +1339,8 @@ static noinline int btrfs_ioctl_resize(struct file *file,
        if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running,
                        1)) {
                pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n");
-               return -EINPROGRESS;
+               mnt_drop_write_file(file);
+               return -EINVAL;
        }
 
        mutex_lock(&root->fs_info->volume_mutex);
@@ -1362,6 +1363,7 @@ static noinline int btrfs_ioctl_resize(struct file *file,
                printk(KERN_INFO "btrfs: resizing devid %llu\n",
                       (unsigned long long)devid);
        }
+
        device = btrfs_find_device(root->fs_info, devid, NULL, NULL);
        if (!device) {
                printk(KERN_INFO "btrfs: resizer unable to find device %llu\n",
@@ -1369,9 +1371,10 @@ static noinline int btrfs_ioctl_resize(struct file *file,
                ret = -EINVAL;
                goto out_free;
        }
-       if (device->fs_devices && device->fs_devices->seeding) {
+
+       if (!device->writeable) {
                printk(KERN_INFO "btrfs: resizer unable to apply on "
-                      "seeding device %llu\n",
+                      "readonly device %llu\n",
                       (unsigned long long)devid);
                ret = -EINVAL;
                goto out_free;
@@ -1443,8 +1446,8 @@ out_free:
        kfree(vol_args);
 out:
        mutex_unlock(&root->fs_info->volume_mutex);
-       mnt_drop_write_file(file);
        atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0);
+       mnt_drop_write_file(file);
        return ret;
 }
 
@@ -2095,13 +2098,13 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
                err = inode_permission(inode, MAY_WRITE | MAY_EXEC);
                if (err)
                        goto out_dput;
-
-               /* check if subvolume may be deleted by a non-root user */
-               err = btrfs_may_delete(dir, dentry, 1);
-               if (err)
-                       goto out_dput;
        }
 
+       /* check if subvolume may be deleted by a user */
+       err = btrfs_may_delete(dir, dentry, 1);
+       if (err)
+               goto out_dput;
+
        if (btrfs_ino(inode) != BTRFS_FIRST_FREE_OBJECTID) {
                err = -EINVAL;
                goto out_dput;
@@ -2183,19 +2186,20 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp)
        struct btrfs_ioctl_defrag_range_args *range;
        int ret;
 
-       if (btrfs_root_readonly(root))
-               return -EROFS;
+       ret = mnt_want_write_file(file);
+       if (ret)
+               return ret;
 
        if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running,
                        1)) {
                pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n");
-               return -EINPROGRESS;
+               mnt_drop_write_file(file);
+               return -EINVAL;
        }
-       ret = mnt_want_write_file(file);
-       if (ret) {
-               atomic_set(&root->fs_info->mutually_exclusive_operation_running,
-                          0);
-               return ret;
+
+       if (btrfs_root_readonly(root)) {
+               ret = -EROFS;
+               goto out;
        }
 
        switch (inode->i_mode & S_IFMT) {
@@ -2247,8 +2251,8 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp)
                ret = -EINVAL;
        }
 out:
-       mnt_drop_write_file(file);
        atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0);
+       mnt_drop_write_file(file);
        return ret;
 }
 
@@ -2263,7 +2267,7 @@ static long btrfs_ioctl_add_dev(struct btrfs_root *root, void __user *arg)
        if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running,
                        1)) {
                pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n");
-               return -EINPROGRESS;
+               return -EINVAL;
        }
 
        mutex_lock(&root->fs_info->volume_mutex);
@@ -2300,7 +2304,7 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg)
                        1)) {
                pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n");
                mnt_drop_write_file(file);
-               return -EINPROGRESS;
+               return -EINVAL;
        }
 
        mutex_lock(&root->fs_info->volume_mutex);
@@ -2316,8 +2320,8 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg)
        kfree(vol_args);
 out:
        mutex_unlock(&root->fs_info->volume_mutex);
-       mnt_drop_write_file(file);
        atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0);
+       mnt_drop_write_file(file);
        return ret;
 }
 
@@ -3437,8 +3441,8 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg)
        struct btrfs_fs_info *fs_info = root->fs_info;
        struct btrfs_ioctl_balance_args *bargs;
        struct btrfs_balance_control *bctl;
+       bool need_unlock; /* for mut. excl. ops lock */
        int ret;
-       int need_to_clear_lock = 0;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
@@ -3447,14 +3451,61 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg)
        if (ret)
                return ret;
 
-       mutex_lock(&fs_info->volume_mutex);
+again:
+       if (!atomic_xchg(&fs_info->mutually_exclusive_operation_running, 1)) {
+               mutex_lock(&fs_info->volume_mutex);
+               mutex_lock(&fs_info->balance_mutex);
+               need_unlock = true;
+               goto locked;
+       }
+
+       /*
+        * mut. excl. ops lock is locked.  Three possibilites:
+        *   (1) some other op is running
+        *   (2) balance is running
+        *   (3) balance is paused -- special case (think resume)
+        */
        mutex_lock(&fs_info->balance_mutex);
+       if (fs_info->balance_ctl) {
+               /* this is either (2) or (3) */
+               if (!atomic_read(&fs_info->balance_running)) {
+                       mutex_unlock(&fs_info->balance_mutex);
+                       if (!mutex_trylock(&fs_info->volume_mutex))
+                               goto again;
+                       mutex_lock(&fs_info->balance_mutex);
+
+                       if (fs_info->balance_ctl &&
+                           !atomic_read(&fs_info->balance_running)) {
+                               /* this is (3) */
+                               need_unlock = false;
+                               goto locked;
+                       }
+
+                       mutex_unlock(&fs_info->balance_mutex);
+                       mutex_unlock(&fs_info->volume_mutex);
+                       goto again;
+               } else {
+                       /* this is (2) */
+                       mutex_unlock(&fs_info->balance_mutex);
+                       ret = -EINPROGRESS;
+                       goto out;
+               }
+       } else {
+               /* this is (1) */
+               mutex_unlock(&fs_info->balance_mutex);
+               pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n");
+               ret = -EINVAL;
+               goto out;
+       }
+
+locked:
+       BUG_ON(!atomic_read(&fs_info->mutually_exclusive_operation_running));
 
        if (arg) {
                bargs = memdup_user(arg, sizeof(*bargs));
                if (IS_ERR(bargs)) {
                        ret = PTR_ERR(bargs);
-                       goto out;
+                       goto out_unlock;
                }
 
                if (bargs->flags & BTRFS_BALANCE_RESUME) {
@@ -3474,13 +3525,10 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg)
                bargs = NULL;
        }
 
-       if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running,
-                       1)) {
-               pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n");
+       if (fs_info->balance_ctl) {
                ret = -EINPROGRESS;
                goto out_bargs;
        }
-       need_to_clear_lock = 1;
 
        bctl = kzalloc(sizeof(*bctl), GFP_NOFS);
        if (!bctl) {
@@ -3501,11 +3549,17 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg)
        }
 
 do_balance:
-       ret = btrfs_balance(bctl, bargs);
        /*
-        * bctl is freed in __cancel_balance or in free_fs_info if
-        * restriper was paused all the way until unmount
+        * Ownership of bctl and mutually_exclusive_operation_running
+        * goes to to btrfs_balance.  bctl is freed in __cancel_balance,
+        * or, if restriper was paused all the way until unmount, in
+        * free_fs_info.  mutually_exclusive_operation_running is
+        * cleared in __cancel_balance.
         */
+       need_unlock = false;
+
+       ret = btrfs_balance(bctl, bargs);
+
        if (arg) {
                if (copy_to_user(arg, bargs, sizeof(*bargs)))
                        ret = -EFAULT;
@@ -3513,12 +3567,12 @@ do_balance:
 
 out_bargs:
        kfree(bargs);
-out:
-       if (need_to_clear_lock)
-               atomic_set(&root->fs_info->mutually_exclusive_operation_running,
-                          0);
+out_unlock:
        mutex_unlock(&fs_info->balance_mutex);
        mutex_unlock(&fs_info->volume_mutex);
+       if (need_unlock)
+               atomic_set(&fs_info->mutually_exclusive_operation_running, 0);
+out:
        mnt_drop_write_file(file);
        return ret;
 }
@@ -3698,6 +3752,11 @@ static long btrfs_ioctl_qgroup_create(struct file *file, void __user *arg)
                goto drop_write;
        }
 
+       if (!sa->qgroupid) {
+               ret = -EINVAL;
+               goto out;
+       }
+
        trans = btrfs_join_transaction(root);
        if (IS_ERR(trans)) {
                ret = PTR_ERR(trans);
index fe9d02c..a5c8562 100644 (file)
@@ -379,6 +379,13 @@ next1:
 
                ret = add_relation_rb(fs_info, found_key.objectid,
                                      found_key.offset);
+               if (ret == -ENOENT) {
+                       printk(KERN_WARNING
+                               "btrfs: orphan qgroup relation 0x%llx->0x%llx\n",
+                               (unsigned long long)found_key.objectid,
+                               (unsigned long long)found_key.offset);
+                       ret = 0;        /* ignore the error */
+               }
                if (ret)
                        goto out;
 next2:
@@ -956,17 +963,28 @@ int btrfs_remove_qgroup(struct btrfs_trans_handle *trans,
                        struct btrfs_fs_info *fs_info, u64 qgroupid)
 {
        struct btrfs_root *quota_root;
+       struct btrfs_qgroup *qgroup;
        int ret = 0;
 
        quota_root = fs_info->quota_root;
        if (!quota_root)
                return -EINVAL;
 
+       /* check if there are no relations to this qgroup */
+       spin_lock(&fs_info->qgroup_lock);
+       qgroup = find_qgroup_rb(fs_info, qgroupid);
+       if (qgroup) {
+               if (!list_empty(&qgroup->groups) || !list_empty(&qgroup->members)) {
+                       spin_unlock(&fs_info->qgroup_lock);
+                       return -EBUSY;
+               }
+       }
+       spin_unlock(&fs_info->qgroup_lock);
+
        ret = del_qgroup_item(trans, quota_root, qgroupid);
 
        spin_lock(&fs_info->qgroup_lock);
        del_qgroup_rb(quota_root->fs_info, qgroupid);
-
        spin_unlock(&fs_info->qgroup_lock);
 
        return ret;
index 5445454..321b7fb 100644 (file)
@@ -1814,8 +1814,10 @@ static int name_cache_insert(struct send_ctx *sctx,
                        (unsigned long)nce->ino);
        if (!nce_head) {
                nce_head = kmalloc(sizeof(*nce_head), GFP_NOFS);
-               if (!nce_head)
+               if (!nce_head) {
+                       kfree(nce);
                        return -ENOMEM;
+               }
                INIT_LIST_HEAD(nce_head);
 
                ret = radix_tree_insert(&sctx->name_cache, nce->ino, nce_head);
index 99545df..d8982e9 100644 (file)
@@ -267,7 +267,7 @@ void __btrfs_abort_transaction(struct btrfs_trans_handle *trans,
                             function, line, errstr);
                return;
        }
-       trans->transaction->aborted = errno;
+       ACCESS_ONCE(trans->transaction->aborted) = errno;
        __btrfs_std_error(root->fs_info, function, line, errno, NULL);
 }
 /*
index 87fac9a..f154946 100644 (file)
@@ -1468,7 +1468,8 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
                goto cleanup_transaction;
        }
 
-       if (cur_trans->aborted) {
+       /* Stop the commit early if ->aborted is set */
+       if (unlikely(ACCESS_ONCE(cur_trans->aborted))) {
                ret = cur_trans->aborted;
                goto cleanup_transaction;
        }
@@ -1574,6 +1575,11 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
        wait_event(cur_trans->writer_wait,
                   atomic_read(&cur_trans->num_writers) == 1);
 
+       /* ->aborted might be set after the previous check, so check it */
+       if (unlikely(ACCESS_ONCE(cur_trans->aborted))) {
+               ret = cur_trans->aborted;
+               goto cleanup_transaction;
+       }
        /*
         * the reloc mutex makes sure that we stop
         * the balancing code from coming in and moving
@@ -1657,6 +1663,17 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
                goto cleanup_transaction;
        }
 
+       /*
+        * The tasks which save the space cache and inode cache may also
+        * update ->aborted, check it.
+        */
+       if (unlikely(ACCESS_ONCE(cur_trans->aborted))) {
+               ret = cur_trans->aborted;
+               mutex_unlock(&root->fs_info->tree_log_mutex);
+               mutex_unlock(&root->fs_info->reloc_mutex);
+               goto cleanup_transaction;
+       }
+
        btrfs_prepare_extent_commit(trans, root);
 
        cur_trans = root->fs_info->running_transaction;
index 83186c7..9027bb1 100644 (file)
@@ -3357,6 +3357,11 @@ static int log_one_extent(struct btrfs_trans_handle *trans,
        if (skip_csum)
                return 0;
 
+       if (em->compress_type) {
+               csum_offset = 0;
+               csum_len = block_len;
+       }
+
        /* block start is already adjusted for the file extent offset. */
        ret = btrfs_lookup_csums_range(log->fs_info->csum_root,
                                       em->block_start + csum_offset,
@@ -3410,13 +3415,13 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans,
                em = list_entry(extents.next, struct extent_map, list);
 
                list_del_init(&em->list);
-               clear_bit(EXTENT_FLAG_LOGGING, &em->flags);
 
                /*
                 * If we had an error we just need to delete everybody from our
                 * private list.
                 */
                if (ret) {
+                       clear_em_logging(tree, em);
                        free_extent_map(em);
                        continue;
                }
@@ -3424,8 +3429,9 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans,
                write_unlock(&tree->lock);
 
                ret = log_one_extent(trans, inode, root, em, path);
-               free_extent_map(em);
                write_lock(&tree->lock);
+               clear_em_logging(tree, em);
+               free_extent_map(em);
        }
        WARN_ON(!list_empty(&extents));
        write_unlock(&tree->lock);
index 5cce6aa..15f6efd 100644 (file)
@@ -1431,7 +1431,7 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
                }
        } else {
                ret = btrfs_get_bdev_and_sb(device_path,
-                                           FMODE_READ | FMODE_EXCL,
+                                           FMODE_WRITE | FMODE_EXCL,
                                            root->fs_info->bdev_holder, 0,
                                            &bdev, &bh);
                if (ret)
@@ -2614,7 +2614,14 @@ static int chunk_usage_filter(struct btrfs_fs_info *fs_info, u64 chunk_offset,
        cache = btrfs_lookup_block_group(fs_info, chunk_offset);
        chunk_used = btrfs_block_group_used(&cache->item);
 
-       user_thresh = div_factor_fine(cache->key.offset, bargs->usage);
+       if (bargs->usage == 0)
+               user_thresh = 0;
+       else if (bargs->usage > 100)
+               user_thresh = cache->key.offset;
+       else
+               user_thresh = div_factor_fine(cache->key.offset,
+                                             bargs->usage);
+
        if (chunk_used < user_thresh)
                ret = 0;
 
@@ -2959,6 +2966,8 @@ static void __cancel_balance(struct btrfs_fs_info *fs_info)
        unset_balance_control(fs_info);
        ret = del_balance_item(fs_info->tree_root);
        BUG_ON(ret);
+
+       atomic_set(&fs_info->mutually_exclusive_operation_running, 0);
 }
 
 void update_ioctl_balance_args(struct btrfs_fs_info *fs_info, int lock,
@@ -3138,8 +3147,10 @@ int btrfs_balance(struct btrfs_balance_control *bctl,
 out:
        if (bctl->flags & BTRFS_BALANCE_RESUME)
                __cancel_balance(fs_info);
-       else
+       else {
                kfree(bctl);
+               atomic_set(&fs_info->mutually_exclusive_operation_running, 0);
+       }
        return ret;
 }
 
@@ -3156,7 +3167,6 @@ static int balance_kthread(void *data)
                ret = btrfs_balance(fs_info->balance_ctl, NULL);
        }
 
-       atomic_set(&fs_info->mutually_exclusive_operation_running, 0);
        mutex_unlock(&fs_info->balance_mutex);
        mutex_unlock(&fs_info->volume_mutex);
 
@@ -3179,7 +3189,6 @@ int btrfs_resume_balance_async(struct btrfs_fs_info *fs_info)
                return 0;
        }
 
-       WARN_ON(atomic_xchg(&fs_info->mutually_exclusive_operation_running, 1));
        tsk = kthread_run(balance_kthread, fs_info, "btrfs-balance");
        if (IS_ERR(tsk))
                return PTR_ERR(tsk);
@@ -3233,6 +3242,8 @@ int btrfs_recover_balance(struct btrfs_fs_info *fs_info)
        btrfs_balance_sys(leaf, item, &disk_bargs);
        btrfs_disk_balance_args_to_cpu(&bctl->sys, &disk_bargs);
 
+       WARN_ON(atomic_xchg(&fs_info->mutually_exclusive_operation_running, 1));
+
        mutex_lock(&fs_info->volume_mutex);
        mutex_lock(&fs_info->balance_mutex);
 
@@ -3496,7 +3507,7 @@ struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES] = {
        { 1, 1, 2, 2, 2, 2 /* raid1 */ },
        { 1, 2, 1, 1, 1, 2 /* dup */ },
        { 1, 1, 0, 2, 1, 1 /* raid0 */ },
-       { 1, 1, 0, 1, 1, 1 /* single */ },
+       { 1, 1, 1, 1, 1, 1 /* single */ },
 };
 
 static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
index ce5cbd7..210fce2 100644 (file)
@@ -226,6 +226,8 @@ compose_mount_options_out:
 compose_mount_options_err:
        kfree(mountdata);
        mountdata = ERR_PTR(rc);
+       kfree(*devname);
+       *devname = NULL;
        goto compose_mount_options_out;
 }
 
index 17c3643..12b3da3 100644 (file)
@@ -1917,7 +1917,7 @@ srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
        }
        case AF_INET6: {
                struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
-               struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)&rhs;
+               struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
                return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
        }
        default:
index e95b949..137af42 100644 (file)
@@ -191,15 +191,14 @@ struct posix_acl *f2fs_get_acl(struct inode *inode, int type)
                retval = f2fs_getxattr(inode, name_index, "", value, retval);
        }
 
-       if (retval < 0) {
-               if (retval == -ENODATA)
-                       acl = NULL;
-               else
-                       acl = ERR_PTR(retval);
-       } else {
+       if (retval > 0)
                acl = f2fs_acl_from_disk(value, retval);
-       }
+       else if (retval == -ENODATA)
+               acl = NULL;
+       else
+               acl = ERR_PTR(retval);
        kfree(value);
+
        if (!IS_ERR(acl))
                set_cached_acl(inode, type, acl);
 
index 6ef36c3..ff3c843 100644 (file)
@@ -214,7 +214,6 @@ retry:
                goto retry;
        }
        new->ino = ino;
-       INIT_LIST_HEAD(&new->list);
 
        /* add new_oentry into list which is sorted by inode number */
        if (orphan) {
@@ -772,7 +771,7 @@ void init_orphan_info(struct f2fs_sb_info *sbi)
        sbi->n_orphans = 0;
 }
 
-int create_checkpoint_caches(void)
+int __init create_checkpoint_caches(void)
 {
        orphan_entry_slab = f2fs_kmem_cache_create("f2fs_orphan_entry",
                        sizeof(struct orphan_inode_entry), NULL);
index 3aa5ce7..7bd22a2 100644 (file)
@@ -547,6 +547,15 @@ redirty_out:
 
 #define MAX_DESIRED_PAGES_WP   4096
 
+static int __f2fs_writepage(struct page *page, struct writeback_control *wbc,
+                       void *data)
+{
+       struct address_space *mapping = data;
+       int ret = mapping->a_ops->writepage(page, wbc);
+       mapping_set_error(mapping, ret);
+       return ret;
+}
+
 static int f2fs_write_data_pages(struct address_space *mapping,
                            struct writeback_control *wbc)
 {
@@ -563,7 +572,7 @@ static int f2fs_write_data_pages(struct address_space *mapping,
 
        if (!S_ISDIR(inode->i_mode))
                mutex_lock(&sbi->writepages);
-       ret = generic_writepages(mapping, wbc);
+       ret = write_cache_pages(mapping, wbc, __f2fs_writepage, mapping);
        if (!S_ISDIR(inode->i_mode))
                mutex_unlock(&sbi->writepages);
        f2fs_submit_bio(sbi, DATA, (wbc->sync_mode == WB_SYNC_ALL));
@@ -689,6 +698,11 @@ static int f2fs_set_data_page_dirty(struct page *page)
        return 0;
 }
 
+static sector_t f2fs_bmap(struct address_space *mapping, sector_t block)
+{
+       return generic_block_bmap(mapping, block, get_data_block_ro);
+}
+
 const struct address_space_operations f2fs_dblock_aops = {
        .readpage       = f2fs_read_data_page,
        .readpages      = f2fs_read_data_pages,
@@ -700,4 +714,5 @@ const struct address_space_operations f2fs_dblock_aops = {
        .invalidatepage = f2fs_invalidate_data_page,
        .releasepage    = f2fs_release_data_page,
        .direct_IO      = f2fs_direct_IO,
+       .bmap           = f2fs_bmap,
 };
index 0e0380a..c8c3730 100644 (file)
@@ -26,6 +26,7 @@
 
 static LIST_HEAD(f2fs_stat_list);
 static struct dentry *debugfs_root;
+static DEFINE_MUTEX(f2fs_stat_mutex);
 
 static void update_general_status(struct f2fs_sb_info *sbi)
 {
@@ -180,18 +181,14 @@ static int stat_show(struct seq_file *s, void *v)
        int i = 0;
        int j;
 
+       mutex_lock(&f2fs_stat_mutex);
        list_for_each_entry_safe(si, next, &f2fs_stat_list, stat_list) {
 
-               mutex_lock(&si->stat_lock);
-               if (!si->sbi) {
-                       mutex_unlock(&si->stat_lock);
-                       continue;
-               }
                update_general_status(si->sbi);
 
                seq_printf(s, "\n=====[ partition info. #%d ]=====\n", i++);
-               seq_printf(s, "[SB: 1] [CP: 2] [NAT: %d] [SIT: %d] ",
-                          si->nat_area_segs, si->sit_area_segs);
+               seq_printf(s, "[SB: 1] [CP: 2] [SIT: %d] [NAT: %d] ",
+                          si->sit_area_segs, si->nat_area_segs);
                seq_printf(s, "[SSA: %d] [MAIN: %d",
                           si->ssa_area_segs, si->main_area_segs);
                seq_printf(s, "(OverProv:%d Resv:%d)]\n\n",
@@ -286,8 +283,8 @@ static int stat_show(struct seq_file *s, void *v)
                seq_printf(s, "\nMemory: %u KB = static: %u + cached: %u\n",
                                (si->base_mem + si->cache_mem) >> 10,
                                si->base_mem >> 10, si->cache_mem >> 10);
-               mutex_unlock(&si->stat_lock);
        }
+       mutex_unlock(&f2fs_stat_mutex);
        return 0;
 }
 
@@ -303,7 +300,7 @@ static const struct file_operations stat_fops = {
        .release = single_release,
 };
 
-static int init_stats(struct f2fs_sb_info *sbi)
+int f2fs_build_stats(struct f2fs_sb_info *sbi)
 {
        struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
        struct f2fs_stat_info *si;
@@ -313,9 +310,6 @@ static int init_stats(struct f2fs_sb_info *sbi)
                return -ENOMEM;
 
        si = sbi->stat_info;
-       mutex_init(&si->stat_lock);
-       list_add_tail(&si->stat_list, &f2fs_stat_list);
-
        si->all_area_segs = le32_to_cpu(raw_super->segment_count);
        si->sit_area_segs = le32_to_cpu(raw_super->segment_count_sit);
        si->nat_area_segs = le32_to_cpu(raw_super->segment_count_nat);
@@ -325,21 +319,11 @@ static int init_stats(struct f2fs_sb_info *sbi)
        si->main_area_zones = si->main_area_sections /
                                le32_to_cpu(raw_super->secs_per_zone);
        si->sbi = sbi;
-       return 0;
-}
 
-int f2fs_build_stats(struct f2fs_sb_info *sbi)
-{
-       int retval;
-
-       retval = init_stats(sbi);
-       if (retval)
-               return retval;
-
-       if (!debugfs_root)
-               debugfs_root = debugfs_create_dir("f2fs", NULL);
+       mutex_lock(&f2fs_stat_mutex);
+       list_add_tail(&si->stat_list, &f2fs_stat_list);
+       mutex_unlock(&f2fs_stat_mutex);
 
-       debugfs_create_file("status", S_IRUGO, debugfs_root, NULL, &stat_fops);
        return 0;
 }
 
@@ -347,14 +331,22 @@ void f2fs_destroy_stats(struct f2fs_sb_info *sbi)
 {
        struct f2fs_stat_info *si = sbi->stat_info;
 
+       mutex_lock(&f2fs_stat_mutex);
        list_del(&si->stat_list);
-       mutex_lock(&si->stat_lock);
-       si->sbi = NULL;
-       mutex_unlock(&si->stat_lock);
+       mutex_unlock(&f2fs_stat_mutex);
+
        kfree(sbi->stat_info);
 }
 
-void destroy_root_stats(void)
+void __init f2fs_create_root_stats(void)
+{
+       debugfs_root = debugfs_create_dir("f2fs", NULL);
+       if (debugfs_root)
+               debugfs_create_file("status", S_IRUGO, debugfs_root,
+                                        NULL, &stat_fops);
+}
+
+void f2fs_destroy_root_stats(void)
 {
        debugfs_remove_recursive(debugfs_root);
        debugfs_root = NULL;
index 951ed52..989980e 100644 (file)
@@ -503,7 +503,7 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page,
        }
 
        if (inode) {
-               inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+               inode->i_ctime = CURRENT_TIME;
                drop_nlink(inode);
                if (S_ISDIR(inode->i_mode)) {
                        drop_nlink(inode);
index 13c6dfb..c8e2d75 100644 (file)
@@ -211,11 +211,11 @@ struct dnode_of_data {
 static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode,
                struct page *ipage, struct page *npage, nid_t nid)
 {
+       memset(dn, 0, sizeof(*dn));
        dn->inode = inode;
        dn->inode_page = ipage;
        dn->node_page = npage;
        dn->nid = nid;
-       dn->inode_page_locked = 0;
 }
 
 /*
@@ -877,6 +877,8 @@ bool f2fs_empty_dir(struct inode *);
  * super.c
  */
 int f2fs_sync_fs(struct super_block *, int);
+extern __printf(3, 4)
+void f2fs_msg(struct super_block *, const char *, const char *, ...);
 
 /*
  * hash.c
@@ -912,7 +914,7 @@ int restore_node_summary(struct f2fs_sb_info *, unsigned int,
 void flush_nat_entries(struct f2fs_sb_info *);
 int build_node_manager(struct f2fs_sb_info *);
 void destroy_node_manager(struct f2fs_sb_info *);
-int create_node_manager_caches(void);
+int __init create_node_manager_caches(void);
 void destroy_node_manager_caches(void);
 
 /*
@@ -964,7 +966,7 @@ void sync_dirty_dir_inodes(struct f2fs_sb_info *);
 void block_operations(struct f2fs_sb_info *);
 void write_checkpoint(struct f2fs_sb_info *, bool, bool);
 void init_orphan_info(struct f2fs_sb_info *);
-int create_checkpoint_caches(void);
+int __init create_checkpoint_caches(void);
 void destroy_checkpoint_caches(void);
 
 /*
@@ -984,9 +986,9 @@ int do_write_data_page(struct page *);
 int start_gc_thread(struct f2fs_sb_info *);
 void stop_gc_thread(struct f2fs_sb_info *);
 block_t start_bidx_of_node(unsigned int);
-int f2fs_gc(struct f2fs_sb_info *, int);
+int f2fs_gc(struct f2fs_sb_info *);
 void build_gc_manager(struct f2fs_sb_info *);
-int create_gc_caches(void);
+int __init create_gc_caches(void);
 void destroy_gc_caches(void);
 
 /*
@@ -1058,7 +1060,8 @@ struct f2fs_stat_info {
 
 int f2fs_build_stats(struct f2fs_sb_info *);
 void f2fs_destroy_stats(struct f2fs_sb_info *);
-void destroy_root_stats(void);
+void __init f2fs_create_root_stats(void);
+void f2fs_destroy_root_stats(void);
 #else
 #define stat_inc_call_count(si)
 #define stat_inc_seg_count(si, type)
@@ -1068,7 +1071,8 @@ void destroy_root_stats(void);
 
 static inline int f2fs_build_stats(struct f2fs_sb_info *sbi) { return 0; }
 static inline void f2fs_destroy_stats(struct f2fs_sb_info *sbi) { }
-static inline void destroy_root_stats(void) { }
+static inline void __init f2fs_create_root_stats(void) { }
+static inline void f2fs_destroy_root_stats(void) { }
 #endif
 
 extern const struct file_operations f2fs_dir_operations;
index 7f9ea92..3191b52 100644 (file)
@@ -96,8 +96,9 @@ out:
 }
 
 static const struct vm_operations_struct f2fs_file_vm_ops = {
-       .fault        = filemap_fault,
-       .page_mkwrite = f2fs_vm_page_mkwrite,
+       .fault          = filemap_fault,
+       .page_mkwrite   = f2fs_vm_page_mkwrite,
+       .remap_pages    = generic_file_remap_pages,
 };
 
 static int need_to_sync_dir(struct f2fs_sb_info *sbi, struct inode *inode)
@@ -137,6 +138,9 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
        if (ret)
                return ret;
 
+       /* guarantee free sections for fsync */
+       f2fs_balance_fs(sbi);
+
        mutex_lock(&inode->i_mutex);
 
        if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
@@ -407,6 +411,8 @@ int truncate_hole(struct inode *inode, pgoff_t pg_start, pgoff_t pg_end)
                struct dnode_of_data dn;
                struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
 
+               f2fs_balance_fs(sbi);
+
                mutex_lock_op(sbi, DATA_TRUNC);
                set_new_dnode(&dn, inode, NULL, NULL, 0);
                err = get_dnode_of_data(&dn, index, RDONLY_NODE);
@@ -534,7 +540,6 @@ static long f2fs_fallocate(struct file *file, int mode,
                                loff_t offset, loff_t len)
 {
        struct inode *inode = file->f_path.dentry->d_inode;
-       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
        long ret;
 
        if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
@@ -545,7 +550,10 @@ static long f2fs_fallocate(struct file *file, int mode,
        else
                ret = expand_inode_data(inode, offset, len, mode);
 
-       f2fs_balance_fs(sbi);
+       if (!ret) {
+               inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+               mark_inode_dirty(inode);
+       }
        return ret;
 }
 
index b0ec721..c386910 100644 (file)
@@ -78,7 +78,7 @@ static int gc_thread_func(void *data)
 
                sbi->bg_gc++;
 
-               if (f2fs_gc(sbi, 1) == GC_NONE)
+               if (f2fs_gc(sbi) == GC_NONE)
                        wait_ms = GC_THREAD_NOGC_SLEEP_TIME;
                else if (wait_ms == GC_THREAD_NOGC_SLEEP_TIME)
                        wait_ms = GC_THREAD_MAX_SLEEP_TIME;
@@ -424,7 +424,11 @@ next_step:
 }
 
 /*
- * Calculate start block index that this node page contains
+ * Calculate start block index indicating the given node offset.
+ * Be careful, caller should give this node offset only indicating direct node
+ * blocks. If any node offsets, which point the other types of node blocks such
+ * as indirect or double indirect node blocks, are given, it must be a caller's
+ * bug.
  */
 block_t start_bidx_of_node(unsigned int node_ofs)
 {
@@ -651,62 +655,44 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi, unsigned int segno,
        return ret;
 }
 
-int f2fs_gc(struct f2fs_sb_info *sbi, int nGC)
+int f2fs_gc(struct f2fs_sb_info *sbi)
 {
-       unsigned int segno;
-       int old_free_secs, cur_free_secs;
-       int gc_status, nfree;
        struct list_head ilist;
+       unsigned int segno, i;
        int gc_type = BG_GC;
+       int gc_status = GC_NONE;
 
        INIT_LIST_HEAD(&ilist);
 gc_more:
-       nfree = 0;
-       gc_status = GC_NONE;
+       if (!(sbi->sb->s_flags & MS_ACTIVE))
+               goto stop;
 
        if (has_not_enough_free_secs(sbi))
-               old_free_secs = reserved_sections(sbi);
-       else
-               old_free_secs = free_sections(sbi);
-
-       while (sbi->sb->s_flags & MS_ACTIVE) {
-               int i;
-               if (has_not_enough_free_secs(sbi))
-                       gc_type = FG_GC;
+               gc_type = FG_GC;
 
-               cur_free_secs = free_sections(sbi) + nfree;
+       if (!__get_victim(sbi, &segno, gc_type, NO_CHECK_TYPE))
+               goto stop;
 
-               /* We got free space successfully. */
-               if (nGC < cur_free_secs - old_free_secs)
-                       break;
-
-               if (!__get_victim(sbi, &segno, gc_type, NO_CHECK_TYPE))
+       for (i = 0; i < sbi->segs_per_sec; i++) {
+               /*
+                * do_garbage_collect will give us three gc_status:
+                * GC_ERROR, GC_DONE, and GC_BLOCKED.
+                * If GC is finished uncleanly, we have to return
+                * the victim to dirty segment list.
+                */
+               gc_status = do_garbage_collect(sbi, segno + i, &ilist, gc_type);
+               if (gc_status != GC_DONE)
                        break;
-
-               for (i = 0; i < sbi->segs_per_sec; i++) {
-                       /*
-                        * do_garbage_collect will give us three gc_status:
-                        * GC_ERROR, GC_DONE, and GC_BLOCKED.
-                        * If GC is finished uncleanly, we have to return
-                        * the victim to dirty segment list.
-                        */
-                       gc_status = do_garbage_collect(sbi, segno + i,
-                                       &ilist, gc_type);
-                       if (gc_status != GC_DONE)
-                               goto stop;
-                       nfree++;
-               }
        }
-stop:
-       if (has_not_enough_free_secs(sbi) || gc_status == GC_BLOCKED) {
+       if (has_not_enough_free_secs(sbi)) {
                write_checkpoint(sbi, (gc_status == GC_BLOCKED), false);
-               if (nfree)
+               if (has_not_enough_free_secs(sbi))
                        goto gc_more;
        }
+stop:
        mutex_unlock(&sbi->gc_mutex);
 
        put_gc_inode(&ilist);
-       BUG_ON(!list_empty(&ilist));
        return gc_status;
 }
 
@@ -715,7 +701,7 @@ void build_gc_manager(struct f2fs_sb_info *sbi)
        DIRTY_I(sbi)->v_ops = &default_v_ops;
 }
 
-int create_gc_caches(void)
+int __init create_gc_caches(void)
 {
        winode_slab = f2fs_kmem_cache_create("f2fs_gc_inodes",
                        sizeof(struct inode_entry), NULL);
index bf20b4d..7942417 100644 (file)
@@ -217,6 +217,9 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc)
                        inode->i_ino == F2FS_META_INO(sbi))
                return 0;
 
+       if (wbc)
+               f2fs_balance_fs(sbi);
+
        node_page = get_node_page(sbi, inode->i_ino);
        if (IS_ERR(node_page))
                return PTR_ERR(node_page);
index 5066bfd..9bda63c 100644 (file)
@@ -1124,6 +1124,12 @@ static int f2fs_write_node_page(struct page *page,
        return 0;
 }
 
+/*
+ * It is very important to gather dirty pages and write at once, so that we can
+ * submit a big bio without interfering other data writes.
+ * Be default, 512 pages (2MB), a segment size, is quite reasonable.
+ */
+#define COLLECT_DIRTY_NODES    512
 static int f2fs_write_node_pages(struct address_space *mapping,
                            struct writeback_control *wbc)
 {
@@ -1131,17 +1137,16 @@ static int f2fs_write_node_pages(struct address_space *mapping,
        struct block_device *bdev = sbi->sb->s_bdev;
        long nr_to_write = wbc->nr_to_write;
 
-       if (wbc->for_kupdate)
-               return 0;
-
-       if (get_pages(sbi, F2FS_DIRTY_NODES) == 0)
-               return 0;
-
+       /* First check balancing cached NAT entries */
        if (try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK)) {
                write_checkpoint(sbi, false, false);
                return 0;
        }
 
+       /* collect a number of dirty node pages and write together */
+       if (get_pages(sbi, F2FS_DIRTY_NODES) < COLLECT_DIRTY_NODES)
+               return 0;
+
        /* if mounting is failed, skip writing node pages */
        wbc->nr_to_write = bio_get_nr_vecs(bdev);
        sync_node_pages(sbi, 0, wbc);
@@ -1732,7 +1737,7 @@ void destroy_node_manager(struct f2fs_sb_info *sbi)
        kfree(nm_i);
 }
 
-int create_node_manager_caches(void)
+int __init create_node_manager_caches(void)
 {
        nat_entry_slab = f2fs_kmem_cache_create("nat_entry",
                        sizeof(struct nat_entry), NULL);
index b571fee..f42e406 100644 (file)
@@ -67,7 +67,7 @@ static int recover_dentry(struct page *ipage, struct inode *inode)
                kunmap(page);
                f2fs_put_page(page, 0);
        } else {
-               f2fs_add_link(&dent, inode);
+               err = f2fs_add_link(&dent, inode);
        }
        iput(dir);
 out:
@@ -151,7 +151,6 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head)
                                goto out;
                        }
 
-                       INIT_LIST_HEAD(&entry->list);
                        list_add_tail(&entry->list, head);
                        entry->blkaddr = blkaddr;
                }
@@ -174,10 +173,9 @@ out:
 static void destroy_fsync_dnodes(struct f2fs_sb_info *sbi,
                                        struct list_head *head)
 {
-       struct list_head *this;
-       struct fsync_inode_entry *entry;
-       list_for_each(this, head) {
-               entry = list_entry(this, struct fsync_inode_entry, list);
+       struct fsync_inode_entry *entry, *tmp;
+
+       list_for_each_entry_safe(entry, tmp, head, list) {
                iput(entry->inode);
                list_del(&entry->list);
                kmem_cache_free(fsync_entry_slab, entry);
index de62409..4b00990 100644 (file)
@@ -31,7 +31,7 @@ void f2fs_balance_fs(struct f2fs_sb_info *sbi)
         */
        if (has_not_enough_free_secs(sbi)) {
                mutex_lock(&sbi->gc_mutex);
-               f2fs_gc(sbi, 1);
+               f2fs_gc(sbi);
        }
 }
 
index 08a94c8..37fad04 100644 (file)
@@ -53,6 +53,18 @@ static match_table_t f2fs_tokens = {
        {Opt_err, NULL},
 };
 
+void f2fs_msg(struct super_block *sb, const char *level, const char *fmt, ...)
+{
+       struct va_format vaf;
+       va_list args;
+
+       va_start(args, fmt);
+       vaf.fmt = fmt;
+       vaf.va = &args;
+       printk("%sF2FS-fs (%s): %pV\n", level, sb->s_id, &vaf);
+       va_end(args);
+}
+
 static void init_once(void *foo)
 {
        struct f2fs_inode_info *fi = (struct f2fs_inode_info *) foo;
@@ -125,6 +137,8 @@ int f2fs_sync_fs(struct super_block *sb, int sync)
 
        if (sync)
                write_checkpoint(sbi, false, false);
+       else
+               f2fs_balance_fs(sbi);
 
        return 0;
 }
@@ -247,7 +261,8 @@ static const struct export_operations f2fs_export_ops = {
        .get_parent = f2fs_get_parent,
 };
 
-static int parse_options(struct f2fs_sb_info *sbi, char *options)
+static int parse_options(struct super_block *sb, struct f2fs_sb_info *sbi,
+                               char *options)
 {
        substring_t args[MAX_OPT_ARGS];
        char *p;
@@ -286,7 +301,8 @@ static int parse_options(struct f2fs_sb_info *sbi, char *options)
                        break;
 #else
                case Opt_nouser_xattr:
-                       pr_info("nouser_xattr options not supported\n");
+                       f2fs_msg(sb, KERN_INFO,
+                               "nouser_xattr options not supported");
                        break;
 #endif
 #ifdef CONFIG_F2FS_FS_POSIX_ACL
@@ -295,7 +311,7 @@ static int parse_options(struct f2fs_sb_info *sbi, char *options)
                        break;
 #else
                case Opt_noacl:
-                       pr_info("noacl options not supported\n");
+                       f2fs_msg(sb, KERN_INFO, "noacl options not supported");
                        break;
 #endif
                case Opt_active_logs:
@@ -309,8 +325,9 @@ static int parse_options(struct f2fs_sb_info *sbi, char *options)
                        set_opt(sbi, DISABLE_EXT_IDENTIFY);
                        break;
                default:
-                       pr_err("Unrecognized mount option \"%s\" or missing value\n",
-                                       p);
+                       f2fs_msg(sb, KERN_ERR,
+                               "Unrecognized mount option \"%s\" or missing value",
+                               p);
                        return -EINVAL;
                }
        }
@@ -337,23 +354,36 @@ static loff_t max_file_size(unsigned bits)
        return result;
 }
 
-static int sanity_check_raw_super(struct f2fs_super_block *raw_super)
+static int sanity_check_raw_super(struct super_block *sb,
+                       struct f2fs_super_block *raw_super)
 {
        unsigned int blocksize;
 
-       if (F2FS_SUPER_MAGIC != le32_to_cpu(raw_super->magic))
+       if (F2FS_SUPER_MAGIC != le32_to_cpu(raw_super->magic)) {
+               f2fs_msg(sb, KERN_INFO,
+                       "Magic Mismatch, valid(0x%x) - read(0x%x)",
+                       F2FS_SUPER_MAGIC, le32_to_cpu(raw_super->magic));
                return 1;
+       }
 
        /* Currently, support only 4KB block size */
        blocksize = 1 << le32_to_cpu(raw_super->log_blocksize);
-       if (blocksize != PAGE_CACHE_SIZE)
+       if (blocksize != PAGE_CACHE_SIZE) {
+               f2fs_msg(sb, KERN_INFO,
+                       "Invalid blocksize (%u), supports only 4KB\n",
+                       blocksize);
                return 1;
+       }
        if (le32_to_cpu(raw_super->log_sectorsize) !=
-                                       F2FS_LOG_SECTOR_SIZE)
+                                       F2FS_LOG_SECTOR_SIZE) {
+               f2fs_msg(sb, KERN_INFO, "Invalid log sectorsize");
                return 1;
+       }
        if (le32_to_cpu(raw_super->log_sectors_per_block) !=
-                                       F2FS_LOG_SECTORS_PER_BLOCK)
+                                       F2FS_LOG_SECTORS_PER_BLOCK) {
+               f2fs_msg(sb, KERN_INFO, "Invalid log sectors per block");
                return 1;
+       }
        return 0;
 }
 
@@ -413,14 +443,17 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
        if (!sbi)
                return -ENOMEM;
 
-       /* set a temporary block size */
-       if (!sb_set_blocksize(sb, F2FS_BLKSIZE))
+       /* set a block size */
+       if (!sb_set_blocksize(sb, F2FS_BLKSIZE)) {
+               f2fs_msg(sb, KERN_ERR, "unable to set blocksize");
                goto free_sbi;
+       }
 
        /* read f2fs raw super block */
        raw_super_buf = sb_bread(sb, 0);
        if (!raw_super_buf) {
                err = -EIO;
+               f2fs_msg(sb, KERN_ERR, "unable to read superblock");
                goto free_sbi;
        }
        raw_super = (struct f2fs_super_block *)
@@ -438,12 +471,14 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
        set_opt(sbi, POSIX_ACL);
 #endif
        /* parse mount options */
-       if (parse_options(sbi, (char *)data))
+       if (parse_options(sb, sbi, (char *)data))
                goto free_sb_buf;
 
        /* sanity checking of raw super */
-       if (sanity_check_raw_super(raw_super))
+       if (sanity_check_raw_super(sb, raw_super)) {
+               f2fs_msg(sb, KERN_ERR, "Can't find a valid F2FS filesystem");
                goto free_sb_buf;
+       }
 
        sb->s_maxbytes = max_file_size(le32_to_cpu(raw_super->log_blocksize));
        sb->s_max_links = F2FS_LINK_MAX;
@@ -477,18 +512,23 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
        /* get an inode for meta space */
        sbi->meta_inode = f2fs_iget(sb, F2FS_META_INO(sbi));
        if (IS_ERR(sbi->meta_inode)) {
+               f2fs_msg(sb, KERN_ERR, "Failed to read F2FS meta data inode");
                err = PTR_ERR(sbi->meta_inode);
                goto free_sb_buf;
        }
 
        err = get_valid_checkpoint(sbi);
-       if (err)
+       if (err) {
+               f2fs_msg(sb, KERN_ERR, "Failed to get valid F2FS checkpoint");
                goto free_meta_inode;
+       }
 
        /* sanity checking of checkpoint */
        err = -EINVAL;
-       if (sanity_check_ckpt(raw_super, sbi->ckpt))
+       if (sanity_check_ckpt(raw_super, sbi->ckpt)) {
+               f2fs_msg(sb, KERN_ERR, "Invalid F2FS checkpoint");
                goto free_cp;
+       }
 
        sbi->total_valid_node_count =
                                le32_to_cpu(sbi->ckpt->valid_node_count);
@@ -502,25 +542,28 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
        INIT_LIST_HEAD(&sbi->dir_inode_list);
        spin_lock_init(&sbi->dir_inode_lock);
 
-       /* init super block */
-       if (!sb_set_blocksize(sb, sbi->blocksize))
-               goto free_cp;
-
        init_orphan_info(sbi);
 
        /* setup f2fs internal modules */
        err = build_segment_manager(sbi);
-       if (err)
+       if (err) {
+               f2fs_msg(sb, KERN_ERR,
+                       "Failed to initialize F2FS segment manager");
                goto free_sm;
+       }
        err = build_node_manager(sbi);
-       if (err)
+       if (err) {
+               f2fs_msg(sb, KERN_ERR,
+                       "Failed to initialize F2FS node manager");
                goto free_nm;
+       }
 
        build_gc_manager(sbi);
 
        /* get an inode for node space */
        sbi->node_inode = f2fs_iget(sb, F2FS_NODE_INO(sbi));
        if (IS_ERR(sbi->node_inode)) {
+               f2fs_msg(sb, KERN_ERR, "Failed to read node inode");
                err = PTR_ERR(sbi->node_inode);
                goto free_nm;
        }
@@ -533,6 +576,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
        /* read root inode and dentry */
        root = f2fs_iget(sb, F2FS_ROOT_INO(sbi));
        if (IS_ERR(root)) {
+               f2fs_msg(sb, KERN_ERR, "Failed to read root inode");
                err = PTR_ERR(root);
                goto free_node_inode;
        }
@@ -596,7 +640,7 @@ static struct file_system_type f2fs_fs_type = {
        .fs_flags       = FS_REQUIRES_DEV,
 };
 
-static int init_inodecache(void)
+static int __init init_inodecache(void)
 {
        f2fs_inode_cachep = f2fs_kmem_cache_create("f2fs_inode_cache",
                        sizeof(struct f2fs_inode_info), NULL);
@@ -631,14 +675,17 @@ static int __init init_f2fs_fs(void)
        err = create_checkpoint_caches();
        if (err)
                goto fail;
-       return register_filesystem(&f2fs_fs_type);
+       err = register_filesystem(&f2fs_fs_type);
+       if (err)
+               goto fail;
+       f2fs_create_root_stats();
 fail:
        return err;
 }
 
 static void __exit exit_f2fs_fs(void)
 {
-       destroy_root_stats();
+       f2fs_destroy_root_stats();
        unregister_filesystem(&f2fs_fs_type);
        destroy_checkpoint_caches();
        destroy_gc_caches();
index 940136a..8038c04 100644 (file)
@@ -318,6 +318,8 @@ int f2fs_setxattr(struct inode *inode, int name_index, const char *name,
        if (name_len > 255 || value_len > MAX_VALUE_LEN)
                return -ERANGE;
 
+       f2fs_balance_fs(sbi);
+
        mutex_lock_op(sbi, NODE_NEW);
        if (!fi->i_xattr_nid) {
                /* Allocate new attribute block */
index 0cf160a..1b2f6c2 100644 (file)
@@ -4,12 +4,24 @@ config FUSE_FS
          With FUSE it is possible to implement a fully functional filesystem
          in a userspace program.
 
-         There's also companion library: libfuse.  This library along with
-         utilities is available from the FUSE homepage:
+         There's also a companion library: libfuse2.  This library is available
+         from the FUSE homepage:
          <http://fuse.sourceforge.net/>
+         although chances are your distribution already has that library
+         installed if you've installed the "fuse" package itself.
 
          See <file:Documentation/filesystems/fuse.txt> for more information.
          See <file:Documentation/Changes> for needed library/utility version.
 
          If you want to develop a userspace FS, or if you want to use
          a filesystem based on FUSE, answer Y or M.
+
+config CUSE
+       tristate "Character device in Userspace support"
+       depends on FUSE_FS
+       help
+         This FUSE extension allows character devices to be
+         implemented in userspace.
+
+         If you want to develop or use a userspace character device
+         based on CUSE, answer Y or M.
index ee8d550..e397b67 100644 (file)
@@ -45,7 +45,6 @@
 #include <linux/miscdevice.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
-#include <linux/spinlock.h>
 #include <linux/stat.h>
 #include <linux/module.h>
 
@@ -63,7 +62,7 @@ struct cuse_conn {
        bool                    unrestricted_ioctl;
 };
 
-static DEFINE_SPINLOCK(cuse_lock);             /* protects cuse_conntbl */
+static DEFINE_MUTEX(cuse_lock);                /* protects registration */
 static struct list_head cuse_conntbl[CUSE_CONNTBL_LEN];
 static struct class *cuse_class;
 
@@ -114,14 +113,14 @@ static int cuse_open(struct inode *inode, struct file *file)
        int rc;
 
        /* look up and get the connection */
-       spin_lock(&cuse_lock);
+       mutex_lock(&cuse_lock);
        list_for_each_entry(pos, cuse_conntbl_head(devt), list)
                if (pos->dev->devt == devt) {
                        fuse_conn_get(&pos->fc);
                        cc = pos;
                        break;
                }
-       spin_unlock(&cuse_lock);
+       mutex_unlock(&cuse_lock);
 
        /* dead? */
        if (!cc)
@@ -267,7 +266,7 @@ static int cuse_parse_one(char **pp, char *end, char **keyp, char **valp)
 static int cuse_parse_devinfo(char *p, size_t len, struct cuse_devinfo *devinfo)
 {
        char *end = p + len;
-       char *key, *val;
+       char *uninitialized_var(key), *uninitialized_var(val);
        int rc;
 
        while (true) {
@@ -305,14 +304,14 @@ static void cuse_gendev_release(struct device *dev)
  */
 static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
 {
-       struct cuse_conn *cc = fc_to_cc(fc);
+       struct cuse_conn *cc = fc_to_cc(fc), *pos;
        struct cuse_init_out *arg = req->out.args[0].value;
        struct page *page = req->pages[0];
        struct cuse_devinfo devinfo = { };
        struct device *dev;
        struct cdev *cdev;
        dev_t devt;
-       int rc;
+       int rc, i;
 
        if (req->out.h.error ||
            arg->major != FUSE_KERNEL_VERSION || arg->minor < 11) {
@@ -356,15 +355,24 @@ static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
        dev_set_drvdata(dev, cc);
        dev_set_name(dev, "%s", devinfo.name);
 
+       mutex_lock(&cuse_lock);
+
+       /* make sure the device-name is unique */
+       for (i = 0; i < CUSE_CONNTBL_LEN; ++i) {
+               list_for_each_entry(pos, &cuse_conntbl[i], list)
+                       if (!strcmp(dev_name(pos->dev), dev_name(dev)))
+                               goto err_unlock;
+       }
+
        rc = device_add(dev);
        if (rc)
-               goto err_device;
+               goto err_unlock;
 
        /* register cdev */
        rc = -ENOMEM;
        cdev = cdev_alloc();
        if (!cdev)
-               goto err_device;
+               goto err_unlock;
 
        cdev->owner = THIS_MODULE;
        cdev->ops = &cuse_frontend_fops;
@@ -377,9 +385,8 @@ static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
        cc->cdev = cdev;
 
        /* make the device available */
-       spin_lock(&cuse_lock);
        list_add(&cc->list, cuse_conntbl_head(devt));
-       spin_unlock(&cuse_lock);
+       mutex_unlock(&cuse_lock);
 
        /* announce device availability */
        dev_set_uevent_suppress(dev, 0);
@@ -391,7 +398,8 @@ out:
 
 err_cdev:
        cdev_del(cdev);
-err_device:
+err_unlock:
+       mutex_unlock(&cuse_lock);
        put_device(dev);
 err_region:
        unregister_chrdev_region(devt, 1);
@@ -520,9 +528,9 @@ static int cuse_channel_release(struct inode *inode, struct file *file)
        int rc;
 
        /* remove from the conntbl, no more access from this point on */
-       spin_lock(&cuse_lock);
+       mutex_lock(&cuse_lock);
        list_del_init(&cc->list);
-       spin_unlock(&cuse_lock);
+       mutex_unlock(&cuse_lock);
 
        /* remove device */
        if (cc->dev)
index c163353..e83351a 100644 (file)
@@ -692,8 +692,6 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep)
        struct page *oldpage = *pagep;
        struct page *newpage;
        struct pipe_buffer *buf = cs->pipebufs;
-       struct address_space *mapping;
-       pgoff_t index;
 
        unlock_request(cs->fc, cs->req);
        fuse_copy_finish(cs);
@@ -724,9 +722,6 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep)
        if (fuse_check_page(newpage) != 0)
                goto out_fallback_unlock;
 
-       mapping = oldpage->mapping;
-       index = oldpage->index;
-
        /*
         * This is a new and locked page, it shouldn't be mapped or
         * have any special flags on it
index e21d4d8..f3ab824 100644 (file)
@@ -2177,8 +2177,8 @@ fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
        return ret;
 }
 
-long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
-                           loff_t length)
+static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
+                               loff_t length)
 {
        struct fuse_file *ff = file->private_data;
        struct fuse_conn *fc = ff->fc;
@@ -2213,7 +2213,6 @@ long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
 
        return err;
 }
-EXPORT_SYMBOL_GPL(fuse_file_fallocate);
 
 static const struct file_operations fuse_file_operations = {
        .llseek         = fuse_file_llseek,
index ccf7b4f..6c32af9 100644 (file)
@@ -16,6 +16,22 @@ extern void
 dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
                    dma_addr_t dma_handle);
 
+static inline void *dma_alloc_attrs(struct device *dev, size_t size,
+                                   dma_addr_t *dma_handle, gfp_t flag,
+                                   struct dma_attrs *attrs)
+{
+       /* attrs is not supported and ignored */
+       return dma_alloc_coherent(dev, size, dma_handle, flag);
+}
+
+static inline void dma_free_attrs(struct device *dev, size_t size,
+                                 void *cpu_addr, dma_addr_t dma_handle,
+                                 struct dma_attrs *attrs)
+{
+       /* attrs is not supported and ignored */
+       dma_free_coherent(dev, size, cpu_addr, dma_handle);
+}
+
 #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
 #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
 
index 701beab..5cf680a 100644 (file)
@@ -461,10 +461,8 @@ static inline int is_zero_pfn(unsigned long pfn)
        return offset_from_zero_pfn <= (zero_page_mask >> PAGE_SHIFT);
 }
 
-static inline unsigned long my_zero_pfn(unsigned long addr)
-{
-       return page_to_pfn(ZERO_PAGE(addr));
-}
+#define my_zero_pfn(addr)      page_to_pfn(ZERO_PAGE(addr))
+
 #else
 static inline int is_zero_pfn(unsigned long pfn)
 {
index 58f466f..1db51b8 100644 (file)
@@ -21,10 +21,12 @@ asmlinkage long sys_mmap(unsigned long addr, unsigned long len,
                        unsigned long fd, off_t pgoff);
 #endif
 
+#ifndef CONFIG_GENERIC_SIGALTSTACK
 #ifndef sys_sigaltstack
 asmlinkage long sys_sigaltstack(const stack_t __user *, stack_t __user *,
                        struct pt_regs *);
 #endif
+#endif
 
 #ifndef sys_rt_sigreturn
 asmlinkage long sys_rt_sigreturn(struct pt_regs *regs);
index 408da95..8f7a3d6 100644 (file)
@@ -297,10 +297,12 @@ enum {
        ATA_LOG_SATA_NCQ        = 0x10,
        ATA_LOG_SATA_ID_DEV_DATA  = 0x30,
        ATA_LOG_SATA_SETTINGS     = 0x08,
-       ATA_LOG_DEVSLP_MDAT       = 0x30,
+       ATA_LOG_DEVSLP_OFFSET     = 0x30,
+       ATA_LOG_DEVSLP_SIZE       = 0x08,
+       ATA_LOG_DEVSLP_MDAT       = 0x00,
        ATA_LOG_DEVSLP_MDAT_MASK  = 0x1F,
-       ATA_LOG_DEVSLP_DETO       = 0x31,
-       ATA_LOG_DEVSLP_VALID      = 0x37,
+       ATA_LOG_DEVSLP_DETO       = 0x01,
+       ATA_LOG_DEVSLP_VALID      = 0x07,
        ATA_LOG_DEVSLP_VALID_MASK = 0x80,
 
        /* READ/WRITE LONG (obsolete) */
index 83ba0ab..649e5f8 100644 (file)
@@ -652,8 +652,8 @@ struct ata_device {
                u32             gscr[SATA_PMP_GSCR_DWORDS]; /* PMP GSCR block */
        };
 
-       /* Identify Device Data Log (30h), SATA Settings (page 08h) */
-       u8                      sata_settings[ATA_SECT_SIZE];
+       /* DEVSLP Timing Variables from Identify Device Data Log */
+       u8                      devslp_timing[ATA_LOG_DEVSLP_SIZE];
 
        /* error history */
        int                     spdn_cnt;
index 7760c6d..1375ee3 100644 (file)
@@ -199,11 +199,11 @@ struct module_use {
        struct module *source, *target;
 };
 
-enum module_state
-{
-       MODULE_STATE_LIVE,
-       MODULE_STATE_COMING,
-       MODULE_STATE_GOING,
+enum module_state {
+       MODULE_STATE_LIVE,      /* Normal state. */
+       MODULE_STATE_COMING,    /* Full formed, running module_init. */
+       MODULE_STATE_GOING,     /* Going away. */
+       MODULE_STATE_UNFORMED,  /* Still setting it up. */
 };
 
 /**
index 1693775..89573a3 100644 (file)
@@ -45,7 +45,6 @@ extern long arch_ptrace(struct task_struct *child, long request,
 extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len);
 extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len);
 extern void ptrace_disable(struct task_struct *);
-extern int ptrace_check_attach(struct task_struct *task, bool ignore_state);
 extern int ptrace_request(struct task_struct *child, long request,
                          unsigned long addr, unsigned long data);
 extern void ptrace_notify(int exit_code);
index 6fc8f45..d211247 100644 (file)
@@ -2714,7 +2714,16 @@ static inline void thread_group_cputime_init(struct signal_struct *sig)
 extern void recalc_sigpending_and_wake(struct task_struct *t);
 extern void recalc_sigpending(void);
 
-extern void signal_wake_up(struct task_struct *t, int resume_stopped);
+extern void signal_wake_up_state(struct task_struct *t, unsigned int state);
+
+static inline void signal_wake_up(struct task_struct *t, bool resume)
+{
+       signal_wake_up_state(t, resume ? TASK_WAKEKILL : 0);
+}
+static inline void ptrace_signal_wake_up(struct task_struct *t, bool resume)
+{
+       signal_wake_up_state(t, resume ? __TASK_TRACED : 0);
+}
 
 /*
  * Wrappers for p->thread_info->cpu access. No-op on UP.
index 78f99d9..2c6c85f 100644 (file)
@@ -50,7 +50,8 @@
 #define PORT_LPC3220   22      /* NXP LPC32xx SoC "Standard" UART */
 #define PORT_8250_CIR  23      /* CIR infrared port, has its own driver */
 #define PORT_XR17V35X  24      /* Exar XR17V35x UARTs */
-#define PORT_MAX_8250  24      /* max port ID */
+#define PORT_BRCM_TRUMANAGE    24
+#define PORT_MAX_8250  25      /* max port ID */
 
 /*
  * ARM specific type numbers.  These are not currently guaranteed
index 5e4ded5..f9acf71 100644 (file)
@@ -36,6 +36,10 @@ __setup("noinitrd", no_initrd);
 static int init_linuxrc(struct subprocess_info *info, struct cred *new)
 {
        sys_unshare(CLONE_FS | CLONE_FILES);
+       /* stdin/stdout/stderr for /linuxrc */
+       sys_open("/dev/console", O_RDWR, 0);
+       sys_dup(0);
+       sys_dup(0);
        /* move initrd over / and chdir/chroot in initrd root */
        sys_chdir("/root");
        sys_mount(".", "/", NULL, MS_MOVE, NULL);
index 85d69df..92d728a 100644 (file)
@@ -802,7 +802,7 @@ static int run_init_process(const char *init_filename)
                (const char __user *const __user *)envp_init);
 }
 
-static void __init kernel_init_freeable(void);
+static noinline void __init kernel_init_freeable(void);
 
 static int __ref kernel_init(void *unused)
 {
@@ -845,7 +845,7 @@ static int __ref kernel_init(void *unused)
              "See Linux Documentation/init.txt for guidance.");
 }
 
-static void __init kernel_init_freeable(void)
+static noinline void __init kernel_init_freeable(void)
 {
        /*
         * Wait until kthreadd is all set-up.
index a1d585c..6f34904 100644 (file)
@@ -86,18 +86,27 @@ static atomic_t entry_count;
  */
 static async_cookie_t  __lowest_in_progress(struct async_domain *running)
 {
+       async_cookie_t first_running = next_cookie;     /* infinity value */
+       async_cookie_t first_pending = next_cookie;     /* ditto */
        struct async_entry *entry;
 
+       /*
+        * Both running and pending lists are sorted but not disjoint.
+        * Take the first cookies from both and return the min.
+        */
        if (!list_empty(&running->domain)) {
                entry = list_first_entry(&running->domain, typeof(*entry), list);
-               return entry->cookie;
+               first_running = entry->cookie;
        }
 
-       list_for_each_entry(entry, &async_pending, list)
-               if (entry->running == running)
-                       return entry->cookie;
+       list_for_each_entry(entry, &async_pending, list) {
+               if (entry->running == running) {
+                       first_pending = entry->cookie;
+                       break;
+               }
+       }
 
-       return next_cookie;     /* "infinity" value */
+       return min(first_running, first_pending);
 }
 
 static async_cookie_t  lowest_in_progress(struct async_domain *running)
@@ -118,13 +127,17 @@ static void async_run_entry_fn(struct work_struct *work)
 {
        struct async_entry *entry =
                container_of(work, struct async_entry, work);
+       struct async_entry *pos;
        unsigned long flags;
        ktime_t uninitialized_var(calltime), delta, rettime;
        struct async_domain *running = entry->running;
 
-       /* 1) move self to the running queue */
+       /* 1) move self to the running queue, make sure it stays sorted */
        spin_lock_irqsave(&async_lock, flags);
-       list_move_tail(&entry->list, &running->domain);
+       list_for_each_entry_reverse(pos, &running->domain, list)
+               if (entry->cookie < pos->cookie)
+                       break;
+       list_move_tail(&entry->list, &pos->list);
        spin_unlock_irqrestore(&async_lock, flags);
 
        /* 2) run (and print duration) */
index f6150e9..36700e9 100644 (file)
@@ -535,9 +535,11 @@ asmlinkage long compat_sys_getrusage(int who, struct compat_rusage __user *ru)
        return 0;
 }
 
-asmlinkage long
-compat_sys_wait4(compat_pid_t pid, compat_uint_t __user *stat_addr, int options,
-       struct compat_rusage __user *ru)
+COMPAT_SYSCALL_DEFINE4(wait4,
+       compat_pid_t, pid,
+       compat_uint_t __user *, stat_addr,
+       int, options,
+       struct compat_rusage __user *, ru)
 {
        if (!ru) {
                return sys_wait4(pid, stat_addr, options, NULL);
@@ -564,9 +566,10 @@ compat_sys_wait4(compat_pid_t pid, compat_uint_t __user *stat_addr, int options,
        }
 }
 
-asmlinkage long compat_sys_waitid(int which, compat_pid_t pid,
-               struct compat_siginfo __user *uinfo, int options,
-               struct compat_rusage __user *uru)
+COMPAT_SYSCALL_DEFINE5(waitid,
+               int, which, compat_pid_t, pid,
+               struct compat_siginfo __user *, uinfo, int, options,
+               struct compat_rusage __user *, uru)
 {
        siginfo_t info;
        struct rusage ru;
@@ -584,7 +587,11 @@ asmlinkage long compat_sys_waitid(int which, compat_pid_t pid,
                return ret;
 
        if (uru) {
-               ret = put_compat_rusage(&ru, uru);
+               /* sys_waitid() overwrites everything in ru */
+               if (COMPAT_USE_64BIT_TIME)
+                       ret = copy_to_user(uru, &ru, sizeof(ru));
+               else
+                       ret = put_compat_rusage(&ru, uru);
                if (ret)
                        return ret;
        }
@@ -994,7 +1001,7 @@ compat_sys_rt_sigtimedwait (compat_sigset_t __user *uthese,
        sigset_from_compat(&s, &s32);
 
        if (uts) {
-               if (get_compat_timespec(&t, uts))
+               if (compat_get_timespec(&t, uts))
                        return -EFAULT;
        }
 
index 4d5f8d5..8875254 100644 (file)
@@ -1970,6 +1970,8 @@ static int kdb_lsmod(int argc, const char **argv)
 
        kdb_printf("Module                  Size  modstruct     Used by\n");
        list_for_each_entry(mod, kdb_modules, list) {
+               if (mod->state == MODULE_STATE_UNFORMED)
+                       continue;
 
                kdb_printf("%-20s%8u  0x%p ", mod->name,
                           mod->core_size, (void *)mod);
index 65ca6d2..c535f33 100644 (file)
@@ -1668,8 +1668,10 @@ SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
                 int, tls_val)
 #endif
 {
-       return do_fork(clone_flags, newsp, 0,
-               parent_tidptr, child_tidptr);
+       long ret = do_fork(clone_flags, newsp, 0, parent_tidptr, child_tidptr);
+       asmlinkage_protect(5, ret, clone_flags, newsp,
+                       parent_tidptr, child_tidptr, tls_val);
+       return ret;
 }
 #endif
 
index b10b048..eab0827 100644 (file)
@@ -188,6 +188,7 @@ struct load_info {
    ongoing or failed initialization etc. */
 static inline int strong_try_module_get(struct module *mod)
 {
+       BUG_ON(mod && mod->state == MODULE_STATE_UNFORMED);
        if (mod && mod->state == MODULE_STATE_COMING)
                return -EBUSY;
        if (try_module_get(mod))
@@ -343,6 +344,9 @@ bool each_symbol_section(bool (*fn)(const struct symsearch *arr,
 #endif
                };
 
+               if (mod->state == MODULE_STATE_UNFORMED)
+                       continue;
+
                if (each_symbol_in_section(arr, ARRAY_SIZE(arr), mod, fn, data))
                        return true;
        }
@@ -450,16 +454,24 @@ const struct kernel_symbol *find_symbol(const char *name,
 EXPORT_SYMBOL_GPL(find_symbol);
 
 /* Search for module by name: must hold module_mutex. */
-struct module *find_module(const char *name)
+static struct module *find_module_all(const char *name,
+                                     bool even_unformed)
 {
        struct module *mod;
 
        list_for_each_entry(mod, &modules, list) {
+               if (!even_unformed && mod->state == MODULE_STATE_UNFORMED)
+                       continue;
                if (strcmp(mod->name, name) == 0)
                        return mod;
        }
        return NULL;
 }
+
+struct module *find_module(const char *name)
+{
+       return find_module_all(name, false);
+}
 EXPORT_SYMBOL_GPL(find_module);
 
 #ifdef CONFIG_SMP
@@ -525,6 +537,8 @@ bool is_module_percpu_address(unsigned long addr)
        preempt_disable();
 
        list_for_each_entry_rcu(mod, &modules, list) {
+               if (mod->state == MODULE_STATE_UNFORMED)
+                       continue;
                if (!mod->percpu_size)
                        continue;
                for_each_possible_cpu(cpu) {
@@ -1048,6 +1062,8 @@ static ssize_t show_initstate(struct module_attribute *mattr,
        case MODULE_STATE_GOING:
                state = "going";
                break;
+       default:
+               BUG();
        }
        return sprintf(buffer, "%s\n", state);
 }
@@ -1786,6 +1802,8 @@ void set_all_modules_text_rw(void)
 
        mutex_lock(&module_mutex);
        list_for_each_entry_rcu(mod, &modules, list) {
+               if (mod->state == MODULE_STATE_UNFORMED)
+                       continue;
                if ((mod->module_core) && (mod->core_text_size)) {
                        set_page_attributes(mod->module_core,
                                                mod->module_core + mod->core_text_size,
@@ -1807,6 +1825,8 @@ void set_all_modules_text_ro(void)
 
        mutex_lock(&module_mutex);
        list_for_each_entry_rcu(mod, &modules, list) {
+               if (mod->state == MODULE_STATE_UNFORMED)
+                       continue;
                if ((mod->module_core) && (mod->core_text_size)) {
                        set_page_attributes(mod->module_core,
                                                mod->module_core + mod->core_text_size,
@@ -2527,6 +2547,13 @@ static int copy_module_from_fd(int fd, struct load_info *info)
                err = -EFBIG;
                goto out;
        }
+
+       /* Don't hand 0 to vmalloc, it whines. */
+       if (stat.size == 0) {
+               err = -EINVAL;
+               goto out;
+       }
+
        info->hdr = vmalloc(stat.size);
        if (!info->hdr) {
                err = -ENOMEM;
@@ -2990,8 +3017,9 @@ static bool finished_loading(const char *name)
        bool ret;
 
        mutex_lock(&module_mutex);
-       mod = find_module(name);
-       ret = !mod || mod->state != MODULE_STATE_COMING;
+       mod = find_module_all(name, true);
+       ret = !mod || mod->state == MODULE_STATE_LIVE
+               || mod->state == MODULE_STATE_GOING;
        mutex_unlock(&module_mutex);
 
        return ret;
@@ -3136,6 +3164,32 @@ static int load_module(struct load_info *info, const char __user *uargs,
                goto free_copy;
        }
 
+       /*
+        * We try to place it in the list now to make sure it's unique
+        * before we dedicate too many resources.  In particular,
+        * temporary percpu memory exhaustion.
+        */
+       mod->state = MODULE_STATE_UNFORMED;
+again:
+       mutex_lock(&module_mutex);
+       if ((old = find_module_all(mod->name, true)) != NULL) {
+               if (old->state == MODULE_STATE_COMING
+                   || old->state == MODULE_STATE_UNFORMED) {
+                       /* Wait in case it fails to load. */
+                       mutex_unlock(&module_mutex);
+                       err = wait_event_interruptible(module_wq,
+                                              finished_loading(mod->name));
+                       if (err)
+                               goto free_module;
+                       goto again;
+               }
+               err = -EEXIST;
+               mutex_unlock(&module_mutex);
+               goto free_module;
+       }
+       list_add_rcu(&mod->list, &modules);
+       mutex_unlock(&module_mutex);
+
 #ifdef CONFIG_MODULE_SIG
        mod->sig_ok = info->sig_ok;
        if (!mod->sig_ok)
@@ -3145,7 +3199,7 @@ static int load_module(struct load_info *info, const char __user *uargs,
        /* Now module is in final location, initialize linked lists, etc. */
        err = module_unload_init(mod);
        if (err)
-               goto free_module;
+               goto unlink_mod;
 
        /* Now we've got everything in the final locations, we can
         * find optional sections. */
@@ -3180,54 +3234,33 @@ static int load_module(struct load_info *info, const char __user *uargs,
                goto free_arch_cleanup;
        }
 
-       /* Mark state as coming so strong_try_module_get() ignores us. */
-       mod->state = MODULE_STATE_COMING;
-
-       /* Now sew it into the lists so we can get lockdep and oops
-        * info during argument parsing.  No one should access us, since
-        * strong_try_module_get() will fail.
-        * lockdep/oops can run asynchronous, so use the RCU list insertion
-        * function to insert in a way safe to concurrent readers.
-        * The mutex protects against concurrent writers.
-        */
-again:
-       mutex_lock(&module_mutex);
-       if ((old = find_module(mod->name)) != NULL) {
-               if (old->state == MODULE_STATE_COMING) {
-                       /* Wait in case it fails to load. */
-                       mutex_unlock(&module_mutex);
-                       err = wait_event_interruptible(module_wq,
-                                              finished_loading(mod->name));
-                       if (err)
-                               goto free_arch_cleanup;
-                       goto again;
-               }
-               err = -EEXIST;
-               goto unlock;
-       }
-
-       /* This has to be done once we're sure module name is unique. */
        dynamic_debug_setup(info->debug, info->num_debug);
 
-       /* Find duplicate symbols */
+       mutex_lock(&module_mutex);
+       /* Find duplicate symbols (must be called under lock). */
        err = verify_export_symbols(mod);
        if (err < 0)
-               goto ddebug;
+               goto ddebug_cleanup;
 
+       /* This relies on module_mutex for list integrity. */
        module_bug_finalize(info->hdr, info->sechdrs, mod);
-       list_add_rcu(&mod->list, &modules);
+
+       /* Mark state as coming so strong_try_module_get() ignores us,
+        * but kallsyms etc. can see us. */
+       mod->state = MODULE_STATE_COMING;
+
        mutex_unlock(&module_mutex);
 
        /* Module is ready to execute: parsing args may do that. */
        err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp,
                         -32768, 32767, &ddebug_dyndbg_module_param_cb);
        if (err < 0)
-               goto unlink;
+               goto bug_cleanup;
 
        /* Link in to syfs. */
        err = mod_sysfs_setup(mod, info, mod->kp, mod->num_kp);
        if (err < 0)
-               goto unlink;
+               goto bug_cleanup;
 
        /* Get rid of temporary copy. */
        free_copy(info);
@@ -3237,16 +3270,13 @@ again:
 
        return do_init_module(mod);
 
- unlink:
+ bug_cleanup:
+       /* module_bug_cleanup needs module_mutex protection */
        mutex_lock(&module_mutex);
-       /* Unlink carefully: kallsyms could be walking list. */
-       list_del_rcu(&mod->list);
        module_bug_cleanup(mod);
-       wake_up_all(&module_wq);
- ddebug:
-       dynamic_debug_remove(info->debug);
- unlock:
+ ddebug_cleanup:
        mutex_unlock(&module_mutex);
+       dynamic_debug_remove(info->debug);
        synchronize_sched();
        kfree(mod->args);
  free_arch_cleanup:
@@ -3255,6 +3285,12 @@ again:
        free_modinfo(mod);
  free_unload:
        module_unload_free(mod);
+ unlink_mod:
+       mutex_lock(&module_mutex);
+       /* Unlink carefully: kallsyms could be walking list. */
+       list_del_rcu(&mod->list);
+       wake_up_all(&module_wq);
+       mutex_unlock(&module_mutex);
  free_module:
        module_deallocate(mod, info);
  free_copy:
@@ -3377,6 +3413,8 @@ const char *module_address_lookup(unsigned long addr,
 
        preempt_disable();
        list_for_each_entry_rcu(mod, &modules, list) {
+               if (mod->state == MODULE_STATE_UNFORMED)
+                       continue;
                if (within_module_init(addr, mod) ||
                    within_module_core(addr, mod)) {
                        if (modname)
@@ -3400,6 +3438,8 @@ int lookup_module_symbol_name(unsigned long addr, char *symname)
 
        preempt_disable();
        list_for_each_entry_rcu(mod, &modules, list) {
+               if (mod->state == MODULE_STATE_UNFORMED)
+                       continue;
                if (within_module_init(addr, mod) ||
                    within_module_core(addr, mod)) {
                        const char *sym;
@@ -3424,6 +3464,8 @@ int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size,
 
        preempt_disable();
        list_for_each_entry_rcu(mod, &modules, list) {
+               if (mod->state == MODULE_STATE_UNFORMED)
+                       continue;
                if (within_module_init(addr, mod) ||
                    within_module_core(addr, mod)) {
                        const char *sym;
@@ -3451,6 +3493,8 @@ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
 
        preempt_disable();
        list_for_each_entry_rcu(mod, &modules, list) {
+               if (mod->state == MODULE_STATE_UNFORMED)
+                       continue;
                if (symnum < mod->num_symtab) {
                        *value = mod->symtab[symnum].st_value;
                        *type = mod->symtab[symnum].st_info;
@@ -3493,9 +3537,12 @@ unsigned long module_kallsyms_lookup_name(const char *name)
                        ret = mod_find_symname(mod, colon+1);
                *colon = ':';
        } else {
-               list_for_each_entry_rcu(mod, &modules, list)
+               list_for_each_entry_rcu(mod, &modules, list) {
+                       if (mod->state == MODULE_STATE_UNFORMED)
+                               continue;
                        if ((ret = mod_find_symname(mod, name)) != 0)
                                break;
+               }
        }
        preempt_enable();
        return ret;
@@ -3510,6 +3557,8 @@ int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,
        int ret;
 
        list_for_each_entry(mod, &modules, list) {
+               if (mod->state == MODULE_STATE_UNFORMED)
+                       continue;
                for (i = 0; i < mod->num_symtab; i++) {
                        ret = fn(data, mod->strtab + mod->symtab[i].st_name,
                                 mod, mod->symtab[i].st_value);
@@ -3525,6 +3574,7 @@ static char *module_flags(struct module *mod, char *buf)
 {
        int bx = 0;
 
+       BUG_ON(mod->state == MODULE_STATE_UNFORMED);
        if (mod->taints ||
            mod->state == MODULE_STATE_GOING ||
            mod->state == MODULE_STATE_COMING) {
@@ -3566,6 +3616,10 @@ static int m_show(struct seq_file *m, void *p)
        struct module *mod = list_entry(p, struct module, list);
        char buf[8];
 
+       /* We always ignore unformed modules. */
+       if (mod->state == MODULE_STATE_UNFORMED)
+               return 0;
+
        seq_printf(m, "%s %u",
                   mod->name, mod->init_size + mod->core_size);
        print_unload_info(m, mod);
@@ -3626,6 +3680,8 @@ const struct exception_table_entry *search_module_extables(unsigned long addr)
 
        preempt_disable();
        list_for_each_entry_rcu(mod, &modules, list) {
+               if (mod->state == MODULE_STATE_UNFORMED)
+                       continue;
                if (mod->num_exentries == 0)
                        continue;
 
@@ -3674,10 +3730,13 @@ struct module *__module_address(unsigned long addr)
        if (addr < module_addr_min || addr > module_addr_max)
                return NULL;
 
-       list_for_each_entry_rcu(mod, &modules, list)
+       list_for_each_entry_rcu(mod, &modules, list) {
+               if (mod->state == MODULE_STATE_UNFORMED)
+                       continue;
                if (within_module_core(addr, mod)
                    || within_module_init(addr, mod))
                        return mod;
+       }
        return NULL;
 }
 EXPORT_SYMBOL_GPL(__module_address);
@@ -3730,8 +3789,11 @@ void print_modules(void)
        printk(KERN_DEFAULT "Modules linked in:");
        /* Most callers should already have preempt disabled, but make sure */
        preempt_disable();
-       list_for_each_entry_rcu(mod, &modules, list)
+       list_for_each_entry_rcu(mod, &modules, list) {
+               if (mod->state == MODULE_STATE_UNFORMED)
+                       continue;
                printk(" %s%s", mod->name, module_flags(mod, buf));
+       }
        preempt_enable();
        if (last_unloaded_module[0])
                printk(" [last unloaded: %s]", last_unloaded_module);
index 1599157..6cbeaae 100644 (file)
@@ -117,11 +117,45 @@ void __ptrace_unlink(struct task_struct *child)
         * TASK_KILLABLE sleeps.
         */
        if (child->jobctl & JOBCTL_STOP_PENDING || task_is_traced(child))
-               signal_wake_up(child, task_is_traced(child));
+               ptrace_signal_wake_up(child, true);
 
        spin_unlock(&child->sighand->siglock);
 }
 
+/* Ensure that nothing can wake it up, even SIGKILL */
+static bool ptrace_freeze_traced(struct task_struct *task)
+{
+       bool ret = false;
+
+       /* Lockless, nobody but us can set this flag */
+       if (task->jobctl & JOBCTL_LISTENING)
+               return ret;
+
+       spin_lock_irq(&task->sighand->siglock);
+       if (task_is_traced(task) && !__fatal_signal_pending(task)) {
+               task->state = __TASK_TRACED;
+               ret = true;
+       }
+       spin_unlock_irq(&task->sighand->siglock);
+
+       return ret;
+}
+
+static void ptrace_unfreeze_traced(struct task_struct *task)
+{
+       if (task->state != __TASK_TRACED)
+               return;
+
+       WARN_ON(!task->ptrace || task->parent != current);
+
+       spin_lock_irq(&task->sighand->siglock);
+       if (__fatal_signal_pending(task))
+               wake_up_state(task, __TASK_TRACED);
+       else
+               task->state = TASK_TRACED;
+       spin_unlock_irq(&task->sighand->siglock);
+}
+
 /**
  * ptrace_check_attach - check whether ptracee is ready for ptrace operation
  * @child: ptracee to check for
@@ -139,7 +173,7 @@ void __ptrace_unlink(struct task_struct *child)
  * RETURNS:
  * 0 on success, -ESRCH if %child is not ready.
  */
-int ptrace_check_attach(struct task_struct *child, bool ignore_state)
+static int ptrace_check_attach(struct task_struct *child, bool ignore_state)
 {
        int ret = -ESRCH;
 
@@ -151,24 +185,29 @@ int ptrace_check_attach(struct task_struct *child, bool ignore_state)
         * be changed by us so it's not changing right after this.
         */
        read_lock(&tasklist_lock);
-       if ((child->ptrace & PT_PTRACED) && child->parent == current) {
+       if (child->ptrace && child->parent == current) {
+               WARN_ON(child->state == __TASK_TRACED);
                /*
                 * child->sighand can't be NULL, release_task()
                 * does ptrace_unlink() before __exit_signal().
                 */
-               spin_lock_irq(&child->sighand->siglock);
-               WARN_ON_ONCE(task_is_stopped(child));
-               if (ignore_state || (task_is_traced(child) &&
-                                    !(child->jobctl & JOBCTL_LISTENING)))
+               if (ignore_state || ptrace_freeze_traced(child))
                        ret = 0;
-               spin_unlock_irq(&child->sighand->siglock);
        }
        read_unlock(&tasklist_lock);
 
-       if (!ret && !ignore_state)
-               ret = wait_task_inactive(child, TASK_TRACED) ? 0 : -ESRCH;
+       if (!ret && !ignore_state) {
+               if (!wait_task_inactive(child, __TASK_TRACED)) {
+                       /*
+                        * This can only happen if may_ptrace_stop() fails and
+                        * ptrace_stop() changes ->state back to TASK_RUNNING,
+                        * so we should not worry about leaking __TASK_TRACED.
+                        */
+                       WARN_ON(child->state == __TASK_TRACED);
+                       ret = -ESRCH;
+               }
+       }
 
-       /* All systems go.. */
        return ret;
 }
 
@@ -317,7 +356,7 @@ static int ptrace_attach(struct task_struct *task, long request,
         */
        if (task_is_stopped(task) &&
            task_set_jobctl_pending(task, JOBCTL_TRAP_STOP | JOBCTL_TRAPPING))
-               signal_wake_up(task, 1);
+               signal_wake_up_state(task, __TASK_STOPPED);
 
        spin_unlock(&task->sighand->siglock);
 
@@ -737,7 +776,7 @@ int ptrace_request(struct task_struct *child, long request,
                 * tracee into STOP.
                 */
                if (likely(task_set_jobctl_pending(child, JOBCTL_TRAP_STOP)))
-                       signal_wake_up(child, child->jobctl & JOBCTL_LISTENING);
+                       ptrace_signal_wake_up(child, child->jobctl & JOBCTL_LISTENING);
 
                unlock_task_sighand(child, &flags);
                ret = 0;
@@ -763,7 +802,7 @@ int ptrace_request(struct task_struct *child, long request,
                         * start of this trap and now.  Trigger re-trap.
                         */
                        if (child->jobctl & JOBCTL_TRAP_NOTIFY)
-                               signal_wake_up(child, true);
+                               ptrace_signal_wake_up(child, true);
                        ret = 0;
                }
                unlock_task_sighand(child, &flags);
@@ -900,6 +939,8 @@ SYSCALL_DEFINE4(ptrace, long, request, long, pid, unsigned long, addr,
                goto out_put_task_struct;
 
        ret = arch_ptrace(child, request, addr, data);
+       if (ret || request != PTRACE_DETACH)
+               ptrace_unfreeze_traced(child);
 
  out_put_task_struct:
        put_task_struct(child);
@@ -1039,8 +1080,11 @@ asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid,
 
        ret = ptrace_check_attach(child, request == PTRACE_KILL ||
                                  request == PTRACE_INTERRUPT);
-       if (!ret)
+       if (!ret) {
                ret = compat_arch_ptrace(child, request, addr, data);
+               if (ret || request != PTRACE_DETACH)
+                       ptrace_unfreeze_traced(child);
+       }
 
  out_put_task_struct:
        put_task_struct(child);
index 257002c..26058d0 100644 (file)
@@ -1523,7 +1523,8 @@ out:
  */
 int wake_up_process(struct task_struct *p)
 {
-       return try_to_wake_up(p, TASK_ALL, 0);
+       WARN_ON(task_is_stopped_or_traced(p));
+       return try_to_wake_up(p, TASK_NORMAL, 0);
 }
 EXPORT_SYMBOL(wake_up_process);
 
index 372771e..3d09cf6 100644 (file)
@@ -680,23 +680,17 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
  * No need to set need_resched since signal event passing
  * goes through ->blocked
  */
-void signal_wake_up(struct task_struct *t, int resume)
+void signal_wake_up_state(struct task_struct *t, unsigned int state)
 {
-       unsigned int mask;
-
        set_tsk_thread_flag(t, TIF_SIGPENDING);
-
        /*
-        * For SIGKILL, we want to wake it up in the stopped/traced/killable
+        * TASK_WAKEKILL also means wake it up in the stopped/traced/killable
         * case. We don't check t->state here because there is a race with it
         * executing another processor and just now entering stopped state.
         * By using wake_up_state, we ensure the process will wake up and
         * handle its death signal.
         */
-       mask = TASK_INTERRUPTIBLE;
-       if (resume)
-               mask |= TASK_WAKEKILL;
-       if (!wake_up_state(t, mask))
+       if (!wake_up_state(t, state | TASK_INTERRUPTIBLE))
                kick_process(t);
 }
 
@@ -844,7 +838,7 @@ static void ptrace_trap_notify(struct task_struct *t)
        assert_spin_locked(&t->sighand->siglock);
 
        task_set_jobctl_pending(t, JOBCTL_TRAP_NOTIFY);
-       signal_wake_up(t, t->jobctl & JOBCTL_LISTENING);
+       ptrace_signal_wake_up(t, t->jobctl & JOBCTL_LISTENING);
 }
 
 /*
@@ -1800,6 +1794,10 @@ static inline int may_ptrace_stop(void)
         * If SIGKILL was already sent before the caller unlocked
         * ->siglock we must see ->core_state != NULL. Otherwise it
         * is safe to enter schedule().
+        *
+        * This is almost outdated, a task with the pending SIGKILL can't
+        * block in TASK_TRACED. But PTRACE_EVENT_EXIT can be reported
+        * after SIGKILL was already dequeued.
         */
        if (unlikely(current->mm->core_state) &&
            unlikely(current->mm == current->parent->mm))
@@ -1925,6 +1923,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info)
                if (gstop_done)
                        do_notify_parent_cldstop(current, false, why);
 
+               /* tasklist protects us from ptrace_freeze_traced() */
                __set_current_state(TASK_RUNNING);
                if (clear_code)
                        current->exit_code = 0;
@@ -3116,8 +3115,9 @@ int __save_altstack(stack_t __user *uss, unsigned long sp)
 
 #ifdef CONFIG_COMPAT
 #ifdef CONFIG_GENERIC_SIGALTSTACK
-asmlinkage long compat_sys_sigaltstack(const compat_stack_t __user *uss_ptr,
-                                      compat_stack_t __user *uoss_ptr)
+COMPAT_SYSCALL_DEFINE2(sigaltstack,
+                       const compat_stack_t __user *, uss_ptr,
+                       compat_stack_t __user *, uoss_ptr)
 {
        stack_t uss, uoss;
        int ret;
index 3ffe4c5..41473b4 100644 (file)
@@ -3998,7 +3998,7 @@ static int ftrace_module_notify(struct notifier_block *self,
 
 struct notifier_block ftrace_module_nb = {
        .notifier_call = ftrace_module_notify,
-       .priority = 0,
+       .priority = INT_MAX,    /* Run before anything that can use kprobes */
 };
 
 extern unsigned long __start_mcount_loc[];
index a28c141..d0cdf14 100644 (file)
--- a/lib/bug.c
+++ b/lib/bug.c
@@ -55,6 +55,7 @@ static inline unsigned long bug_addr(const struct bug_entry *bug)
 }
 
 #ifdef CONFIG_MODULES
+/* Updates are protected by module mutex */
 static LIST_HEAD(module_bug_list);
 
 static const struct bug_entry *module_find_bug(unsigned long bugaddr)
index 19ecc8d..d794abc 100644 (file)
@@ -215,7 +215,9 @@ static void devcgroup_css_free(struct cgroup *cgroup)
        struct dev_cgroup *dev_cgroup;
 
        dev_cgroup = cgroup_to_devcgroup(cgroup);
+       mutex_lock(&devcgroup_mutex);
        dev_exception_clean(dev_cgroup);
+       mutex_unlock(&devcgroup_mutex);
        kfree(dev_cgroup);
 }
 
index dfb2691..7dd538e 100644 (file)
@@ -205,9 +205,9 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name,
                rc = __vfs_setxattr_noperm(dentry, XATTR_NAME_EVM,
                                           &xattr_data,
                                           sizeof(xattr_data), 0);
-       }
-       else if (rc == -ENODATA)
+       } else if (rc == -ENODATA && inode->i_op->removexattr) {
                rc = inode->i_op->removexattr(dentry, XATTR_NAME_EVM);
+       }
        return rc;
 }
 
index b8fb0a5..822df97 100644 (file)
@@ -3654,6 +3654,7 @@ static void hda_call_codec_resume(struct hda_codec *codec)
        hda_set_power_state(codec, AC_PWRST_D0);
        restore_shutup_pins(codec);
        hda_exec_init_verbs(codec);
+       snd_hda_jack_set_dirty_all(codec);
        if (codec->patch_ops.resume)
                codec->patch_ops.resume(codec);
        else {
@@ -3665,10 +3666,8 @@ static void hda_call_codec_resume(struct hda_codec *codec)
 
        if (codec->jackpoll_interval)
                hda_jackpoll_work(&codec->jackpoll_work.work);
-       else {
-               snd_hda_jack_set_dirty_all(codec);
+       else
                snd_hda_jack_report_sync(codec);
-       }
 
        codec->in_pm = 0;
        snd_hda_power_down(codec); /* flag down before returning */
index dd798c3..009b77a 100644 (file)
@@ -4636,6 +4636,12 @@ static const struct hda_codec_preset snd_hda_preset_conexant[] = {
          .patch = patch_conexant_auto },
        { .id = 0x14f15111, .name = "CX20753/4",
          .patch = patch_conexant_auto },
+       { .id = 0x14f15113, .name = "CX20755",
+         .patch = patch_conexant_auto },
+       { .id = 0x14f15114, .name = "CX20756",
+         .patch = patch_conexant_auto },
+       { .id = 0x14f15115, .name = "CX20757",
+         .patch = patch_conexant_auto },
        {} /* terminator */
 };
 
@@ -4659,6 +4665,9 @@ MODULE_ALIAS("snd-hda-codec-id:14f150b9");
 MODULE_ALIAS("snd-hda-codec-id:14f1510f");
 MODULE_ALIAS("snd-hda-codec-id:14f15110");
 MODULE_ALIAS("snd-hda-codec-id:14f15111");
+MODULE_ALIAS("snd-hda-codec-id:14f15113");
+MODULE_ALIAS("snd-hda-codec-id:14f15114");
+MODULE_ALIAS("snd-hda-codec-id:14f15115");
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Conexant HD-audio codec");
index f519627..cf38861 100644 (file)
@@ -6251,6 +6251,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0x0349, "Acer AOD260", ALC269_FIXUP_INV_DMIC),
        SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_MIC2_MUTE_LED),
        SND_PCI_QUIRK(0x103c, 0x1972, "HP Pavilion 17", ALC269_FIXUP_MIC1_MUTE_LED),
+       SND_PCI_QUIRK(0x103c, 0x1977, "HP Pavilion 14", ALC269_FIXUP_MIC1_MUTE_LED),
        SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_DMIC),
        SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_DMIC),
        SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
@@ -6265,6 +6266,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
        SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
        SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
+       SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK),
        SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK),
        SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
        SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK),
index 80db3f4..39d4106 100644 (file)
@@ -11,11 +11,21 @@ lib/rbtree.c
 include/linux/swab.h
 arch/*/include/asm/unistd*.h
 arch/*/include/asm/perf_regs.h
+arch/*/include/uapi/asm/unistd*.h
+arch/*/include/uapi/asm/perf_regs.h
 arch/*/lib/memcpy*.S
 arch/*/lib/memset*.S
 include/linux/poison.h
 include/linux/magic.h
 include/linux/hw_breakpoint.h
+include/linux/rbtree_augmented.h
+include/uapi/linux/perf_event.h
+include/uapi/linux/const.h
+include/uapi/linux/swab.h
+include/uapi/linux/hw_breakpoint.h
 arch/x86/include/asm/svm.h
 arch/x86/include/asm/vmx.h
 arch/x86/include/asm/kvm_host.h
+arch/x86/include/uapi/asm/svm.h
+arch/x86/include/uapi/asm/vmx.h
+arch/x86/include/uapi/asm/kvm.h
index 891bc77..8ab05e5 100644 (file)
@@ -58,7 +58,7 @@ ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
                                  -e s/arm.*/arm/ -e s/sa110/arm/ \
                                  -e s/s390x/s390/ -e s/parisc64/parisc/ \
                                  -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
-                                 -e s/sh[234].*/sh/ )
+                                 -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ )
 NO_PERF_REGS := 1
 
 CC = $(CROSS_COMPILE)gcc