Merge branch 'pm-cpufreq'
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Mon, 26 Aug 2013 23:44:40 +0000 (01:44 +0200)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Mon, 26 Aug 2013 23:44:40 +0000 (01:44 +0200)
* pm-cpufreq: (60 commits)
  cpufreq: pmac32-cpufreq: remove device tree parsing for cpu nodes
  cpufreq: pmac64-cpufreq: remove device tree parsing for cpu nodes
  cpufreq: maple-cpufreq: remove device tree parsing for cpu nodes
  cpufreq: arm_big_little: remove device tree parsing for cpu nodes
  cpufreq: kirkwood-cpufreq: remove device tree parsing for cpu nodes
  cpufreq: spear-cpufreq: remove device tree parsing for cpu nodes
  cpufreq: highbank-cpufreq: remove device tree parsing for cpu nodes
  cpufreq: cpufreq-cpu0: remove device tree parsing for cpu nodes
  cpufreq: imx6q-cpufreq: remove device tree parsing for cpu nodes
  drivers/bus: arm-cci: avoid parsing DT for cpu device nodes
  ARM: mvebu: remove device tree parsing for cpu nodes
  ARM: topology: remove hwid/MPIDR dependency from cpu_capacity
  of/device: add helper to get cpu device node from logical cpu index
  driver/core: cpu: initialize of_node in cpu's device struture
  ARM: DT/kernel: define ARM specific arch_match_cpu_phys_id
  of: move of_get_cpu_node implementation to DT core library
  powerpc: refactor of_get_cpu_node to support other architectures
  openrisc: remove undefined of_get_cpu_node declaration
  microblaze: remove undefined of_get_cpu_node declaration
  cpufreq: fix bad unlock balance on !CONFIG_SMP
  ...

255 files changed:
Documentation/kernel-parameters.txt
Documentation/laptops/asus-laptop.txt
Documentation/laptops/sony-laptop.txt
Documentation/laptops/thinkpad-acpi.txt
MAINTAINERS
Makefile
arch/arc/lib/strchr-700.S
arch/arm/boot/dts/at91sam9n12ek.dts
arch/arm/boot/dts/at91sam9x5ek.dtsi
arch/arm/boot/dts/tegra20-seaboard.dts
arch/arm/boot/dts/tegra20-trimslice.dts
arch/arm/boot/dts/tegra20-whistler.dts
arch/arm/kernel/fiq.c
arch/arm/kernel/machine_kexec.c
arch/arm/kvm/coproc.c
arch/arm/kvm/coproc.h
arch/arm/kvm/coproc_a15.c
arch/arm/kvm/mmio.c
arch/arm/kvm/mmu.c
arch/arm/mach-at91/at91sam9x5.c
arch/arm/mach-davinci/board-dm355-leopard.c
arch/arm/mach-davinci/board-dm644x-evm.c
arch/arm/mach-davinci/board-dm646x-evm.c
arch/arm/mach-davinci/board-neuros-osd2.c
arch/arm/mach-davinci/cpuidle.c
arch/arm/mach-omap2/board-n8x0.c
arch/arm/mach-omap2/board-rx51.c
arch/arm/mach-omap2/usb-musb.c
arch/arm/mach-ux500/Makefile
arch/arm/mach-ux500/cpuidle.c [deleted file]
arch/arm/mm/Kconfig
arch/arm/plat-samsung/init.c
arch/arm/xen/enlighten.c
arch/arm64/include/asm/kvm_asm.h
arch/arm64/include/asm/kvm_host.h
arch/arm64/kernel/perf_event.c
arch/arm64/kvm/hyp.S
arch/arm64/kvm/sys_regs.c
arch/mips/math-emu/cp1emu.c
arch/sh/kernel/cpu/shmobile/cpuidle.c
arch/x86/include/asm/bootparam_utils.h
arch/x86/include/asm/microcode_amd.h
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/microcode_amd.c
arch/x86/kernel/microcode_amd_early.c
arch/x86/kernel/sys_x86_64.c
arch/x86/kernel/tboot.c
arch/x86/mm/mmap.c
arch/x86/mm/srat.c
arch/x86/pci/i386.c
arch/x86/xen/setup.c
arch/x86/xen/smp.c
drivers/acpi/Kconfig
drivers/acpi/ac.c
drivers/acpi/acpi_pad.c
drivers/acpi/acpi_platform.c
drivers/acpi/acpi_processor.c
drivers/acpi/acpica/acglobal.h
drivers/acpi/acpica/aclocal.h
drivers/acpi/acpica/acnamesp.h
drivers/acpi/acpica/actables.h
drivers/acpi/acpica/acutils.h
drivers/acpi/acpica/evgpeinit.c
drivers/acpi/acpica/exdump.c
drivers/acpi/acpica/exoparg1.c
drivers/acpi/acpica/hwesleep.c
drivers/acpi/acpica/hwtimer.c
drivers/acpi/acpica/nspredef.c
drivers/acpi/acpica/nswalk.c
drivers/acpi/acpica/nsxfeval.c
drivers/acpi/acpica/nsxfname.c
drivers/acpi/acpica/tbfadt.c
drivers/acpi/acpica/tbxfroot.c
drivers/acpi/acpica/uteval.c
drivers/acpi/acpica/utglobal.c
drivers/acpi/acpica/utosi.c
drivers/acpi/acpica/utstring.c
drivers/acpi/acpica/utxface.c
drivers/acpi/battery.c
drivers/acpi/blacklist.c
drivers/acpi/bus.c
drivers/acpi/button.c
drivers/acpi/device_pm.c
drivers/acpi/dock.c
drivers/acpi/ec.c
drivers/acpi/event.c
drivers/acpi/fan.c
drivers/acpi/glue.c
drivers/acpi/internal.h
drivers/acpi/numa.c
drivers/acpi/osl.c
drivers/acpi/pci_slot.c
drivers/acpi/power.c
drivers/acpi/processor_core.c
drivers/acpi/processor_driver.c
drivers/acpi/processor_perflib.c
drivers/acpi/processor_thermal.c
drivers/acpi/resource.c
drivers/acpi/sbs.c
drivers/acpi/scan.c
drivers/acpi/sleep.c
drivers/acpi/thermal.c
drivers/acpi/utils.c
drivers/acpi/video.c
drivers/acpi/video_detect.c
drivers/ata/libata-acpi.c
drivers/ata/libata-pmp.c
drivers/ata/sata_fsl.c
drivers/ata/sata_highbank.c
drivers/base/power/main.c
drivers/base/power/opp.c
drivers/char/sonypi.c
drivers/cpuidle/Kconfig
drivers/cpuidle/Kconfig.arm [new file with mode: 0644]
drivers/cpuidle/Makefile
drivers/cpuidle/cpuidle-calxeda.c
drivers/cpuidle/cpuidle-kirkwood.c
drivers/cpuidle/cpuidle-ux500.c [new file with mode: 0644]
drivers/cpuidle/cpuidle.c
drivers/cpuidle/governors/ladder.c
drivers/cpuidle/governors/menu.c
drivers/cpuidle/sysfs.c
drivers/gpu/drm/gma500/psb_intel_sdvo.c
drivers/gpu/drm/i915/i915_gem_dmabuf.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/nouveau/core/core/mm.c
drivers/gpu/drm/nouveau/core/include/subdev/mc.h
drivers/gpu/drm/nouveau/core/subdev/fb/ramnv49.c
drivers/gpu/drm/nouveau/core/subdev/fb/ramnv4e.c
drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c
drivers/gpu/drm/nouveau/core/subdev/mc/base.c
drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c
drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c
drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c
drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c
drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c
drivers/gpu/drm/nouveau/dispnv04/crtc.c
drivers/gpu/drm/nouveau/dispnv04/disp.h
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nv40_pm.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_uvd.c
drivers/gpu/drm/radeon/rv770.c
drivers/ide/ide-acpi.c
drivers/iio/light/adjd_s311.c
drivers/md/dm-cache-policy-mq.c
drivers/mfd/db8500-prcmu.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/sfc/filter.c
drivers/net/irda/via-ircc.c
drivers/net/macvtap.c
drivers/net/phy/realtek.c
drivers/net/usb/hso.c
drivers/net/wireless/hostap/hostap_ioctl.c
drivers/net/wireless/iwlwifi/dvm/mac80211.c
drivers/net/wireless/iwlwifi/iwl-prph.h
drivers/net/wireless/iwlwifi/mvm/time-event.c
drivers/net/wireless/iwlwifi/pcie/rx.c
drivers/net/wireless/iwlwifi/pcie/trans.c
drivers/net/wireless/zd1201.c
drivers/of/fdt.c
drivers/pci/hotplug/acpiphp.h
drivers/pci/hotplug/acpiphp_core.c
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/hotplug/acpiphp_ibm.c
drivers/pci/pci-acpi.c
drivers/pinctrl/pinctrl-sunxi.c
drivers/pinctrl/pinctrl-sunxi.h
drivers/platform/olpc/olpc-ec.c
drivers/platform/x86/asus-laptop.c
drivers/platform/x86/eeepc-laptop.c
drivers/platform/x86/fujitsu-laptop.c
drivers/platform/x86/hp-wmi.c
drivers/platform/x86/panasonic-laptop.c
drivers/platform/x86/sony-laptop.c
drivers/platform/x86/thinkpad_acpi.c
drivers/pnp/driver.c
drivers/pnp/pnpacpi/core.c
drivers/s390/scsi/zfcp_erp.c
drivers/s390/scsi/zfcp_qdio.c
drivers/s390/scsi/zfcp_sysfs.c
drivers/scsi/Kconfig
drivers/staging/comedi/drivers.c
drivers/usb/host/ohci-pci.c
drivers/usb/phy/phy-fsl-usb.h
drivers/usb/phy/phy-fsm-usb.c
drivers/xen/acpi.c
drivers/xen/events.c
fs/bfs/inode.c
fs/bio.c
fs/dcache.c
fs/efs/inode.c
fs/gfs2/glock.c
fs/gfs2/glops.c
fs/gfs2/inode.c
fs/gfs2/main.c
fs/hugetlbfs/inode.c
fs/namespace.c
fs/nilfs2/segbuf.c
fs/proc/fd.c
fs/proc/generic.c
fs/proc/root.c
include/acpi/acpi_bus.h
include/acpi/acpi_drivers.h
include/acpi/acpixf.h
include/acpi/actypes.h
include/linux/acpi.h
include/linux/cpu.h
include/linux/cpuidle.h
include/linux/dcache.h
include/linux/inetdevice.h
include/linux/ipv6.h
include/linux/mm_types.h
include/linux/pci-acpi.h
include/linux/sched.h
include/linux/wait.h
include/net/ip6_route.h
include/trace/events/power.h
include/uapi/linux/ip.h
include/xen/acpi.h
include/xen/interface/platform.h
init/Kconfig
kernel/cpu.c
kernel/cpuset.c
kernel/power/suspend.c
kernel/time/sched_clock.c
kernel/time/tick-sched.c
kernel/wait.c
lib/earlycpio.c
lib/lz4/lz4_compress.c
lib/lz4/lz4_decompress.c
lib/lz4/lz4hc_compress.c
mm/memcontrol.c
mm/shmem.c
net/batman-adv/unicast.c
net/bridge/br_fdb.c
net/bridge/br_netlink.c
net/bridge/br_vlan.c
net/ipv4/tcp.c
net/ipv6/addrconf.c
net/ipv6/ndisc.c
net/ipv6/reassembly.c
net/ipv6/route.c
net/netlink/genetlink.c
net/packet/af_packet.c
net/wireless/nl80211.c
net/wireless/sme.c

index 15356ac..03c196d 100644 (file)
@@ -235,10 +235,61 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        Format: To spoof as Windows 98: ="Microsoft Windows"
 
        acpi_osi=       [HW,ACPI] Modify list of supported OS interface strings
-                       acpi_osi="string1"      # add string1 -- only one string
-                       acpi_osi="!string2"     # remove built-in string2
+                       acpi_osi="string1"      # add string1
+                       acpi_osi="!string2"     # remove string2
+                       acpi_osi=!*             # remove all strings
+                       acpi_osi=!              # disable all built-in OS vendor
+                                                 strings
                        acpi_osi=               # disable all strings
 
+                       'acpi_osi=!' can be used in combination with single or
+                       multiple 'acpi_osi="string1"' to support specific OS
+                       vendor string(s).  Note that such command can only
+                       affect the default state of the OS vendor strings, thus
+                       it cannot affect the default state of the feature group
+                       strings and the current state of the OS vendor strings,
+                       specifying it multiple times through kernel command line
+                       is meaningless.  This command is useful when one do not
+                       care about the state of the feature group strings which
+                       should be controlled by the OSPM.
+                       Examples:
+                         1. 'acpi_osi=! acpi_osi="Windows 2000"' is equivalent
+                            to 'acpi_osi="Windows 2000" acpi_osi=!', they all
+                            can make '_OSI("Windows 2000")' TRUE.
+
+                       'acpi_osi=' cannot be used in combination with other
+                       'acpi_osi=' command lines, the _OSI method will not
+                       exist in the ACPI namespace.  NOTE that such command can
+                       only affect the _OSI support state, thus specifying it
+                       multiple times through kernel command line is also
+                       meaningless.
+                       Examples:
+                         1. 'acpi_osi=' can make 'CondRefOf(_OSI, Local1)'
+                            FALSE.
+
+                       'acpi_osi=!*' can be used in combination with single or
+                       multiple 'acpi_osi="string1"' to support specific
+                       string(s).  Note that such command can affect the
+                       current state of both the OS vendor strings and the
+                       feature group strings, thus specifying it multiple times
+                       through kernel command line is meaningful.  But it may
+                       still not able to affect the final state of a string if
+                       there are quirks related to this string.  This command
+                       is useful when one want to control the state of the
+                       feature group strings to debug BIOS issues related to
+                       the OSPM features.
+                       Examples:
+                         1. 'acpi_osi="Module Device" acpi_osi=!*' can make
+                            '_OSI("Module Device")' FALSE.
+                         2. 'acpi_osi=!* acpi_osi="Module Device"' can make
+                            '_OSI("Module Device")' TRUE.
+                         3. 'acpi_osi=! acpi_osi=!* acpi_osi="Windows 2000"' is
+                            equivalent to
+                            'acpi_osi=!* acpi_osi=! acpi_osi="Windows 2000"'
+                            and
+                            'acpi_osi=!* acpi_osi="Windows 2000" acpi_osi=!',
+                            they all will make '_OSI("Windows 2000")' TRUE.
+
        acpi_pm_good    [X86]
                        Override the pmtimer bug detection: force the kernel
                        to assume that this machine's pmtimer latches its value
@@ -2953,7 +3004,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        improve throughput, but will also increase the
                        amount of memory reserved for use by the client.
 
-       swapaccount[=0|1]
+       swapaccount=[0|1]
                        [KNL] Enable accounting of swap in memory resource
                        controller if no parameter or 1 is given or disable
                        it if 0 is given (See Documentation/cgroups/memory.txt)
index 69f9fb3..79a1bc6 100644 (file)
@@ -8,8 +8,8 @@ http://acpi4asus.sf.net/
 
  This driver provides support for extra features of ACPI-compatible ASUS laptops.
  It may also support some MEDION, JVC or VICTOR laptops (such as MEDION 9675 or
- VICTOR XP7210 for example). It makes all the extra buttons generate standard
ACPI events that go through /proc/acpi/events and input events (like keyboards).
+ VICTOR XP7210 for example). It makes all the extra buttons generate input
+ events (like keyboards).
  On some models adds support for changing the display brightness and output,
  switching the LCD backlight on and off, and most importantly, allows you to
  blink those fancy LEDs intended for reporting mail and wireless status.
@@ -55,8 +55,8 @@ Usage
   DSDT) to me.
 
   That's all, now, all the events generated by the hotkeys of your laptop
-  should be reported in your /proc/acpi/event entry. You can check with
-  "acpi_listen".
+  should be reported via netlink events. You can check with
+  "acpi_genl monitor" (part of the acpica project).
 
   Hotkeys are also reported as input keys (like keyboards) you can check
   which key are supported using "xev" under X11.
index 0d5ac7f..978b1e6 100644 (file)
@@ -12,10 +12,10 @@ Fn keys (hotkeys):
 ------------------
 Some models report hotkeys through the SNC or SPIC devices, such events are
 reported both through the ACPI subsystem as acpi events and through the INPUT
-subsystem. See the logs of acpid or /proc/acpi/event and
-/proc/bus/input/devices to find out what those events are and which input
-devices are created by the driver. Additionally, loading the driver with the
-debug option will report all events in the kernel log.
+subsystem. See the logs of /proc/bus/input/devices to find out what those
+events are and which input devices are created by the driver.
+Additionally, loading the driver with the debug option will report all events
+in the kernel log.
 
 The "scancodes" passed to the input system (that can be remapped with udev)
 are indexes to the table "sony_laptop_input_keycode_map" in the sony-laptop.c
index cf7bc6c..86c5236 100644 (file)
@@ -329,20 +329,6 @@ sysfs notes:
 
                This attribute has poll()/select() support.
 
-       hotkey_report_mode:
-               Returns the state of the procfs ACPI event report mode
-               filter for hot keys.  If it is set to 1 (the default),
-               all hot key presses are reported both through the input
-               layer and also as ACPI events through procfs (but not
-               through netlink).  If it is set to 2, hot key presses
-               are reported only through the input layer.
-
-               This attribute is read-only in kernels 2.6.23 or later,
-               and read-write on earlier kernels.
-
-               May return -EPERM (write access locked out by module
-               parameter) or -EACCES (read-only).
-
        wakeup_reason:
                Set to 1 if the system is waking up because the user
                requested a bay ejection.  Set to 2 if the system is
@@ -518,24 +504,21 @@ SW_TABLET_MODE    Tablet ThinkPads HKEY events 0x5009 and 0x500A
 Non hotkey ACPI HKEY event map:
 -------------------------------
 
-Events that are not propagated by the driver, except for legacy
-compatibility purposes when hotkey_report_mode is set to 1:
-
-0x5001         Lid closed
-0x5002         Lid opened
-0x5009         Tablet swivel: switched to tablet mode
-0x500A         Tablet swivel: switched to normal mode
-0x7000         Radio Switch may have changed state
-
 Events that are never propagated by the driver:
 
 0x2304         System is waking up from suspend to undock
 0x2305         System is waking up from suspend to eject bay
 0x2404         System is waking up from hibernation to undock
 0x2405         System is waking up from hibernation to eject bay
+0x5001         Lid closed
+0x5002         Lid opened
+0x5009         Tablet swivel: switched to tablet mode
+0x500A         Tablet swivel: switched to normal mode
 0x5010         Brightness level changed/control event
 0x6000         KEYBOARD: Numlock key pressed
 0x6005         KEYBOARD: Fn key pressed (TO BE VERIFIED)
+0x7000         Radio Switch may have changed state
+
 
 Events that are propagated by the driver to userspace:
 
@@ -574,50 +557,6 @@ operating system is to force either an immediate suspend or hibernate
 cycle, or a system shutdown.  Obviously, something is very wrong if this
 happens.
 
-Compatibility notes:
-
-ibm-acpi and thinkpad-acpi 0.15 (mainline kernels before 2.6.23) never
-supported the input layer, and sent events over the procfs ACPI event
-interface.
-
-To avoid sending duplicate events over the input layer and the ACPI
-event interface, thinkpad-acpi 0.16 implements a module parameter
-(hotkey_report_mode), and also a sysfs device attribute with the same
-name.
-
-Make no mistake here: userspace is expected to switch to using the input
-layer interface of thinkpad-acpi, together with the ACPI netlink event
-interface in kernels 2.6.23 and later, or with the ACPI procfs event
-interface in kernels 2.6.22 and earlier.
-
-If no hotkey_report_mode module parameter is specified (or it is set to
-zero), the driver defaults to mode 1 (see below), and on kernels 2.6.22
-and earlier, also allows one to change the hotkey_report_mode through
-sysfs.  In kernels 2.6.23 and later, where the netlink ACPI event
-interface is available, hotkey_report_mode cannot be changed through
-sysfs (it is read-only).
-
-If the hotkey_report_mode module parameter is set to 1 or 2, it cannot
-be changed later through sysfs (any writes will return -EPERM to signal
-that hotkey_report_mode was locked.  On 2.6.23 and later, where
-hotkey_report_mode cannot be changed at all, writes will return -EACCES).
-
-hotkey_report_mode set to 1 makes the driver export through the procfs
-ACPI event interface all hot key presses (which are *also* sent to the
-input layer).  This is a legacy compatibility behaviour, and it is also
-the default mode of operation for the driver.
-
-hotkey_report_mode set to 2 makes the driver filter out the hot key
-presses from the procfs ACPI event interface, so these events will only
-be sent through the input layer.  Userspace that has been updated to use
-the thinkpad-acpi input layer interface should set hotkey_report_mode to
-2.
-
-Hot key press events are never sent to the ACPI netlink event interface.
-Really up-to-date userspace under kernel 2.6.23 and later is to use the
-netlink interface and the input layer interface, and don't bother at all
-with hotkey_report_mode.
-
 
 Brightness hotkey notes:
 
index 229c66b..8197fbd 100644 (file)
@@ -5884,7 +5884,7 @@ F:        drivers/i2c/busses/i2c-omap.c
 F:     include/linux/i2c-omap.h
 
 OMAP DEVICE TREE SUPPORT
-M:     Benoît Cousson <b-cousson@ti.com>
+M:     Benoît Cousson <bcousson@baylibre.com>
 M:     Tony Lindgren <tony@atomide.com>
 L:     linux-omap@vger.kernel.org
 L:     devicetree@vger.kernel.org
@@ -5964,14 +5964,14 @@ S:      Maintained
 F:     drivers/char/hw_random/omap-rng.c
 
 OMAP HWMOD SUPPORT
-M:     Benoît Cousson <b-cousson@ti.com>
+M:     Benoît Cousson <bcousson@baylibre.com>
 M:     Paul Walmsley <paul@pwsan.com>
 L:     linux-omap@vger.kernel.org
 S:     Maintained
 F:     arch/arm/mach-omap2/omap_hwmod.*
 
 OMAP HWMOD DATA FOR OMAP4-BASED DEVICES
-M:     Benoît Cousson <b-cousson@ti.com>
+M:     Benoît Cousson <bcousson@baylibre.com>
 L:     linux-omap@vger.kernel.org
 S:     Maintained
 F:     arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index a5a55f4..369882e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 11
 SUBLEVEL = 0
-EXTRAVERSION = -rc6
+EXTRAVERSION = -rc7
 NAME = Linux for Workgroups
 
 # *DOCUMENTATION*
index 99c1047..9c548c7 100644 (file)
@@ -39,9 +39,18 @@ ARC_ENTRY strchr
        ld.a    r2,[r0,4]
        sub     r12,r6,r7
        bic     r12,r12,r6
+#ifdef __LITTLE_ENDIAN__
        and     r7,r12,r4
        breq    r7,0,.Loop ; For speed, we want this branch to be unaligned.
        b       .Lfound_char ; Likewise this one.
+#else
+       and     r12,r12,r4
+       breq    r12,0,.Loop ; For speed, we want this branch to be unaligned.
+       lsr_s   r12,r12,7
+       bic     r2,r7,r6
+       b.d     .Lfound_char_b
+       and_s   r2,r2,r12
+#endif
 ; /* We require this code address to be unaligned for speed...  */
 .Laligned:
        ld_s    r2,[r0]
@@ -95,6 +104,7 @@ ARC_ENTRY strchr
        lsr     r7,r7,7
 
        bic     r2,r7,r6
+.Lfound_char_b:
        norm    r2,r2
        sub_s   r0,r0,4
        asr_s   r2,r2,3
index d59b70c..3d77dbe 100644 (file)
        compatible = "atmel,at91sam9n12ek", "atmel,at91sam9n12", "atmel,at91sam9";
 
        chosen {
-               bootargs = "mem=128M console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=jffs2";
+               bootargs = "console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=jffs2";
        };
 
        memory {
-               reg = <0x20000000 0x10000000>;
+               reg = <0x20000000 0x8000000>;
        };
 
        clocks {
index b753855..49e3c45 100644 (file)
@@ -94,8 +94,9 @@
 
                usb0: ohci@00600000 {
                        status = "okay";
-                       num-ports = <2>;
-                       atmel,vbus-gpio = <&pioD 19 GPIO_ACTIVE_LOW
+                       num-ports = <3>;
+                       atmel,vbus-gpio = <0 /* &pioD 18 GPIO_ACTIVE_LOW *//* Activate to have access to port A */
+                                          &pioD 19 GPIO_ACTIVE_LOW
                                           &pioD 20 GPIO_ACTIVE_LOW
                                          >;
                };
index 365760b..40e6fb2 100644 (file)
                        regulator-max-microvolt = <5000000>;
                        enable-active-high;
                        gpio = <&gpio 24 0>; /* PD0 */
+                       regulator-always-on;
+                       regulator-boot-on;
                };
        };
 
index ed4b901..37c93d3 100644 (file)
                        regulator-max-microvolt = <5000000>;
                        enable-active-high;
                        gpio = <&gpio 170 0>; /* PV2 */
+                       regulator-always-on;
+                       regulator-boot-on;
                };
        };
 
index ab67c94..a3d0eba 100644 (file)
                        regulator-max-microvolt = <5000000>;
                        enable-active-high;
                        gpio = <&tca6416 0 0>; /* GPIO_PMU0 */
+                       regulator-always-on;
+                       regulator-boot-on;
                };
 
                vbus3_reg: regulator@3 {
                        regulator-max-microvolt = <5000000>;
                        enable-active-high;
                        gpio = <&tca6416 1 0>; /* GPIO_PMU1 */
+                       regulator-always-on;
+                       regulator-boot-on;
                };
        };
 
index fc79202..918875d 100644 (file)
@@ -89,7 +89,8 @@ void set_fiq_handler(void *start, unsigned int length)
 
        memcpy(base + offset, start, length);
        if (!cache_is_vipt_nonaliasing())
-               flush_icache_range(base + offset, offset + length);
+               flush_icache_range((unsigned long)base + offset, offset +
+                                  length);
        flush_icache_range(0xffff0000 + offset, 0xffff0000 + offset + length);
 }
 
index d7c82df..57221e3 100644 (file)
@@ -82,6 +82,7 @@ void machine_crash_nonpanic_core(void *unused)
        crash_save_cpu(&regs, smp_processor_id());
        flush_cache_all();
 
+       set_cpu_online(smp_processor_id(), false);
        atomic_dec(&waiting_for_crash_ipi);
        while (1)
                cpu_relax();
index 4a51990..db9cf69 100644 (file)
@@ -146,7 +146,11 @@ static bool pm_fake(struct kvm_vcpu *vcpu,
 #define access_pmintenclr pm_fake
 
 /* Architected CP15 registers.
- * Important: Must be sorted ascending by CRn, CRM, Op1, Op2
+ * CRn denotes the primary register number, but is copied to the CRm in the
+ * user space API for 64-bit register access in line with the terminology used
+ * in the ARM ARM.
+ * Important: Must be sorted ascending by CRn, CRM, Op1, Op2 and with 64-bit
+ *            registers preceding 32-bit ones.
  */
 static const struct coproc_reg cp15_regs[] = {
        /* CSSELR: swapped by interrupt.S. */
@@ -154,8 +158,8 @@ static const struct coproc_reg cp15_regs[] = {
                        NULL, reset_unknown, c0_CSSELR },
 
        /* TTBR0/TTBR1: swapped by interrupt.S. */
-       { CRm( 2), Op1( 0), is64, NULL, reset_unknown64, c2_TTBR0 },
-       { CRm( 2), Op1( 1), is64, NULL, reset_unknown64, c2_TTBR1 },
+       { CRm64( 2), Op1( 0), is64, NULL, reset_unknown64, c2_TTBR0 },
+       { CRm64( 2), Op1( 1), is64, NULL, reset_unknown64, c2_TTBR1 },
 
        /* TTBCR: swapped by interrupt.S. */
        { CRn( 2), CRm( 0), Op1( 0), Op2( 2), is32,
@@ -182,7 +186,7 @@ static const struct coproc_reg cp15_regs[] = {
                        NULL, reset_unknown, c6_IFAR },
 
        /* PAR swapped by interrupt.S */
-       { CRn( 7), Op1( 0), is64, NULL, reset_unknown64, c7_PAR },
+       { CRm64( 7), Op1( 0), is64, NULL, reset_unknown64, c7_PAR },
 
        /*
         * DC{C,I,CI}SW operations:
@@ -399,12 +403,13 @@ static bool index_to_params(u64 id, struct coproc_params *params)
                              | KVM_REG_ARM_OPC1_MASK))
                        return false;
                params->is_64bit = true;
-               params->CRm = ((id & KVM_REG_ARM_CRM_MASK)
+               /* CRm to CRn: see cp15_to_index for details */
+               params->CRn = ((id & KVM_REG_ARM_CRM_MASK)
                               >> KVM_REG_ARM_CRM_SHIFT);
                params->Op1 = ((id & KVM_REG_ARM_OPC1_MASK)
                               >> KVM_REG_ARM_OPC1_SHIFT);
                params->Op2 = 0;
-               params->CRn = 0;
+               params->CRm = 0;
                return true;
        default:
                return false;
@@ -898,7 +903,14 @@ static u64 cp15_to_index(const struct coproc_reg *reg)
        if (reg->is_64) {
                val |= KVM_REG_SIZE_U64;
                val |= (reg->Op1 << KVM_REG_ARM_OPC1_SHIFT);
-               val |= (reg->CRm << KVM_REG_ARM_CRM_SHIFT);
+               /*
+                * CRn always denotes the primary coproc. reg. nr. for the
+                * in-kernel representation, but the user space API uses the
+                * CRm for the encoding, because it is modelled after the
+                * MRRC/MCRR instructions: see the ARM ARM rev. c page
+                * B3-1445
+                */
+               val |= (reg->CRn << KVM_REG_ARM_CRM_SHIFT);
        } else {
                val |= KVM_REG_SIZE_U32;
                val |= (reg->Op1 << KVM_REG_ARM_OPC1_SHIFT);
index b7301d3..0461d5c 100644 (file)
@@ -135,6 +135,8 @@ static inline int cmp_reg(const struct coproc_reg *i1,
                return -1;
        if (i1->CRn != i2->CRn)
                return i1->CRn - i2->CRn;
+       if (i1->is_64 != i2->is_64)
+               return i2->is_64 - i1->is_64;
        if (i1->CRm != i2->CRm)
                return i1->CRm - i2->CRm;
        if (i1->Op1 != i2->Op1)
@@ -145,6 +147,7 @@ static inline int cmp_reg(const struct coproc_reg *i1,
 
 #define CRn(_x)                .CRn = _x
 #define CRm(_x)        .CRm = _x
+#define CRm64(_x)       .CRn = _x, .CRm = 0
 #define Op1(_x)        .Op1 = _x
 #define Op2(_x)        .Op2 = _x
 #define is64           .is_64 = true
index 685063a..cf93472 100644 (file)
@@ -114,7 +114,11 @@ static bool access_l2ectlr(struct kvm_vcpu *vcpu,
 
 /*
  * A15-specific CP15 registers.
- * Important: Must be sorted ascending by CRn, CRM, Op1, Op2
+ * CRn denotes the primary register number, but is copied to the CRm in the
+ * user space API for 64-bit register access in line with the terminology used
+ * in the ARM ARM.
+ * Important: Must be sorted ascending by CRn, CRM, Op1, Op2 and with 64-bit
+ *            registers preceding 32-bit ones.
  */
 static const struct coproc_reg a15_regs[] = {
        /* MPIDR: we use VMPIDR for guest access. */
index b8e06b7..0c25d94 100644 (file)
@@ -63,7 +63,8 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
 static int decode_hsr(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
                      struct kvm_exit_mmio *mmio)
 {
-       unsigned long rt, len;
+       unsigned long rt;
+       int len;
        bool is_write, sign_extend;
 
        if (kvm_vcpu_dabt_isextabt(vcpu)) {
index ca6bea4..0988d9e 100644 (file)
@@ -85,6 +85,12 @@ static void *mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc)
        return p;
 }
 
+static bool page_empty(void *ptr)
+{
+       struct page *ptr_page = virt_to_page(ptr);
+       return page_count(ptr_page) == 1;
+}
+
 static void clear_pud_entry(struct kvm *kvm, pud_t *pud, phys_addr_t addr)
 {
        pmd_t *pmd_table = pmd_offset(pud, 0);
@@ -103,12 +109,6 @@ static void clear_pmd_entry(struct kvm *kvm, pmd_t *pmd, phys_addr_t addr)
        put_page(virt_to_page(pmd));
 }
 
-static bool pmd_empty(pmd_t *pmd)
-{
-       struct page *pmd_page = virt_to_page(pmd);
-       return page_count(pmd_page) == 1;
-}
-
 static void clear_pte_entry(struct kvm *kvm, pte_t *pte, phys_addr_t addr)
 {
        if (pte_present(*pte)) {
@@ -118,12 +118,6 @@ static void clear_pte_entry(struct kvm *kvm, pte_t *pte, phys_addr_t addr)
        }
 }
 
-static bool pte_empty(pte_t *pte)
-{
-       struct page *pte_page = virt_to_page(pte);
-       return page_count(pte_page) == 1;
-}
-
 static void unmap_range(struct kvm *kvm, pgd_t *pgdp,
                        unsigned long long start, u64 size)
 {
@@ -132,37 +126,37 @@ static void unmap_range(struct kvm *kvm, pgd_t *pgdp,
        pmd_t *pmd;
        pte_t *pte;
        unsigned long long addr = start, end = start + size;
-       u64 range;
+       u64 next;
 
        while (addr < end) {
                pgd = pgdp + pgd_index(addr);
                pud = pud_offset(pgd, addr);
                if (pud_none(*pud)) {
-                       addr += PUD_SIZE;
+                       addr = pud_addr_end(addr, end);
                        continue;
                }
 
                pmd = pmd_offset(pud, addr);
                if (pmd_none(*pmd)) {
-                       addr += PMD_SIZE;
+                       addr = pmd_addr_end(addr, end);
                        continue;
                }
 
                pte = pte_offset_kernel(pmd, addr);
                clear_pte_entry(kvm, pte, addr);
-               range = PAGE_SIZE;
+               next = addr + PAGE_SIZE;
 
                /* If we emptied the pte, walk back up the ladder */
-               if (pte_empty(pte)) {
+               if (page_empty(pte)) {
                        clear_pmd_entry(kvm, pmd, addr);
-                       range = PMD_SIZE;
-                       if (pmd_empty(pmd)) {
+                       next = pmd_addr_end(addr, end);
+                       if (page_empty(pmd) && !page_empty(pud)) {
                                clear_pud_entry(kvm, pud, addr);
-                               range = PUD_SIZE;
+                               next = pud_addr_end(addr, end);
                        }
                }
 
-               addr += range;
+               addr = next;
        }
 }
 
index 2abee66..916e5a1 100644 (file)
@@ -227,6 +227,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("usart", "f8020000.serial", &usart1_clk),
        CLKDEV_CON_DEV_ID("usart", "f8024000.serial", &usart2_clk),
        CLKDEV_CON_DEV_ID("usart", "f8028000.serial", &usart3_clk),
+       CLKDEV_CON_DEV_ID("usart", "f8040000.serial", &uart0_clk),
+       CLKDEV_CON_DEV_ID("usart", "f8044000.serial", &uart1_clk),
        CLKDEV_CON_DEV_ID("t0_clk", "f8008000.timer", &tcb0_clk),
        CLKDEV_CON_DEV_ID("t0_clk", "f800c000.timer", &tcb0_clk),
        CLKDEV_CON_DEV_ID("mci_clk", "f0008000.mmc", &mmc0_clk),
index dff4ddc..139e42d 100644 (file)
@@ -75,6 +75,7 @@ static struct davinci_nand_pdata davinci_nand_data = {
        .parts                  = davinci_nand_partitions,
        .nr_parts               = ARRAY_SIZE(davinci_nand_partitions),
        .ecc_mode               = NAND_ECC_HW_SYNDROME,
+       .ecc_bits               = 4,
        .bbt_options            = NAND_BBT_USE_FLASH,
 };
 
index a33686a..fa4bfaf 100644 (file)
@@ -153,6 +153,7 @@ static struct davinci_nand_pdata davinci_evm_nandflash_data = {
        .parts          = davinci_evm_nandflash_partition,
        .nr_parts       = ARRAY_SIZE(davinci_evm_nandflash_partition),
        .ecc_mode       = NAND_ECC_HW,
+       .ecc_bits       = 1,
        .bbt_options    = NAND_BBT_USE_FLASH,
        .timing         = &davinci_evm_nandflash_timing,
 };
index fbb8e5a..0c005e8 100644 (file)
@@ -90,6 +90,7 @@ static struct davinci_nand_pdata davinci_nand_data = {
        .parts                  = davinci_nand_partitions,
        .nr_parts               = ARRAY_SIZE(davinci_nand_partitions),
        .ecc_mode               = NAND_ECC_HW,
+       .ecc_bits               = 1,
        .options                = 0,
 };
 
index 2bc112a..808233b 100644 (file)
@@ -88,6 +88,7 @@ static struct davinci_nand_pdata davinci_ntosd2_nandflash_data = {
        .parts          = davinci_ntosd2_nandflash_partition,
        .nr_parts       = ARRAY_SIZE(davinci_ntosd2_nandflash_partition),
        .ecc_mode       = NAND_ECC_HW,
+       .ecc_bits       = 1,
        .bbt_options    = NAND_BBT_USE_FLASH,
 };
 
index 36aef3a..f1ac1c9 100644 (file)
@@ -65,7 +65,7 @@ static struct cpuidle_driver davinci_idle_driver = {
        .states[1]              = {
                .enter                  = davinci_enter_idle,
                .exit_latency           = 10,
-               .target_residency       = 100000,
+               .target_residency       = 10000,
                .flags                  = CPUIDLE_FLAG_TIME_VALID,
                .name                   = "DDR SR",
                .desc                   = "WFI and DDR Self Refresh",
index f6eeb87..827d150 100644 (file)
@@ -122,11 +122,7 @@ static struct musb_hdrc_config musb_config = {
 };
 
 static struct musb_hdrc_platform_data tusb_data = {
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
        .mode           = MUSB_OTG,
-#else
-       .mode           = MUSB_HOST,
-#endif
        .set_power      = tusb_set_power,
        .min_power      = 25,   /* x2 = 50 mA drawn from VBUS as peripheral */
        .power          = 100,  /* Max 100 mA VBUS for host mode */
index d2ea68e..7735105 100644 (file)
@@ -85,7 +85,7 @@ static struct omap_board_mux board_mux[] __initdata = {
 
 static struct omap_musb_board_data musb_board_data = {
        .interface_type         = MUSB_INTERFACE_ULPI,
-       .mode                   = MUSB_PERIPHERAL,
+       .mode                   = MUSB_OTG,
        .power                  = 0,
 };
 
index 8c4de27..bc89723 100644 (file)
@@ -38,11 +38,8 @@ static struct musb_hdrc_config musb_config = {
 };
 
 static struct musb_hdrc_platform_data musb_plat = {
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
        .mode           = MUSB_OTG,
-#else
-       .mode           = MUSB_HOST,
-#endif
+
        /* .clock is set dynamically */
        .config         = &musb_config,
 
index bf9b6be..fe1f3e2 100644 (file)
@@ -4,7 +4,6 @@
 
 obj-y                          := cpu.o devices.o devices-common.o \
                                   id.o usb.o timer.o pm.o
-obj-$(CONFIG_CPU_IDLE)          += cpuidle.o
 obj-$(CONFIG_CACHE_L2X0)       += cache-l2x0.o
 obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o
 obj-$(CONFIG_MACH_MOP500)      += board-mop500.o board-mop500-sdi.o \
diff --git a/arch/arm/mach-ux500/cpuidle.c b/arch/arm/mach-ux500/cpuidle.c
deleted file mode 100644 (file)
index a45dd09..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (c) 2012 Linaro : Daniel Lezcano <daniel.lezcano@linaro.org> (IBM)
- *
- * Based on the work of Rickard Andersson <rickard.andersson@stericsson.com>
- * and Jonas Aaberg <jonas.aberg@stericsson.com>.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/cpuidle.h>
-#include <linux/spinlock.h>
-#include <linux/atomic.h>
-#include <linux/smp.h>
-#include <linux/mfd/dbx500-prcmu.h>
-#include <linux/platform_data/arm-ux500-pm.h>
-
-#include <asm/cpuidle.h>
-#include <asm/proc-fns.h>
-
-#include "db8500-regs.h"
-#include "id.h"
-
-static atomic_t master = ATOMIC_INIT(0);
-static DEFINE_SPINLOCK(master_lock);
-
-static inline int ux500_enter_idle(struct cpuidle_device *dev,
-                                  struct cpuidle_driver *drv, int index)
-{
-       int this_cpu = smp_processor_id();
-       bool recouple = false;
-
-       if (atomic_inc_return(&master) == num_online_cpus()) {
-
-               /* With this lock, we prevent the other cpu to exit and enter
-                * this function again and become the master */
-               if (!spin_trylock(&master_lock))
-                       goto wfi;
-
-               /* decouple the gic from the A9 cores */
-               if (prcmu_gic_decouple()) {
-                       spin_unlock(&master_lock);
-                       goto out;
-               }
-
-               /* If an error occur, we will have to recouple the gic
-                * manually */
-               recouple = true;
-
-               /* At this state, as the gic is decoupled, if the other
-                * cpu is in WFI, we have the guarantee it won't be wake
-                * up, so we can safely go to retention */
-               if (!prcmu_is_cpu_in_wfi(this_cpu ? 0 : 1))
-                       goto out;
-
-               /* The prcmu will be in charge of watching the interrupts
-                * and wake up the cpus */
-               if (prcmu_copy_gic_settings())
-                       goto out;
-
-               /* Check in the meantime an interrupt did
-                * not occur on the gic ... */
-               if (prcmu_gic_pending_irq())
-                       goto out;
-
-               /* ... and the prcmu */
-               if (prcmu_pending_irq())
-                       goto out;
-
-               /* Go to the retention state, the prcmu will wait for the
-                * cpu to go WFI and this is what happens after exiting this
-                * 'master' critical section */
-               if (prcmu_set_power_state(PRCMU_AP_IDLE, true, true))
-                       goto out;
-
-               /* When we switch to retention, the prcmu is in charge
-                * of recoupling the gic automatically */
-               recouple = false;
-
-               spin_unlock(&master_lock);
-       }
-wfi:
-       cpu_do_idle();
-out:
-       atomic_dec(&master);
-
-       if (recouple) {
-               prcmu_gic_recouple();
-               spin_unlock(&master_lock);
-       }
-
-       return index;
-}
-
-static struct cpuidle_driver ux500_idle_driver = {
-       .name = "ux500_idle",
-       .owner = THIS_MODULE,
-       .states = {
-               ARM_CPUIDLE_WFI_STATE,
-               {
-                       .enter            = ux500_enter_idle,
-                       .exit_latency     = 70,
-                       .target_residency = 260,
-                       .flags            = CPUIDLE_FLAG_TIME_VALID |
-                                           CPUIDLE_FLAG_TIMER_STOP,
-                       .name             = "ApIdle",
-                       .desc             = "ARM Retention",
-               },
-       },
-       .safe_state_index = 0,
-       .state_count = 2,
-};
-
-int __init ux500_idle_init(void)
-{
-       if (!(cpu_is_u8500_family() || cpu_is_ux540_family()))
-               return -ENODEV;
-
-       /* Configure wake up reasons */
-       prcmu_enable_wakeups(PRCMU_WAKEUP(ARM) | PRCMU_WAKEUP(RTC) |
-                            PRCMU_WAKEUP(ABB));
-
-       return cpuidle_register(&ux500_idle_driver, NULL);
-}
-
-device_initcall(ux500_idle_init);
index db5c2ca..cd2c88e 100644 (file)
@@ -809,15 +809,18 @@ config KUSER_HELPERS
          the CPU type fitted to the system.  This permits binaries to be
          run on ARMv4 through to ARMv7 without modification.
 
+         See Documentation/arm/kernel_user_helpers.txt for details.
+
          However, the fixed address nature of these helpers can be used
          by ROP (return orientated programming) authors when creating
          exploits.
 
          If all of the binaries and libraries which run on your platform
          are built specifically for your platform, and make no use of
-         these helpers, then you can turn this option off.  However,
-         when such an binary or library is run, it will receive a SIGILL
-         signal, which will terminate the program.
+         these helpers, then you can turn this option off to hinder
+         such exploits. However, in that case, if a binary or library
+         relying on those helpers is run, it will receive a SIGILL signal,
+         which will terminate the program.
 
          Say N here only if you are absolutely certain that you do not
          need these helpers; otherwise, the safe option is to say Y.
index 3e5c461..50a3ea0 100644 (file)
@@ -55,12 +55,13 @@ void __init s3c_init_cpu(unsigned long idcode,
 
        printk("CPU %s (id 0x%08lx)\n", cpu->name, idcode);
 
-       if (cpu->map_io == NULL || cpu->init == NULL) {
+       if (cpu->init == NULL) {
                printk(KERN_ERR "CPU %s support not enabled\n", cpu->name);
                panic("Unsupported Samsung CPU");
        }
 
-       cpu->map_io();
+       if (cpu->map_io)
+               cpu->map_io();
 }
 
 /* s3c24xx_init_clocks
index c9770ba..8a6295c 100644 (file)
@@ -170,6 +170,7 @@ static void __init xen_percpu_init(void *unused)
        per_cpu(xen_vcpu, cpu) = vcpup;
 
        enable_percpu_irq(xen_events_irq, 0);
+       put_cpu();
 }
 
 static void xen_restart(enum reboot_mode reboot_mode, const char *cmd)
index c92de41..b25763b 100644 (file)
 #define        TPIDR_EL1       18      /* Thread ID, Privileged */
 #define        AMAIR_EL1       19      /* Aux Memory Attribute Indirection Register */
 #define        CNTKCTL_EL1     20      /* Timer Control Register (EL1) */
+#define        PAR_EL1         21      /* Physical Address Register */
 /* 32bit specific registers. Keep them at the end of the range */
-#define        DACR32_EL2      21      /* Domain Access Control Register */
-#define        IFSR32_EL2      22      /* Instruction Fault Status Register */
-#define        FPEXC32_EL2     23      /* Floating-Point Exception Control Register */
-#define        DBGVCR32_EL2    24      /* Debug Vector Catch Register */
-#define        TEECR32_EL1     25      /* ThumbEE Configuration Register */
-#define        TEEHBR32_EL1    26      /* ThumbEE Handler Base Register */
-#define        NR_SYS_REGS     27
+#define        DACR32_EL2      22      /* Domain Access Control Register */
+#define        IFSR32_EL2      23      /* Instruction Fault Status Register */
+#define        FPEXC32_EL2     24      /* Floating-Point Exception Control Register */
+#define        DBGVCR32_EL2    25      /* Debug Vector Catch Register */
+#define        TEECR32_EL1     26      /* ThumbEE Configuration Register */
+#define        TEEHBR32_EL1    27      /* ThumbEE Handler Base Register */
+#define        NR_SYS_REGS     28
 
 /* 32bit mapping */
 #define c0_MPIDR       (MPIDR_EL1 * 2) /* MultiProcessor ID Register */
@@ -69,6 +70,8 @@
 #define c5_AIFSR       (AFSR1_EL1 * 2) /* Auxiliary Instr Fault Status R */
 #define c6_DFAR                (FAR_EL1 * 2)   /* Data Fault Address Register */
 #define c6_IFAR                (c6_DFAR + 1)   /* Instruction Fault Address Register */
+#define c7_PAR         (PAR_EL1 * 2)   /* Physical Address Register */
+#define c7_PAR_high    (c7_PAR + 1)    /* PAR top 32 bits */
 #define c10_PRRR       (MAIR_EL1 * 2)  /* Primary Region Remap Register */
 #define c10_NMRR       (c10_PRRR + 1)  /* Normal Memory Remap Register */
 #define c12_VBAR       (VBAR_EL1 * 2)  /* Vector Base Address Register */
index 644d739..0859a4d 100644 (file)
@@ -129,7 +129,7 @@ struct kvm_vcpu_arch {
        struct kvm_mmu_memory_cache mmu_page_cache;
 
        /* Target CPU and feature flags */
-       u32 target;
+       int target;
        DECLARE_BITMAP(features, KVM_VCPU_MAX_FEATURES);
 
        /* Detect first run of a vcpu */
index 9ba33c4..12e6ccb 100644 (file)
@@ -107,7 +107,12 @@ armpmu_map_cache_event(const unsigned (*cache_map)
 static int
 armpmu_map_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config)
 {
-       int mapping = (*event_map)[config];
+       int mapping;
+
+       if (config >= PERF_COUNT_HW_MAX)
+               return -EINVAL;
+
+       mapping = (*event_map)[config];
        return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping;
 }
 
@@ -317,6 +322,9 @@ validate_event(struct pmu_hw_events *hw_events,
        struct hw_perf_event fake_event = event->hw;
        struct pmu *leader_pmu = event->group_leader->pmu;
 
+       if (is_software_event(event))
+               return 1;
+
        if (event->pmu != leader_pmu || event->state <= PERF_EVENT_STATE_OFF)
                return 1;
 
index ff985e3..1ac0bbb 100644 (file)
@@ -214,6 +214,7 @@ __kvm_hyp_code_start:
        mrs     x21,    tpidr_el1
        mrs     x22,    amair_el1
        mrs     x23,    cntkctl_el1
+       mrs     x24,    par_el1
 
        stp     x4, x5, [x3]
        stp     x6, x7, [x3, #16]
@@ -225,6 +226,7 @@ __kvm_hyp_code_start:
        stp     x18, x19, [x3, #112]
        stp     x20, x21, [x3, #128]
        stp     x22, x23, [x3, #144]
+       str     x24, [x3, #160]
 .endm
 
 .macro restore_sysregs
@@ -243,6 +245,7 @@ __kvm_hyp_code_start:
        ldp     x18, x19, [x3, #112]
        ldp     x20, x21, [x3, #128]
        ldp     x22, x23, [x3, #144]
+       ldr     x24, [x3, #160]
 
        msr     vmpidr_el2,     x4
        msr     csselr_el1,     x5
@@ -264,6 +267,7 @@ __kvm_hyp_code_start:
        msr     tpidr_el1,      x21
        msr     amair_el1,      x22
        msr     cntkctl_el1,    x23
+       msr     par_el1,        x24
 .endm
 
 .macro skip_32bit_state tmp, target
@@ -600,6 +604,8 @@ END(__kvm_vcpu_run)
 
 // void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa);
 ENTRY(__kvm_tlb_flush_vmid_ipa)
+       dsb     ishst
+
        kern_hyp_va     x0
        ldr     x2, [x0, #KVM_VTTBR]
        msr     vttbr_el2, x2
@@ -621,6 +627,7 @@ ENTRY(__kvm_tlb_flush_vmid_ipa)
 ENDPROC(__kvm_tlb_flush_vmid_ipa)
 
 ENTRY(__kvm_flush_vm_context)
+       dsb     ishst
        tlbi    alle1is
        ic      ialluis
        dsb     sy
@@ -753,6 +760,10 @@ el1_trap:
         */
        tbnz    x1, #7, 1f      // S1PTW is set
 
+       /* Preserve PAR_EL1 */
+       mrs     x3, par_el1
+       push    x3, xzr
+
        /*
         * Permission fault, HPFAR_EL2 is invalid.
         * Resolve the IPA the hard way using the guest VA.
@@ -766,6 +777,8 @@ el1_trap:
 
        /* Read result */
        mrs     x3, par_el1
+       pop     x0, xzr                 // Restore PAR_EL1 from the stack
+       msr     par_el1, x0
        tbnz    x3, #0, 3f              // Bail out if we failed the translation
        ubfx    x3, x3, #12, #36        // Extract IPA
        lsl     x3, x3, #4              // and present it like HPFAR
index 9492360..02e9d09 100644 (file)
@@ -211,6 +211,9 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        /* FAR_EL1 */
        { Op0(0b11), Op1(0b000), CRn(0b0110), CRm(0b0000), Op2(0b000),
          NULL, reset_unknown, FAR_EL1 },
+       /* PAR_EL1 */
+       { Op0(0b11), Op1(0b000), CRn(0b0111), CRm(0b0100), Op2(0b000),
+         NULL, reset_unknown, PAR_EL1 },
 
        /* PMINTENSET_EL1 */
        { Op0(0b11), Op1(0b000), CRn(0b1001), CRm(0b1110), Op2(0b001),
index e773659..46048d2 100644 (file)
@@ -803,6 +803,32 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
                                dec_insn.next_pc_inc;
                return 1;
                break;
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+       case lwc2_op: /* This is bbit0 on Octeon */
+               if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt)) == 0)
+                       *contpc = regs->cp0_epc + 4 + (insn.i_format.simmediate << 2);
+               else
+                       *contpc = regs->cp0_epc + 8;
+               return 1;
+       case ldc2_op: /* This is bbit032 on Octeon */
+               if ((regs->regs[insn.i_format.rs] & (1ull<<(insn.i_format.rt + 32))) == 0)
+                       *contpc = regs->cp0_epc + 4 + (insn.i_format.simmediate << 2);
+               else
+                       *contpc = regs->cp0_epc + 8;
+               return 1;
+       case swc2_op: /* This is bbit1 on Octeon */
+               if (regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt))
+                       *contpc = regs->cp0_epc + 4 + (insn.i_format.simmediate << 2);
+               else
+                       *contpc = regs->cp0_epc + 8;
+               return 1;
+       case sdc2_op: /* This is bbit132 on Octeon */
+               if (regs->regs[insn.i_format.rs] & (1ull<<(insn.i_format.rt + 32)))
+                       *contpc = regs->cp0_epc + 4 + (insn.i_format.simmediate << 2);
+               else
+                       *contpc = regs->cp0_epc + 8;
+               return 1;
+#endif
        case cop0_op:
        case cop1_op:
        case cop2_op:
index d306225..e3abfd4 100644 (file)
@@ -91,13 +91,11 @@ static struct cpuidle_driver cpuidle_driver = {
 
 int __init sh_mobile_setup_cpuidle(void)
 {
-       int ret;
-
        if (sh_mobile_sleep_supported & SUSP_SH_SF)
                cpuidle_driver.states[1].disabled = false;
 
        if (sh_mobile_sleep_supported & SUSP_SH_STANDBY)
                cpuidle_driver.states[2].disabled = false;
 
-       return cpuidle_register(&cpuidle_driver);
+       return cpuidle_register(&cpuidle_driver, NULL);
 }
index 653668d..4a8cb8d 100644 (file)
@@ -35,9 +35,9 @@ static void sanitize_boot_params(struct boot_params *boot_params)
         */
        if (boot_params->sentinel) {
                /* fields in boot_params are left uninitialized, clear them */
-               memset(&boot_params->olpc_ofw_header, 0,
+               memset(&boot_params->ext_ramdisk_image, 0,
                       (char *)&boot_params->efi_info -
-                       (char *)&boot_params->olpc_ofw_header);
+                       (char *)&boot_params->ext_ramdisk_image);
                memset(&boot_params->kbd_status, 0,
                       (char *)&boot_params->hdr -
                       (char *)&boot_params->kbd_status);
index 50e5c58..4c01917 100644 (file)
@@ -59,7 +59,7 @@ static inline u16 find_equiv_id(struct equiv_cpu_entry *equiv_cpu_table,
 
 extern int __apply_microcode_amd(struct microcode_amd *mc_amd);
 extern int apply_microcode_amd(int cpu);
-extern enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size);
+extern enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size);
 
 #ifdef CONFIG_MICROCODE_AMD_EARLY
 #ifdef CONFIG_X86_32
index f654ece..08a0890 100644 (file)
@@ -512,7 +512,7 @@ static void early_init_amd(struct cpuinfo_x86 *c)
 
 static const int amd_erratum_383[];
 static const int amd_erratum_400[];
-static bool cpu_has_amd_erratum(const int *erratum);
+static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum);
 
 static void init_amd(struct cpuinfo_x86 *c)
 {
@@ -729,11 +729,11 @@ static void init_amd(struct cpuinfo_x86 *c)
                value &= ~(1ULL << 24);
                wrmsrl_safe(MSR_AMD64_BU_CFG2, value);
 
-               if (cpu_has_amd_erratum(amd_erratum_383))
+               if (cpu_has_amd_erratum(c, amd_erratum_383))
                        set_cpu_bug(c, X86_BUG_AMD_TLB_MMATCH);
        }
 
-       if (cpu_has_amd_erratum(amd_erratum_400))
+       if (cpu_has_amd_erratum(c, amd_erratum_400))
                set_cpu_bug(c, X86_BUG_AMD_APIC_C1E);
 
        rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy);
@@ -878,23 +878,13 @@ static const int amd_erratum_400[] =
 static const int amd_erratum_383[] =
        AMD_OSVW_ERRATUM(3, AMD_MODEL_RANGE(0x10, 0, 0, 0xff, 0xf));
 
-static bool cpu_has_amd_erratum(const int *erratum)
+
+static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum)
 {
-       struct cpuinfo_x86 *cpu = __this_cpu_ptr(&cpu_info);
        int osvw_id = *erratum++;
        u32 range;
        u32 ms;
 
-       /*
-        * If called early enough that current_cpu_data hasn't been initialized
-        * yet, fall back to boot_cpu_data.
-        */
-       if (cpu->x86 == 0)
-               cpu = &boot_cpu_data;
-
-       if (cpu->x86_vendor != X86_VENDOR_AMD)
-               return false;
-
        if (osvw_id >= 0 && osvw_id < 65536 &&
            cpu_has(cpu, X86_FEATURE_OSVW)) {
                u64 osvw_len;
index 7a0adb7..7123b5d 100644 (file)
@@ -145,10 +145,9 @@ static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig)
        return 0;
 }
 
-static unsigned int verify_patch_size(int cpu, u32 patch_size,
+static unsigned int verify_patch_size(u8 family, u32 patch_size,
                                      unsigned int size)
 {
-       struct cpuinfo_x86 *c = &cpu_data(cpu);
        u32 max_size;
 
 #define F1XH_MPB_MAX_SIZE 2048
@@ -156,7 +155,7 @@ static unsigned int verify_patch_size(int cpu, u32 patch_size,
 #define F15H_MPB_MAX_SIZE 4096
 #define F16H_MPB_MAX_SIZE 3458
 
-       switch (c->x86) {
+       switch (family) {
        case 0x14:
                max_size = F14H_MPB_MAX_SIZE;
                break;
@@ -277,9 +276,8 @@ static void cleanup(void)
  * driver cannot continue functioning normally. In such cases, we tear
  * down everything we've used up so far and exit.
  */
-static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover)
+static int verify_and_add_patch(u8 family, u8 *fw, unsigned int leftover)
 {
-       struct cpuinfo_x86 *c = &cpu_data(cpu);
        struct microcode_header_amd *mc_hdr;
        struct ucode_patch *patch;
        unsigned int patch_size, crnt_size, ret;
@@ -299,7 +297,7 @@ static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover)
 
        /* check if patch is for the current family */
        proc_fam = ((proc_fam >> 8) & 0xf) + ((proc_fam >> 20) & 0xff);
-       if (proc_fam != c->x86)
+       if (proc_fam != family)
                return crnt_size;
 
        if (mc_hdr->nb_dev_id || mc_hdr->sb_dev_id) {
@@ -308,7 +306,7 @@ static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover)
                return crnt_size;
        }
 
-       ret = verify_patch_size(cpu, patch_size, leftover);
+       ret = verify_patch_size(family, patch_size, leftover);
        if (!ret) {
                pr_err("Patch-ID 0x%08x: size mismatch.\n", mc_hdr->patch_id);
                return crnt_size;
@@ -339,7 +337,8 @@ static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover)
        return crnt_size;
 }
 
-static enum ucode_state __load_microcode_amd(int cpu, const u8 *data, size_t size)
+static enum ucode_state __load_microcode_amd(u8 family, const u8 *data,
+                                            size_t size)
 {
        enum ucode_state ret = UCODE_ERROR;
        unsigned int leftover;
@@ -362,7 +361,7 @@ static enum ucode_state __load_microcode_amd(int cpu, const u8 *data, size_t siz
        }
 
        while (leftover) {
-               crnt_size = verify_and_add_patch(cpu, fw, leftover);
+               crnt_size = verify_and_add_patch(family, fw, leftover);
                if (crnt_size < 0)
                        return ret;
 
@@ -373,22 +372,22 @@ static enum ucode_state __load_microcode_amd(int cpu, const u8 *data, size_t siz
        return UCODE_OK;
 }
 
-enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size)
+enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size)
 {
        enum ucode_state ret;
 
        /* free old equiv table */
        free_equiv_cpu_table();
 
-       ret = __load_microcode_amd(cpu, data, size);
+       ret = __load_microcode_amd(family, data, size);
 
        if (ret != UCODE_OK)
                cleanup();
 
 #if defined(CONFIG_MICROCODE_AMD_EARLY) && defined(CONFIG_X86_32)
        /* save BSP's matching patch for early load */
-       if (cpu_data(cpu).cpu_index == boot_cpu_data.cpu_index) {
-               struct ucode_patch *p = find_patch(cpu);
+       if (cpu_data(smp_processor_id()).cpu_index == boot_cpu_data.cpu_index) {
+               struct ucode_patch *p = find_patch(smp_processor_id());
                if (p) {
                        memset(amd_bsp_mpb, 0, MPB_MAX_SIZE);
                        memcpy(amd_bsp_mpb, p->data, min_t(u32, ksize(p->data),
@@ -441,7 +440,7 @@ static enum ucode_state request_microcode_amd(int cpu, struct device *device,
                goto fw_release;
        }
 
-       ret = load_microcode_amd(cpu, fw->data, fw->size);
+       ret = load_microcode_amd(c->x86, fw->data, fw->size);
 
  fw_release:
        release_firmware(fw);
index 1d14ffe..6073104 100644 (file)
@@ -238,25 +238,17 @@ static void __init collect_cpu_sig_on_bsp(void *arg)
        uci->cpu_sig.sig = cpuid_eax(0x00000001);
 }
 #else
-static void collect_cpu_info_amd_early(struct cpuinfo_x86 *c,
-                                                struct ucode_cpu_info *uci)
+void load_ucode_amd_ap(void)
 {
+       unsigned int cpu = smp_processor_id();
+       struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
        u32 rev, eax;
 
        rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax);
        eax = cpuid_eax(0x00000001);
 
-       uci->cpu_sig.sig = eax;
        uci->cpu_sig.rev = rev;
-       c->microcode = rev;
-       c->x86 = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff);
-}
-
-void load_ucode_amd_ap(void)
-{
-       unsigned int cpu = smp_processor_id();
-
-       collect_cpu_info_amd_early(&cpu_data(cpu), ucode_cpu_info + cpu);
+       uci->cpu_sig.sig = eax;
 
        if (cpu && !ucode_loaded) {
                void *ucode;
@@ -265,8 +257,10 @@ void load_ucode_amd_ap(void)
                        return;
 
                ucode = (void *)(initrd_start + ucode_offset);
-               if (load_microcode_amd(0, ucode, ucode_size) != UCODE_OK)
+               eax   = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff);
+               if (load_microcode_amd(eax, ucode, ucode_size) != UCODE_OK)
                        return;
+
                ucode_loaded = true;
        }
 
@@ -278,6 +272,8 @@ int __init save_microcode_in_initrd_amd(void)
 {
        enum ucode_state ret;
        void *ucode;
+       u32 eax;
+
 #ifdef CONFIG_X86_32
        unsigned int bsp = boot_cpu_data.cpu_index;
        struct ucode_cpu_info *uci = ucode_cpu_info + bsp;
@@ -293,7 +289,10 @@ int __init save_microcode_in_initrd_amd(void)
                return 0;
 
        ucode = (void *)(initrd_start + ucode_offset);
-       ret = load_microcode_amd(0, ucode, ucode_size);
+       eax   = cpuid_eax(0x00000001);
+       eax   = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff);
+
+       ret = load_microcode_amd(eax, ucode, ucode_size);
        if (ret != UCODE_OK)
                return -EINVAL;
 
index 48f8375..30277e2 100644 (file)
@@ -101,7 +101,7 @@ static void find_start_end(unsigned long flags, unsigned long *begin,
                                *begin = new_begin;
                }
        } else {
-               *begin = mmap_legacy_base();
+               *begin = current->mm->mmap_legacy_base;
                *end = TASK_SIZE;
        }
 }
index addf7b5..91a4496 100644 (file)
@@ -301,6 +301,15 @@ static int tboot_sleep(u8 sleep_state, u32 pm1a_control, u32 pm1b_control)
        return 0;
 }
 
+static int tboot_extended_sleep(u8 sleep_state, u32 val_a, u32 val_b)
+{
+       if (!tboot_enabled())
+               return 0;
+
+       pr_warning("tboot is not able to suspend on platforms with reduced hardware sleep (ACPIv5)");
+       return -ENODEV;
+}
+
 static atomic_t ap_wfs_count;
 
 static int tboot_wait_for_aps(int num_aps)
@@ -422,6 +431,7 @@ static __init int tboot_late_init(void)
 #endif
 
        acpi_os_set_prepare_sleep(&tboot_sleep);
+       acpi_os_set_prepare_extended_sleep(&tboot_extended_sleep);
        return 0;
 }
 
index f63778c..25e7e13 100644 (file)
@@ -98,7 +98,7 @@ static unsigned long mmap_base(void)
  * Bottom-up (legacy) layout on X86_32 did not support randomization, X86_64
  * does, but not when emulating X86_32
  */
-unsigned long mmap_legacy_base(void)
+static unsigned long mmap_legacy_base(void)
 {
        if (mmap_is_ia32())
                return TASK_UNMAPPED_BASE;
@@ -112,11 +112,13 @@ unsigned long mmap_legacy_base(void)
  */
 void arch_pick_mmap_layout(struct mm_struct *mm)
 {
+       mm->mmap_legacy_base = mmap_legacy_base();
+       mm->mmap_base = mmap_base();
+
        if (mmap_is_legacy()) {
-               mm->mmap_base = mmap_legacy_base();
+               mm->mmap_base = mm->mmap_legacy_base;
                mm->get_unmapped_area = arch_get_unmapped_area;
        } else {
-               mm->mmap_base = mmap_base();
                mm->get_unmapped_area = arch_get_unmapped_area_topdown;
        }
 }
index cdd0da9..266ca91 100644 (file)
@@ -146,6 +146,7 @@ int __init
 acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
 {
        u64 start, end;
+       u32 hotpluggable;
        int node, pxm;
 
        if (srat_disabled())
@@ -154,7 +155,8 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
                goto out_err_bad_srat;
        if ((ma->flags & ACPI_SRAT_MEM_ENABLED) == 0)
                goto out_err;
-       if ((ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) && !save_add_info())
+       hotpluggable = ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE;
+       if (hotpluggable && !save_add_info())
                goto out_err;
 
        start = ma->base_address;
@@ -174,9 +176,10 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
 
        node_set(node, numa_nodes_parsed);
 
-       printk(KERN_INFO "SRAT: Node %u PXM %u [mem %#010Lx-%#010Lx]\n",
-              node, pxm,
-              (unsigned long long) start, (unsigned long long) end - 1);
+       pr_info("SRAT: Node %u PXM %u [mem %#010Lx-%#010Lx]%s\n",
+               node, pxm,
+               (unsigned long long) start, (unsigned long long) end - 1,
+               hotpluggable ? " hotplug" : "");
 
        return 0;
 out_err_bad_srat:
index 94919e3..db6b1ab 100644 (file)
@@ -210,6 +210,8 @@ static void pcibios_allocate_bridge_resources(struct pci_dev *dev)
                r = &dev->resource[idx];
                if (!r->flags)
                        continue;
+               if (r->parent)  /* Already allocated */
+                       continue;
                if (!r->start || pci_claim_resource(dev, idx) < 0) {
                        /*
                         * Something is wrong with the region.
@@ -318,6 +320,8 @@ static void pcibios_allocate_dev_rom_resource(struct pci_dev *dev)
        r = &dev->resource[PCI_ROM_RESOURCE];
        if (!r->flags || !r->start)
                return;
+       if (r->parent) /* Already allocated */
+               return;
 
        if (pci_claim_resource(dev, PCI_ROM_RESOURCE) < 0) {
                r->end -= r->start;
index 056d11f..8f3eea6 100644 (file)
@@ -313,6 +313,17 @@ static void xen_align_and_add_e820_region(u64 start, u64 size, int type)
        e820_add_region(start, end - start, type);
 }
 
+void xen_ignore_unusable(struct e820entry *list, size_t map_size)
+{
+       struct e820entry *entry;
+       unsigned int i;
+
+       for (i = 0, entry = list; i < map_size; i++, entry++) {
+               if (entry->type == E820_UNUSABLE)
+                       entry->type = E820_RAM;
+       }
+}
+
 /**
  * machine_specific_memory_setup - Hook for machine specific memory setup.
  **/
@@ -353,6 +364,17 @@ char * __init xen_memory_setup(void)
        }
        BUG_ON(rc);
 
+       /*
+        * Xen won't allow a 1:1 mapping to be created to UNUSABLE
+        * regions, so if we're using the machine memory map leave the
+        * region as RAM as it is in the pseudo-physical map.
+        *
+        * UNUSABLE regions in domUs are not handled and will need
+        * a patch in the future.
+        */
+       if (xen_initial_domain())
+               xen_ignore_unusable(map, memmap.nr_entries);
+
        /* Make sure the Xen-supplied memory map is well-ordered. */
        sanitize_e820_map(map, memmap.nr_entries, &memmap.nr_entries);
 
index ca92754..b81c88e 100644 (file)
@@ -694,8 +694,15 @@ static void __init xen_hvm_smp_prepare_cpus(unsigned int max_cpus)
 static int xen_hvm_cpu_up(unsigned int cpu, struct task_struct *tidle)
 {
        int rc;
-       rc = native_cpu_up(cpu, tidle);
-       WARN_ON (xen_smp_intr_init(cpu));
+       /*
+        * xen_smp_intr_init() needs to run before native_cpu_up()
+        * so that IPI vectors are set up on the booting CPU before
+        * it is marked online in native_cpu_up().
+       */
+       rc = xen_smp_intr_init(cpu);
+       WARN_ON(rc);
+       if (!rc)
+               rc =  native_cpu_up(cpu, tidle);
        return rc;
 }
 
index 100bd72..3278a21 100644 (file)
@@ -91,24 +91,6 @@ config ACPI_EC_DEBUGFS
          Thus this option is a debug option that helps to write ACPI drivers
          and can be used to identify ACPI code or EC firmware bugs.
 
-config ACPI_PROC_EVENT
-       bool "Deprecated /proc/acpi/event support"
-       depends on PROC_FS
-       default y
-       help
-         A user-space daemon, acpid, typically reads /proc/acpi/event
-         and handles all ACPI-generated events.
-
-         These events are now delivered to user-space either
-         via the input layer or as netlink events.
-
-         This build option enables the old code for legacy
-         user-space implementation.  After some time, this will
-         be moved under CONFIG_ACPI_PROCFS, and then deleted.
-
-         Say Y here to retain the old behaviour.  Say N if your
-         user-space is newer than kernel 2.6.23 (September 2007).
-
 config ACPI_AC
        tristate "AC Adapter"
        depends on X86
index 4f4e741..f37beaa 100644 (file)
@@ -267,7 +267,6 @@ static void acpi_ac_notify(struct acpi_device *device, u32 event)
                        msleep(ac_sleep_before_get_state_ms);
 
                acpi_ac_get_state(ac);
-               acpi_bus_generate_proc_event(device, event, (u32) ac->state);
                acpi_bus_generate_netlink_event(device->pnp.device_class,
                                                  dev_name(&device->dev), event,
                                                  (u32) ac->state);
index 27bb6a9..6230637 100644 (file)
@@ -452,7 +452,6 @@ static void acpi_pad_notify(acpi_handle handle, u32 event,
        switch (event) {
        case ACPI_PROCESSOR_AGGREGATOR_NOTIFY:
                acpi_pad_handle_notify(handle);
-               acpi_bus_generate_proc_event(device, event, 0);
                acpi_bus_generate_netlink_event(device->pnp.device_class,
                        dev_name(&device->dev), event, 0);
                break;
index fafec5d..1bde127 100644 (file)
@@ -52,7 +52,7 @@ int acpi_create_platform_device(struct acpi_device *adev,
        struct platform_device_info pdevinfo;
        struct resource_list_entry *rentry;
        struct list_head resource_list;
-       struct resource *resources;
+       struct resource *resources = NULL;
        int count;
 
        /* If the ACPI node already has a physical device attached, skip it. */
@@ -61,20 +61,22 @@ int acpi_create_platform_device(struct acpi_device *adev,
 
        INIT_LIST_HEAD(&resource_list);
        count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
-       if (count <= 0)
+       if (count < 0) {
                return 0;
+       } else if (count > 0) {
+               resources = kmalloc(count * sizeof(struct resource),
+                                   GFP_KERNEL);
+               if (!resources) {
+                       dev_err(&adev->dev, "No memory for resources\n");
+                       acpi_dev_free_resource_list(&resource_list);
+                       return -ENOMEM;
+               }
+               count = 0;
+               list_for_each_entry(rentry, &resource_list, node)
+                       resources[count++] = rentry->res;
 
-       resources = kmalloc(count * sizeof(struct resource), GFP_KERNEL);
-       if (!resources) {
-               dev_err(&adev->dev, "No memory for resources\n");
                acpi_dev_free_resource_list(&resource_list);
-               return -ENOMEM;
        }
-       count = 0;
-       list_for_each_entry(rentry, &resource_list, node)
-               resources[count++] = rentry->res;
-
-       acpi_dev_free_resource_list(&resource_list);
 
        memset(&pdevinfo, 0, sizeof(pdevinfo));
        /*
index 5a74a9c..f29e06e 100644 (file)
@@ -178,14 +178,17 @@ static int acpi_processor_hotadd_init(struct acpi_processor *pr)
        if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_PRESENT))
                return -ENODEV;
 
+       cpu_maps_update_begin();
+       cpu_hotplug_begin();
+
        ret = acpi_map_lsapic(pr->handle, &pr->id);
        if (ret)
-               return ret;
+               goto out;
 
        ret = arch_register_cpu(pr->id);
        if (ret) {
                acpi_unmap_lsapic(pr->id);
-               return ret;
+               goto out;
        }
 
        /*
@@ -195,7 +198,11 @@ static int acpi_processor_hotadd_init(struct acpi_processor *pr)
         */
        pr_info("CPU%d has been hot-added\n", pr->id);
        pr->flags.need_hotplug_init = 1;
-       return 0;
+
+out:
+       cpu_hotplug_done();
+       cpu_maps_update_done();
+       return ret;
 }
 #else
 static inline int acpi_processor_hotadd_init(struct acpi_processor *pr)
@@ -452,11 +459,15 @@ static void acpi_processor_remove(struct acpi_device *device)
        per_cpu(processor_device_array, pr->id) = NULL;
        per_cpu(processors, pr->id) = NULL;
 
+       cpu_maps_update_begin();
+       cpu_hotplug_begin();
+
        /* Remove the CPU. */
-       get_online_cpus();
        arch_unregister_cpu(pr->id);
        acpi_unmap_lsapic(pr->id);
-       put_online_cpus();
+
+       cpu_hotplug_done();
+       cpu_maps_update_done();
 
        try_offline_node(cpu_to_node(pr->id));
 
index b8d3811..90e846f 100644 (file)
@@ -138,6 +138,12 @@ u8 ACPI_INIT_GLOBAL(acpi_gbl_disable_auto_repair, FALSE);
  */
 u8 ACPI_INIT_GLOBAL(acpi_gbl_disable_ssdt_table_load, FALSE);
 
+/*
+ * We keep track of the latest version of Windows that has been requested by
+ * the BIOS.
+ */
+u8 ACPI_INIT_GLOBAL(acpi_gbl_osi_data, 0);
+
 /* acpi_gbl_FADT is a local copy of the FADT, converted to a common format. */
 
 struct acpi_table_fadt acpi_gbl_FADT;
@@ -285,7 +291,6 @@ ACPI_EXTERN u8 acpi_gbl_debugger_configuration;
 ACPI_EXTERN u8 acpi_gbl_step_to_next_call;
 ACPI_EXTERN u8 acpi_gbl_acpi_hardware_present;
 ACPI_EXTERN u8 acpi_gbl_events_initialized;
-ACPI_EXTERN u8 acpi_gbl_osi_data;
 ACPI_EXTERN struct acpi_interface_info *acpi_gbl_supported_interfaces;
 ACPI_EXTERN struct acpi_address_range
     *acpi_gbl_address_range_list[ACPI_ADDRESS_RANGE_MAX];
index d4a4901..0ed0066 100644 (file)
@@ -942,6 +942,9 @@ struct acpi_interface_info {
 
 #define ACPI_OSI_INVALID                0x01
 #define ACPI_OSI_DYNAMIC                0x02
+#define ACPI_OSI_FEATURE                0x04
+#define ACPI_OSI_DEFAULT_INVALID        0x08
+#define ACPI_OSI_OPTIONAL_FEATURE       (ACPI_OSI_FEATURE | ACPI_OSI_DEFAULT_INVALID | ACPI_OSI_INVALID)
 
 struct acpi_port_info {
        char *name;
@@ -1030,6 +1033,7 @@ struct acpi_external_list {
        u8 type;
        u8 flags;
        u8 resolved;
+       u8 emitted;
 };
 
 /* Values for Flags field above */
index b83dc32..40b04bd 100644 (file)
@@ -104,8 +104,8 @@ acpi_ns_walk_namespace(acpi_object_type type,
                       acpi_handle start_object,
                       u32 max_depth,
                       u32 flags,
-                      acpi_walk_callback pre_order_visit,
-                      acpi_walk_callback post_order_visit,
+                      acpi_walk_callback descending_callback,
+                      acpi_walk_callback ascending_callback,
                       void *context, void **return_value);
 
 struct acpi_namespace_node *acpi_ns_get_next_node(struct acpi_namespace_node
index 7755e91..c54f42c 100644 (file)
 
 acpi_status acpi_allocate_root_table(u32 initial_table_count);
 
+/*
+ * tbxfroot - Root pointer utilities
+ */
+acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp);
+
+u8 *acpi_tb_scan_memory_for_rsdp(u8 *start_address, u32 length);
+
 /*
  * tbfadt - FADT parse/convert/validate
  */
index 3c76ede..d5a62a6 100644 (file)
@@ -470,6 +470,8 @@ acpi_status acpi_ut_install_interface(acpi_string interface_name);
 
 acpi_status acpi_ut_remove_interface(acpi_string interface_name);
 
+acpi_status acpi_ut_update_interfaces(u8 action);
+
 struct acpi_interface_info *acpi_ut_get_interface(acpi_string interface_name);
 
 acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state);
@@ -616,7 +618,7 @@ int acpi_ut_stricmp(char *string1, char *string2);
 
 acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer);
 
-void acpi_ut_print_string(char *string, u8 max_length);
+void acpi_ut_print_string(char *string, u16 max_length);
 
 void ut_convert_backslashes(char *pathname);
 
index 9037f17..7842700 100644 (file)
@@ -125,7 +125,6 @@ acpi_status acpi_ev_gpe_initialize(void)
                /* GPE block 0 exists (has both length and address > 0) */
 
                register_count0 = (u16)(acpi_gbl_FADT.gpe0_block_length / 2);
-
                gpe_number_max =
                    (register_count0 * ACPI_GPE_REGISTER_WIDTH) - 1;
 
@@ -204,16 +203,6 @@ acpi_status acpi_ev_gpe_initialize(void)
                goto cleanup;
        }
 
-       /* Check for Max GPE number out-of-range */
-
-       if (gpe_number_max > ACPI_GPE_MAX) {
-               ACPI_ERROR((AE_INFO,
-                           "Maximum GPE number from FADT is too large: 0x%X",
-                           gpe_number_max));
-               status = AE_BAD_VALUE;
-               goto cleanup;
-       }
-
       cleanup:
        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
        return_ACPI_STATUS(AE_OK);
index c740f24..4d046fa 100644 (file)
@@ -338,6 +338,7 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc,
 {
        u8 *target;
        char *name;
+       const char *reference_name;
        u8 count;
 
        if (!info) {
@@ -426,10 +427,9 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc,
 
                case ACPI_EXD_REFERENCE:
 
+                       reference_name = acpi_ut_get_reference_name(obj_desc);
                        acpi_ex_out_string("Class Name",
-                                          ACPI_CAST_PTR(char,
-                                                        acpi_ut_get_reference_name
-                                                        (obj_desc)));
+                                          ACPI_CAST_PTR(char, reference_name));
                        acpi_ex_dump_reference_obj(obj_desc);
                        break;
 
index 814b4a3..2cdd41d 100644 (file)
@@ -962,10 +962,17 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
                                         */
                                        return_desc =
                                            *(operand[0]->reference.where);
-                                       if (return_desc) {
-                                               acpi_ut_add_reference
-                                                   (return_desc);
+                                       if (!return_desc) {
+                                               /*
+                                                * Element is NULL, do not allow the dereference.
+                                                * This provides compatibility with other ACPI
+                                                * implementations.
+                                                */
+                                               return_ACPI_STATUS
+                                                   (AE_AML_UNINITIALIZED_ELEMENT);
                                        }
+
+                                       acpi_ut_add_reference(return_desc);
                                        break;
 
                                default:
@@ -990,11 +997,40 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
                                                                         acpi_namespace_node
                                                                         *)
                                                                        return_desc);
-                               }
+                                       if (!return_desc) {
+                                               break;
+                                       }
 
-                               /* Add another reference to the object! */
+                                       /*
+                                        * June 2013:
+                                        * buffer_fields/field_units require additional resolution
+                                        */
+                                       switch (return_desc->common.type) {
+                                       case ACPI_TYPE_BUFFER_FIELD:
+                                       case ACPI_TYPE_LOCAL_REGION_FIELD:
+                                       case ACPI_TYPE_LOCAL_BANK_FIELD:
+                                       case ACPI_TYPE_LOCAL_INDEX_FIELD:
 
-                               acpi_ut_add_reference(return_desc);
+                                               status =
+                                                   acpi_ex_read_data_from_field
+                                                   (walk_state, return_desc,
+                                                    &temp_desc);
+                                               if (ACPI_FAILURE(status)) {
+                                                       goto cleanup;
+                                               }
+
+                                               return_desc = temp_desc;
+                                               break;
+
+                                       default:
+
+                                               /* Add another reference to the object */
+
+                                               acpi_ut_add_reference
+                                                   (return_desc);
+                                               break;
+                                       }
+                               }
                                break;
 
                        default:
index 5e5f762..4140768 100644 (file)
@@ -43,6 +43,7 @@
  */
 
 #include <acpi/acpi.h>
+#include <linux/acpi.h>
 #include "accommon.h"
 
 #define _COMPONENT          ACPI_HARDWARE
@@ -128,6 +129,14 @@ acpi_status acpi_hw_extended_sleep(u8 sleep_state)
 
        ACPI_FLUSH_CPU_CACHE();
 
+       status = acpi_os_prepare_extended_sleep(sleep_state,
+                                               acpi_gbl_sleep_type_a,
+                                               acpi_gbl_sleep_type_b);
+       if (ACPI_SKIP(status))
+               return_ACPI_STATUS(AE_OK);
+       if (ACPI_FAILURE(status))
+               return_ACPI_STATUS(status);
+
        /*
         * Set the SLP_TYP and SLP_EN bits.
         *
index 0c1a8bb..2d7d22e 100644 (file)
@@ -100,8 +100,13 @@ acpi_status acpi_get_timer(u32 * ticks)
                return_ACPI_STATUS(AE_BAD_PARAMETER);
        }
 
-       status = acpi_hw_read(ticks, &acpi_gbl_FADT.xpm_timer_block);
+       /* ACPI 5.0A: PM Timer is optional */
+
+       if (!acpi_gbl_FADT.xpm_timer_block.address) {
+               return_ACPI_STATUS(AE_SUPPORT);
+       }
 
+       status = acpi_hw_read(ticks, &acpi_gbl_FADT.xpm_timer_block);
        return_ACPI_STATUS(status);
 }
 
@@ -148,6 +153,12 @@ acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 * time_elapsed)
                return_ACPI_STATUS(AE_BAD_PARAMETER);
        }
 
+       /* ACPI 5.0A: PM Timer is optional */
+
+       if (!acpi_gbl_FADT.xpm_timer_block.address) {
+               return_ACPI_STATUS(AE_SUPPORT);
+       }
+
        /*
         * Compute Tick Delta:
         * Handle (max one) timer rollovers on 24-bit versus 32-bit timers.
index 24b71a0..098e766 100644 (file)
@@ -150,6 +150,15 @@ acpi_ns_check_return_value(struct acpi_namespace_node *node,
                goto exit;
        }
 
+       /*
+        *
+        * 4) If there is no return value and it is optional, just return
+        * AE_OK (_WAK).
+        */
+       if (!(*return_object_ptr)) {
+               goto exit;
+       }
+
        /*
         * For returned Package objects, check the type of all sub-objects.
         * Note: Package may have been newly created by call above.
@@ -268,7 +277,12 @@ acpi_ns_check_object_type(struct acpi_evaluate_info *info,
 
        acpi_ut_get_expected_return_types(type_buffer, expected_btypes);
 
-       if (package_index == ACPI_NOT_PACKAGE_ELEMENT) {
+       if (!return_object) {
+               ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
+                                     info->node_flags,
+                                     "Expected return object of type %s",
+                                     type_buffer));
+       } else if (package_index == ACPI_NOT_PACKAGE_ELEMENT) {
                ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
                                      info->node_flags,
                                      "Return type mismatch - found %s, expected %s",
index e70911a..e81f15e 100644 (file)
@@ -156,9 +156,9 @@ struct acpi_namespace_node *acpi_ns_get_next_node_typed(acpi_object_type type,
  *              max_depth           - Depth to which search is to reach
  *              flags               - Whether to unlock the NS before invoking
  *                                    the callback routine
- *              pre_order_visit     - Called during tree pre-order visit
+ *              descending_callback - Called during tree descent
  *                                    when an object of "Type" is found
- *              post_order_visit    - Called during tree post-order visit
+ *              ascending_callback  - Called during tree ascent
  *                                    when an object of "Type" is found
  *              context             - Passed to user function(s) above
  *              return_value        - from the user_function if terminated
@@ -185,8 +185,8 @@ acpi_ns_walk_namespace(acpi_object_type type,
                       acpi_handle start_node,
                       u32 max_depth,
                       u32 flags,
-                      acpi_walk_callback pre_order_visit,
-                      acpi_walk_callback post_order_visit,
+                      acpi_walk_callback descending_callback,
+                      acpi_walk_callback ascending_callback,
                       void *context, void **return_value)
 {
        acpi_status status;
@@ -255,22 +255,22 @@ acpi_ns_walk_namespace(acpi_object_type type,
                        }
 
                        /*
-                        * Invoke the user function, either pre-order or post-order
+                        * Invoke the user function, either descending, ascending,
                         * or both.
                         */
                        if (!node_previously_visited) {
-                               if (pre_order_visit) {
+                               if (descending_callback) {
                                        status =
-                                           pre_order_visit(child_node, level,
-                                                           context,
-                                                           return_value);
+                                           descending_callback(child_node,
+                                                               level, context,
+                                                               return_value);
                                }
                        } else {
-                               if (post_order_visit) {
+                               if (ascending_callback) {
                                        status =
-                                           post_order_visit(child_node, level,
-                                                            context,
-                                                            return_value);
+                                           ascending_callback(child_node,
+                                                              level, context,
+                                                              return_value);
                                }
                        }
 
index f553cfd..b38b4b0 100644 (file)
@@ -533,9 +533,9 @@ static void acpi_ns_resolve_references(struct acpi_evaluate_info *info)
  * PARAMETERS:  type                - acpi_object_type to search for
  *              start_object        - Handle in namespace where search begins
  *              max_depth           - Depth to which search is to reach
- *              pre_order_visit     - Called during tree pre-order visit
+ *              descending_callback - Called during tree descent
  *                                    when an object of "Type" is found
- *              post_order_visit    - Called during tree post-order visit
+ *              ascending_callback  - Called during tree ascent
  *                                    when an object of "Type" is found
  *              context             - Passed to user function(s) above
  *              return_value        - Location where return value of
@@ -563,8 +563,8 @@ acpi_status
 acpi_walk_namespace(acpi_object_type type,
                    acpi_handle start_object,
                    u32 max_depth,
-                   acpi_walk_callback pre_order_visit,
-                   acpi_walk_callback post_order_visit,
+                   acpi_walk_callback descending_callback,
+                   acpi_walk_callback ascending_callback,
                    void *context, void **return_value)
 {
        acpi_status status;
@@ -574,7 +574,7 @@ acpi_walk_namespace(acpi_object_type type,
        /* Parameter validation */
 
        if ((type > ACPI_TYPE_LOCAL_MAX) ||
-           (!max_depth) || (!pre_order_visit && !post_order_visit)) {
+           (!max_depth) || (!descending_callback && !ascending_callback)) {
                return_ACPI_STATUS(AE_BAD_PARAMETER);
        }
 
@@ -606,9 +606,9 @@ acpi_walk_namespace(acpi_object_type type,
        }
 
        status = acpi_ns_walk_namespace(type, start_object, max_depth,
-                                       ACPI_NS_WALK_UNLOCK, pre_order_visit,
-                                       post_order_visit, context,
-                                       return_value);
+                                       ACPI_NS_WALK_UNLOCK,
+                                       descending_callback, ascending_callback,
+                                       context, return_value);
 
        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 
index f3a4d95..83c1644 100644 (file)
@@ -158,6 +158,7 @@ acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer)
 {
        acpi_status status;
        struct acpi_namespace_node *node;
+       char *node_name;
 
        /* Parameter validation */
 
@@ -202,7 +203,8 @@ acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer)
 
        /* Just copy the ACPI name from the Node and zero terminate it */
 
-       ACPI_MOVE_NAME(buffer->pointer, acpi_ut_get_node_name(node));
+       node_name = acpi_ut_get_node_name(node);
+       ACPI_MOVE_NAME(buffer->pointer, node_name);
        ((char *)buffer->pointer)[ACPI_NAME_SIZE] = 0;
        status = AE_OK;
 
@@ -379,9 +381,14 @@ acpi_get_object_info(acpi_handle handle,
                 * Get extra info for ACPI Device/Processor objects only:
                 * Run the _STA, _ADR and, sx_w, and _sx_d methods.
                 *
-                * Note: none of these methods are required, so they may or may
+                * Notes: none of these methods are required, so they may or may
                 * not be present for this device. The Info->Valid bitfield is used
                 * to indicate which methods were found and run successfully.
+                *
+                * For _STA, if the method does not exist, then (as per the ACPI
+                * specification), the returned current_status flags will indicate
+                * that the device is present/functional/enabled. Otherwise, the
+                * current_status flags reflect the value returned from _STA.
                 */
 
                /* Execute the Device._STA method */
index 33b00d2..9d99f21 100644 (file)
@@ -117,7 +117,7 @@ static struct acpi_fadt_info fadt_info_table[] = {
         ACPI_FADT_OFFSET(pm_timer_block),
         ACPI_FADT_OFFSET(pm_timer_length),
         ACPI_PM_TIMER_WIDTH,
-        ACPI_FADT_REQUIRED},
+        ACPI_FADT_SEPARATE_LENGTH},    /* ACPI 5.0A: Timer is optional */
 
        {"Gpe0Block",
         ACPI_FADT_OFFSET(xgpe0_block),
@@ -574,7 +574,7 @@ static void acpi_tb_validate_fadt(void)
 
                if (fadt_info_table[i].type & ACPI_FADT_REQUIRED) {
                        /*
-                        * Field is required (Pm1a_event, Pm1a_control, pm_timer).
+                        * Field is required (Pm1a_event, Pm1a_control).
                         * Both the address and length must be non-zero.
                         */
                        if (!address64->address || !length) {
index 7c2ecfb..948c95e 100644 (file)
 #define _COMPONENT          ACPI_TABLES
 ACPI_MODULE_NAME("tbxfroot")
 
-/* Local prototypes */
-static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length);
-
-static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp);
-
 /*******************************************************************************
  *
  * FUNCTION:    acpi_tb_validate_rsdp
@@ -64,8 +59,7 @@ static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp);
  * DESCRIPTION: Validate the RSDP (ptr)
  *
  ******************************************************************************/
-
-static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp)
+acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp)
 {
 
        /*
@@ -74,7 +68,7 @@ static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp)
         * Note: Sometimes there exists more than one RSDP in memory; the valid
         * RSDP has a valid checksum, all others have an invalid checksum.
         */
-       if (ACPI_STRNCMP((char *)rsdp, ACPI_SIG_RSDP,
+       if (ACPI_STRNCMP((char *)rsdp->signature, ACPI_SIG_RSDP,
                         sizeof(ACPI_SIG_RSDP) - 1) != 0) {
 
                /* Nope, BAD Signature */
@@ -231,7 +225,7 @@ acpi_status acpi_find_root_pointer(acpi_size *table_address)
  * DESCRIPTION: Search a block of memory for the RSDP signature
  *
  ******************************************************************************/
-static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length)
+u8 *acpi_tb_scan_memory_for_rsdp(u8 *start_address, u32 length)
 {
        acpi_status status;
        u8 *mem_rover;
index ee83adb..4fd6897 100644 (file)
@@ -239,7 +239,8 @@ acpi_ut_evaluate_numeric_object(char *object_name,
  * RETURN:      Status
  *
  * DESCRIPTION: Executes _STA for selected device and stores results in
- *              *Flags.
+ *              *Flags. If _STA does not exist, then the device is assumed
+ *              to be present/functional/enabled (as per the ACPI spec).
  *
  *              NOTE: Internal function, no parameter validation
  *
@@ -257,6 +258,11 @@ acpi_ut_execute_STA(struct acpi_namespace_node *device_node, u32 * flags)
                                         ACPI_BTYPE_INTEGER, &obj_desc);
        if (ACPI_FAILURE(status)) {
                if (AE_NOT_FOUND == status) {
+                       /*
+                        * if _STA does not exist, then (as per the ACPI specification),
+                        * the returned flags will indicate that the device is present,
+                        * functional, and enabled.
+                        */
                        ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
                                          "_STA on %4.4s was not found, assuming device is present\n",
                                          acpi_ut_get_node_name(device_node)));
index f736448..d6f26bf 100644 (file)
@@ -336,7 +336,6 @@ acpi_status acpi_ut_init_globals(void)
        acpi_gbl_trace_dbg_layer = 0;
        acpi_gbl_debugger_configuration = DEBUGGER_THREADING;
        acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT;
-       acpi_gbl_osi_data = 0;
        acpi_gbl_osi_mutex = NULL;
        acpi_gbl_reg_methods_executed = FALSE;
 
index 7e80772..8856bd3 100644 (file)
@@ -77,21 +77,20 @@ static struct acpi_interface_info acpi_default_supported_interfaces[] = {
 
        /* Feature Group Strings */
 
-       {"Extended Address Space Descriptor", NULL, 0, 0}
+       {"Extended Address Space Descriptor", NULL, ACPI_OSI_FEATURE, 0},
 
        /*
         * All "optional" feature group strings (features that are implemented
-        * by the host) should be dynamically added by the host via
-        * acpi_install_interface and should not be manually added here.
-        *
-        * Examples of optional feature group strings:
-        *
-        * "Module Device"
-        * "Processor Device"
-        * "3.0 Thermal Model"
-        * "3.0 _SCP Extensions"
-        * "Processor Aggregator Device"
+        * by the host) should be dynamically modified to VALID by the host via
+        * acpi_install_interface or acpi_update_interfaces. Such optional feature
+        * group strings are set as INVALID by default here.
         */
+
+       {"Module Device", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0},
+       {"Processor Device", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0},
+       {"3.0 Thermal Model", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0},
+       {"3.0 _SCP Extensions", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0},
+       {"Processor Aggregator Device", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0}
 };
 
 /*******************************************************************************
@@ -158,11 +157,20 @@ acpi_status acpi_ut_interface_terminate(void)
        while (next_interface) {
                acpi_gbl_supported_interfaces = next_interface->next;
 
-               /* Only interfaces added at runtime can be freed */
-
                if (next_interface->flags & ACPI_OSI_DYNAMIC) {
+
+                       /* Only interfaces added at runtime can be freed */
+
                        ACPI_FREE(next_interface->name);
                        ACPI_FREE(next_interface);
+               } else {
+                       /* Interface is in static list. Reset it to invalid or valid. */
+
+                       if (next_interface->flags & ACPI_OSI_DEFAULT_INVALID) {
+                               next_interface->flags |= ACPI_OSI_INVALID;
+                       } else {
+                               next_interface->flags &= ~ACPI_OSI_INVALID;
+                       }
                }
 
                next_interface = acpi_gbl_supported_interfaces;
@@ -276,6 +284,49 @@ acpi_status acpi_ut_remove_interface(acpi_string interface_name)
        return (AE_NOT_EXIST);
 }
 
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_update_interfaces
+ *
+ * PARAMETERS:  action              - Actions to be performed during the
+ *                                    update
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Update _OSI interface strings, disabling or enabling OS vendor
+ *              strings or/and feature group strings.
+ *              Caller MUST hold acpi_gbl_osi_mutex
+ *
+ ******************************************************************************/
+
+acpi_status acpi_ut_update_interfaces(u8 action)
+{
+       struct acpi_interface_info *next_interface;
+
+       next_interface = acpi_gbl_supported_interfaces;
+       while (next_interface) {
+               if (((next_interface->flags & ACPI_OSI_FEATURE) &&
+                    (action & ACPI_FEATURE_STRINGS)) ||
+                   (!(next_interface->flags & ACPI_OSI_FEATURE) &&
+                    (action & ACPI_VENDOR_STRINGS))) {
+                       if (action & ACPI_DISABLE_INTERFACES) {
+
+                               /* Mark the interfaces as invalid */
+
+                               next_interface->flags |= ACPI_OSI_INVALID;
+                       } else {
+                               /* Mark the interfaces as valid */
+
+                               next_interface->flags &= ~ACPI_OSI_INVALID;
+                       }
+               }
+
+               next_interface = next_interface->next;
+       }
+
+       return (AE_OK);
+}
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ut_get_interface
index c53759b..cb1e9cc 100644 (file)
@@ -333,7 +333,8 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer)
  * FUNCTION:    acpi_ut_print_string
  *
  * PARAMETERS:  string          - Null terminated ASCII string
- *              max_length      - Maximum output length
+ *              max_length      - Maximum output length. Used to constrain the
+ *                                length of strings during debug output only.
  *
  * RETURN:      None
  *
@@ -342,7 +343,7 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer)
  *
  ******************************************************************************/
 
-void acpi_ut_print_string(char *string, u8 max_length)
+void acpi_ut_print_string(char *string, u16 max_length)
 {
        u32 i;
 
index 6505774..03a211e 100644 (file)
@@ -387,6 +387,34 @@ acpi_status acpi_install_interface_handler(acpi_interface_handler handler)
 
 ACPI_EXPORT_SYMBOL(acpi_install_interface_handler)
 
+/*****************************************************************************
+ *
+ * FUNCTION:    acpi_update_interfaces
+ *
+ * PARAMETERS:  action              - Actions to be performed during the
+ *                                    update
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Update _OSI interface strings, disabling or enabling OS vendor
+ *              string or/and feature group strings.
+ *
+ ****************************************************************************/
+acpi_status acpi_update_interfaces(u8 action)
+{
+       acpi_status status;
+
+       status = acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
+       if (ACPI_FAILURE(status)) {
+               return (status);
+       }
+
+       status = acpi_ut_update_interfaces(action);
+
+       acpi_os_release_mutex(acpi_gbl_osi_mutex);
+       return (status);
+}
+
 /*****************************************************************************
  *
  * FUNCTION:    acpi_check_address_range
@@ -402,6 +430,7 @@ ACPI_EXPORT_SYMBOL(acpi_install_interface_handler)
  *              ASL operation region address ranges.
  *
  ****************************************************************************/
+
 u32
 acpi_check_address_range(acpi_adr_space_type space_id,
                         acpi_physical_address address,
index d405fba..2c9958c 100644 (file)
@@ -527,18 +527,14 @@ static int acpi_battery_get_state(struct acpi_battery *battery)
 static int acpi_battery_set_alarm(struct acpi_battery *battery)
 {
        acpi_status status = 0;
-       union acpi_object arg0 = { .type = ACPI_TYPE_INTEGER };
-       struct acpi_object_list arg_list = { 1, &arg0 };
 
        if (!acpi_battery_present(battery) ||
            !test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags))
                return -ENODEV;
 
-       arg0.integer.value = battery->alarm;
-
        mutex_lock(&battery->lock);
-       status = acpi_evaluate_object(battery->device->handle, "_BTP",
-                                &arg_list, NULL);
+       status = acpi_execute_simple_method(battery->device->handle, "_BTP",
+                                           battery->alarm);
        mutex_unlock(&battery->lock);
 
        if (ACPI_FAILURE(status))
@@ -550,12 +546,8 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery)
 
 static int acpi_battery_init_alarm(struct acpi_battery *battery)
 {
-       acpi_status status = AE_OK;
-       acpi_handle handle = NULL;
-
        /* See if alarms are supported, and if so, set default */
-       status = acpi_get_handle(battery->device->handle, "_BTP", &handle);
-       if (ACPI_FAILURE(status)) {
+       if (!acpi_has_method(battery->device->handle, "_BTP")) {
                clear_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags);
                return 0;
        }
@@ -1036,8 +1028,6 @@ static void acpi_battery_notify(struct acpi_device *device, u32 event)
        if (event == ACPI_BATTERY_NOTIFY_INFO)
                acpi_battery_refresh(battery);
        acpi_battery_update(battery);
-       acpi_bus_generate_proc_event(device, event,
-                                    acpi_battery_present(battery));
        acpi_bus_generate_netlink_event(device->pnp.device_class,
                                        dev_name(&device->dev), event,
                                        acpi_battery_present(battery));
@@ -1068,7 +1058,7 @@ static int acpi_battery_add(struct acpi_device *device)
 {
        int result = 0;
        struct acpi_battery *battery = NULL;
-       acpi_handle handle;
+
        if (!device)
                return -EINVAL;
        battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL);
@@ -1080,8 +1070,7 @@ static int acpi_battery_add(struct acpi_device *device)
        device->driver_data = battery;
        mutex_init(&battery->lock);
        mutex_init(&battery->sysfs_lock);
-       if (ACPI_SUCCESS(acpi_get_handle(battery->device->handle,
-                       "_BIX", &handle)))
+       if (acpi_has_method(battery->device->handle, "_BIX"))
                set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
        result = acpi_battery_update(battery);
        if (result)
index cb96296..9515f18 100644 (file)
@@ -192,6 +192,12 @@ static int __init dmi_disable_osi_win7(const struct dmi_system_id *d)
        acpi_osi_setup("!Windows 2009");
        return 0;
 }
+static int __init dmi_disable_osi_win8(const struct dmi_system_id *d)
+{
+       printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident);
+       acpi_osi_setup("!Windows 2012");
+       return 0;
+}
 
 static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
        {
@@ -267,6 +273,30 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
                     DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P305D"),
                },
        },
+       {
+       .callback = dmi_disable_osi_win8,
+       .ident = "ASUS Zenbook Prime UX31A",
+       .matches = {
+                    DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                    DMI_MATCH(DMI_PRODUCT_NAME, "UX31A"),
+               },
+       },
+       {
+       .callback = dmi_disable_osi_win8,
+       .ident = "Dell Inspiron 15R SE",
+       .matches = {
+                    DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                    DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7520"),
+               },
+       },
+       {
+       .callback = dmi_disable_osi_win8,
+       .ident = "Lenovo ThinkPad Edge E530",
+       .matches = {
+                    DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                    DMI_MATCH(DMI_PRODUCT_VERSION, "3259A2G"),
+               },
+       },
 
        /*
         * BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
index a5bb33b..b587ec8 100644 (file)
@@ -89,27 +89,6 @@ static struct dmi_system_id dsdt_dmi_table[] __initdata = {
                                 Device Management
    -------------------------------------------------------------------------- */
 
-int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device)
-{
-       acpi_status status;
-
-       if (!device)
-               return -EINVAL;
-
-       /* TBD: Support fixed-feature devices */
-
-       status = acpi_get_data(handle, acpi_bus_data_handler, (void **)device);
-       if (ACPI_FAILURE(status) || !*device) {
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n",
-                                 handle));
-               return -ENODEV;
-       }
-
-       return 0;
-}
-
-EXPORT_SYMBOL(acpi_bus_get_device);
-
 acpi_status acpi_bus_get_status_handle(acpi_handle handle,
                                       unsigned long long *sta)
 {
@@ -345,104 +324,6 @@ static void acpi_bus_osc_support(void)
        /* do we need to check other returned cap? Sounds no */
 }
 
-/* --------------------------------------------------------------------------
-                                Event Management
-   -------------------------------------------------------------------------- */
-
-#ifdef CONFIG_ACPI_PROC_EVENT
-static DEFINE_SPINLOCK(acpi_bus_event_lock);
-
-LIST_HEAD(acpi_bus_event_list);
-DECLARE_WAIT_QUEUE_HEAD(acpi_bus_event_queue);
-
-extern int event_is_open;
-
-int acpi_bus_generate_proc_event4(const char *device_class, const char *bus_id, u8 type, int data)
-{
-       struct acpi_bus_event *event;
-       unsigned long flags;
-
-       /* drop event on the floor if no one's listening */
-       if (!event_is_open)
-               return 0;
-
-       event = kzalloc(sizeof(struct acpi_bus_event), GFP_ATOMIC);
-       if (!event)
-               return -ENOMEM;
-
-       strcpy(event->device_class, device_class);
-       strcpy(event->bus_id, bus_id);
-       event->type = type;
-       event->data = data;
-
-       spin_lock_irqsave(&acpi_bus_event_lock, flags);
-       list_add_tail(&event->node, &acpi_bus_event_list);
-       spin_unlock_irqrestore(&acpi_bus_event_lock, flags);
-
-       wake_up_interruptible(&acpi_bus_event_queue);
-
-       return 0;
-
-}
-
-EXPORT_SYMBOL_GPL(acpi_bus_generate_proc_event4);
-
-int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
-{
-       if (!device)
-               return -EINVAL;
-       return acpi_bus_generate_proc_event4(device->pnp.device_class,
-                                            device->pnp.bus_id, type, data);
-}
-
-EXPORT_SYMBOL(acpi_bus_generate_proc_event);
-
-int acpi_bus_receive_event(struct acpi_bus_event *event)
-{
-       unsigned long flags;
-       struct acpi_bus_event *entry = NULL;
-
-       DECLARE_WAITQUEUE(wait, current);
-
-
-       if (!event)
-               return -EINVAL;
-
-       if (list_empty(&acpi_bus_event_list)) {
-
-               set_current_state(TASK_INTERRUPTIBLE);
-               add_wait_queue(&acpi_bus_event_queue, &wait);
-
-               if (list_empty(&acpi_bus_event_list))
-                       schedule();
-
-               remove_wait_queue(&acpi_bus_event_queue, &wait);
-               set_current_state(TASK_RUNNING);
-
-               if (signal_pending(current))
-                       return -ERESTARTSYS;
-       }
-
-       spin_lock_irqsave(&acpi_bus_event_lock, flags);
-       if (!list_empty(&acpi_bus_event_list)) {
-               entry = list_entry(acpi_bus_event_list.next,
-                                  struct acpi_bus_event, node);
-               list_del(&entry->node);
-       }
-       spin_unlock_irqrestore(&acpi_bus_event_lock, flags);
-
-       if (!entry)
-               return -ENODEV;
-
-       memcpy(event, entry, sizeof(struct acpi_bus_event));
-
-       kfree(entry);
-
-       return 0;
-}
-
-#endif /* CONFIG_ACPI_PROC_EVENT */
-
 /* --------------------------------------------------------------------------
                              Notification Handling
    -------------------------------------------------------------------------- */
@@ -499,19 +380,6 @@ static void acpi_bus_check_scope(acpi_handle handle)
         */
 }
 
-static BLOCKING_NOTIFIER_HEAD(acpi_bus_notify_list);
-int register_acpi_bus_notifier(struct notifier_block *nb)
-{
-       return blocking_notifier_chain_register(&acpi_bus_notify_list, nb);
-}
-EXPORT_SYMBOL_GPL(register_acpi_bus_notifier);
-
-void unregister_acpi_bus_notifier(struct notifier_block *nb)
-{
-       blocking_notifier_chain_unregister(&acpi_bus_notify_list, nb);
-}
-EXPORT_SYMBOL_GPL(unregister_acpi_bus_notifier);
-
 /**
  * acpi_bus_notify
  * ---------------
@@ -525,9 +393,6 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Notification %#02x to handle %p\n",
                          type, handle));
 
-       blocking_notifier_call_chain(&acpi_bus_notify_list,
-               type, (void *)handle);
-
        switch (type) {
 
        case ACPI_NOTIFY_BUS_CHECK:
@@ -593,8 +458,6 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
 static int __init acpi_bus_init_irq(void)
 {
        acpi_status status;
-       union acpi_object arg = { ACPI_TYPE_INTEGER };
-       struct acpi_object_list arg_list = { 1, &arg };
        char *message = NULL;
 
 
@@ -623,9 +486,7 @@ static int __init acpi_bus_init_irq(void)
 
        printk(KERN_INFO PREFIX "Using %s for interrupt routing\n", message);
 
-       arg.integer.value = acpi_irq_model;
-
-       status = acpi_evaluate_object(NULL, "\\_PIC", &arg_list, NULL);
+       status = acpi_execute_simple_method(NULL, "\\_PIC", acpi_irq_model);
        if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
                ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PIC"));
                return -ENODEV;
@@ -715,7 +576,6 @@ static int __init acpi_bus_init(void)
 {
        int result;
        acpi_status status;
-       extern acpi_status acpi_os_initialize1(void);
 
        acpi_os_initialize1();
 
index d2e617b..a557738 100644 (file)
@@ -303,8 +303,6 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
 
                        pm_wakeup_event(&device->dev, 0);
                }
-
-               acpi_bus_generate_proc_event(device, event, ++button->pushed);
                break;
        default:
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
index 4ab807d..59d3202 100644 (file)
@@ -159,26 +159,29 @@ int acpi_device_set_power(struct acpi_device *device, int state)
        int result = 0;
        bool cut_power = false;
 
-       if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3_COLD))
+       if (!device || !device->flags.power_manageable
+           || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3_COLD))
                return -EINVAL;
 
        /* Make sure this is a valid target state */
 
        if (state == device->power.state) {
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at %s\n",
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] already in %s\n",
+                                 device->pnp.bus_id,
                                  acpi_power_state_string(state)));
                return 0;
        }
 
        if (!device->power.states[state].flags.valid) {
-               printk(KERN_WARNING PREFIX "Device does not support %s\n",
-                      acpi_power_state_string(state));
+               dev_warn(&device->dev, "Power state %s not supported\n",
+                        acpi_power_state_string(state));
                return -ENODEV;
        }
        if (device->parent && (state < device->parent->power.state)) {
-               printk(KERN_WARNING PREFIX
-                             "Cannot set device to a higher-powered"
-                             " state than parent\n");
+               dev_warn(&device->dev,
+                        "Cannot transition to power state %s for parent in %s\n",
+                        acpi_power_state_string(state),
+                        acpi_power_state_string(device->parent->power.state));
                return -ENODEV;
        }
 
@@ -191,8 +194,8 @@ int acpi_device_set_power(struct acpi_device *device, int state)
 
        if (state < device->power.state && state != ACPI_STATE_D0
            && device->power.state >= ACPI_STATE_D3_HOT) {
-               printk(KERN_WARNING PREFIX
-                       "Cannot transition to non-D0 state from D3\n");
+               dev_warn(&device->dev,
+                        "Cannot transition to non-D0 state from D3\n");
                return -ENODEV;
        }
 
@@ -219,10 +222,8 @@ int acpi_device_set_power(struct acpi_device *device, int state)
 
  end:
        if (result) {
-               printk(KERN_WARNING PREFIX
-                             "Device [%s] failed to transition to %s\n",
-                             device->pnp.bus_id,
-                             acpi_power_state_string(state));
+               dev_warn(&device->dev, "Failed to change power state to %s\n",
+                        acpi_power_state_string(state));
        } else {
                device->power.state = state;
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
@@ -244,13 +245,6 @@ int acpi_bus_set_power(acpi_handle handle, int state)
        if (result)
                return result;
 
-       if (!device->flags.power_manageable) {
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                               "Device [%s] is not power manageable\n",
-                               dev_name(&device->dev)));
-               return -ENODEV;
-       }
-
        return acpi_device_set_power(device, state);
 }
 EXPORT_SYMBOL(acpi_bus_set_power);
index 8265607..05ea4be 100644 (file)
@@ -51,8 +51,6 @@ MODULE_PARM_DESC(immediate_undock, "1 (default) will cause the driver to "
        " the driver to wait for userspace to write the undock sysfs file "
        " before undocking");
 
-static struct atomic_notifier_head dock_notifier_list;
-
 static const struct acpi_device_id dock_device_ids[] = {
        {"LNXDOCK", 0},
        {"", 0},
@@ -63,8 +61,6 @@ struct dock_station {
        acpi_handle handle;
        unsigned long last_dock_time;
        u32 flags;
-       spinlock_t dd_lock;
-       struct mutex hp_lock;
        struct list_head dependent_devices;
 
        struct list_head sibling;
@@ -91,6 +87,12 @@ struct dock_dependent_device {
 #define DOCK_EVENT     3
 #define UNDOCK_EVENT   2
 
+enum dock_callback_type {
+       DOCK_CALL_HANDLER,
+       DOCK_CALL_FIXUP,
+       DOCK_CALL_UEVENT,
+};
+
 /*****************************************************************************
  *                         Dock Dependent device functions                   *
  *****************************************************************************/
@@ -101,7 +103,7 @@ struct dock_dependent_device {
  *
  * Add the dependent device to the dock's dependent device list.
  */
-static int
+static int __init
 add_dock_dependent_device(struct dock_station *ds, acpi_handle handle)
 {
        struct dock_dependent_device *dd;
@@ -112,14 +114,21 @@ add_dock_dependent_device(struct dock_station *ds, acpi_handle handle)
 
        dd->handle = handle;
        INIT_LIST_HEAD(&dd->list);
-
-       spin_lock(&ds->dd_lock);
        list_add_tail(&dd->list, &ds->dependent_devices);
-       spin_unlock(&ds->dd_lock);
 
        return 0;
 }
 
+static void remove_dock_dependent_devices(struct dock_station *ds)
+{
+       struct dock_dependent_device *dd, *aux;
+
+       list_for_each_entry_safe(dd, aux, &ds->dependent_devices, list) {
+               list_del(&dd->list);
+               kfree(dd);
+       }
+}
+
 /**
  * dock_init_hotplug - Initialize a hotplug device on a docking station.
  * @dd: Dock-dependent device.
@@ -135,19 +144,16 @@ static int dock_init_hotplug(struct dock_dependent_device *dd,
        int ret = 0;
 
        mutex_lock(&hotplug_lock);
-
-       if (dd->hp_context) {
+       if (WARN_ON(dd->hp_context)) {
                ret = -EEXIST;
        } else {
                dd->hp_refcount = 1;
                dd->hp_ops = ops;
                dd->hp_context = context;
                dd->hp_release = release;
+               if (init)
+                       init(context);
        }
-
-       if (!WARN_ON(ret) && init)
-               init(context);
-
        mutex_unlock(&hotplug_lock);
        return ret;
 }
@@ -162,27 +168,22 @@ static int dock_init_hotplug(struct dock_dependent_device *dd,
  */
 static void dock_release_hotplug(struct dock_dependent_device *dd)
 {
-       void (*release)(void *) = NULL;
-       void *context = NULL;
-
        mutex_lock(&hotplug_lock);
-
        if (dd->hp_context && !--dd->hp_refcount) {
+               void (*release)(void *) = dd->hp_release;
+               void *context = dd->hp_context;
+
                dd->hp_ops = NULL;
-               context = dd->hp_context;
                dd->hp_context = NULL;
-               release = dd->hp_release;
                dd->hp_release = NULL;
+               if (release)
+                       release(context);
        }
-
-       if (release && context)
-               release(context);
-
        mutex_unlock(&hotplug_lock);
 }
 
 static void dock_hotplug_event(struct dock_dependent_device *dd, u32 event,
-                              bool uevent)
+                              enum dock_callback_type cb_type)
 {
        acpi_notify_handler cb = NULL;
        bool run = false;
@@ -192,8 +193,18 @@ static void dock_hotplug_event(struct dock_dependent_device *dd, u32 event,
        if (dd->hp_context) {
                run = true;
                dd->hp_refcount++;
-               if (dd->hp_ops)
-                       cb = uevent ? dd->hp_ops->uevent : dd->hp_ops->handler;
+               if (dd->hp_ops) {
+                       switch (cb_type) {
+                       case DOCK_CALL_FIXUP:
+                               cb = dd->hp_ops->fixup;
+                               break;
+                       case DOCK_CALL_UEVENT:
+                               cb = dd->hp_ops->uevent;
+                               break;
+                       default:
+                               cb = dd->hp_ops->handler;
+                       }
+               }
        }
 
        mutex_unlock(&hotplug_lock);
@@ -220,63 +231,17 @@ find_dock_dependent_device(struct dock_station *ds, acpi_handle handle)
 {
        struct dock_dependent_device *dd;
 
-       spin_lock(&ds->dd_lock);
-       list_for_each_entry(dd, &ds->dependent_devices, list) {
-               if (handle == dd->handle) {
-                       spin_unlock(&ds->dd_lock);
+       list_for_each_entry(dd, &ds->dependent_devices, list)
+               if (handle == dd->handle)
                        return dd;
-               }
-       }
-       spin_unlock(&ds->dd_lock);
+
        return NULL;
 }
 
 /*****************************************************************************
  *                         Dock functions                                    *
  *****************************************************************************/
-/**
- * is_dock - see if a device is a dock station
- * @handle: acpi handle of the device
- *
- * If an acpi object has a _DCK method, then it is by definition a dock
- * station, so return true.
- */
-static int is_dock(acpi_handle handle)
-{
-       acpi_status status;
-       acpi_handle tmp;
-
-       status = acpi_get_handle(handle, "_DCK", &tmp);
-       if (ACPI_FAILURE(status))
-               return 0;
-       return 1;
-}
-
-static int is_ejectable(acpi_handle handle)
-{
-       acpi_status status;
-       acpi_handle tmp;
-
-       status = acpi_get_handle(handle, "_EJ0", &tmp);
-       if (ACPI_FAILURE(status))
-               return 0;
-       return 1;
-}
-
-static int is_ata(acpi_handle handle)
-{
-       acpi_handle tmp;
-
-       if ((ACPI_SUCCESS(acpi_get_handle(handle, "_GTF", &tmp))) ||
-          (ACPI_SUCCESS(acpi_get_handle(handle, "_GTM", &tmp))) ||
-          (ACPI_SUCCESS(acpi_get_handle(handle, "_STM", &tmp))) ||
-          (ACPI_SUCCESS(acpi_get_handle(handle, "_SDD", &tmp))))
-               return 1;
-
-       return 0;
-}
-
-static int is_battery(acpi_handle handle)
+static int __init is_battery(acpi_handle handle)
 {
        struct acpi_device_info *info;
        int ret = 1;
@@ -292,17 +257,13 @@ static int is_battery(acpi_handle handle)
        return ret;
 }
 
-static int is_ejectable_bay(acpi_handle handle)
+/* Check whether ACPI object is an ejectable battery or disk bay */
+static bool __init is_ejectable_bay(acpi_handle handle)
 {
-       acpi_handle phandle;
+       if (acpi_has_method(handle, "_EJ0") && is_battery(handle))
+               return true;
 
-       if (!is_ejectable(handle))
-               return 0;
-       if (is_battery(handle) || is_ata(handle))
-               return 1;
-       if (!acpi_get_parent(handle, &phandle) && is_ata(phandle))
-               return 1;
-       return 0;
+       return acpi_bay_match(handle);
 }
 
 /**
@@ -320,7 +281,7 @@ int is_dock_device(acpi_handle handle)
        if (!dock_station_count)
                return 0;
 
-       if (is_dock(handle))
+       if (acpi_dock_match(handle))
                return 1;
 
        list_for_each_entry(dock_station, &dock_stations, sibling)
@@ -359,10 +320,8 @@ static int dock_present(struct dock_station *ds)
  *  handle if one does not exist already.  This should cause
  *  acpi to scan for drivers for the given devices, and call
  *  matching driver's add routine.
- *
- *  Returns a pointer to the acpi_device corresponding to the handle.
  */
-static struct acpi_device * dock_create_acpi_device(acpi_handle handle)
+static void dock_create_acpi_device(acpi_handle handle)
 {
        struct acpi_device *device;
        int ret;
@@ -375,10 +334,7 @@ static struct acpi_device * dock_create_acpi_device(acpi_handle handle)
                ret = acpi_bus_scan(handle);
                if (ret)
                        pr_debug("error adding bus, %x\n", -ret);
-
-               acpi_bus_get_device(handle, &device);
        }
-       return device;
 }
 
 /**
@@ -397,9 +353,29 @@ static void dock_remove_acpi_device(acpi_handle handle)
 }
 
 /**
- * hotplug_dock_devices - insert or remove devices on the dock station
+ * hot_remove_dock_devices - Remove dock station devices.
+ * @ds: Dock station.
+ */
+static void hot_remove_dock_devices(struct dock_station *ds)
+{
+       struct dock_dependent_device *dd;
+
+       /*
+        * Walk the list in reverse order so that devices that have been added
+        * last are removed first (in case there are some indirect dependencies
+        * between them).
+        */
+       list_for_each_entry_reverse(dd, &ds->dependent_devices, list)
+               dock_hotplug_event(dd, ACPI_NOTIFY_EJECT_REQUEST, false);
+
+       list_for_each_entry_reverse(dd, &ds->dependent_devices, list)
+               dock_remove_acpi_device(dd->handle);
+}
+
+/**
+ * hotplug_dock_devices - Insert devices on a dock station.
  * @ds: the dock station
- * @event: either bus check or eject request
+ * @event: either bus check or device check request
  *
  * Some devices on the dock station need to have drivers called
  * to perform hotplug operations after a dock event has occurred.
@@ -410,27 +386,21 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event)
 {
        struct dock_dependent_device *dd;
 
-       mutex_lock(&ds->hp_lock);
+       /* Call driver specific post-dock fixups. */
+       list_for_each_entry(dd, &ds->dependent_devices, list)
+               dock_hotplug_event(dd, event, DOCK_CALL_FIXUP);
 
-       /*
-        * First call driver specific hotplug functions
-        */
+       /* Call driver specific hotplug functions. */
        list_for_each_entry(dd, &ds->dependent_devices, list)
-               dock_hotplug_event(dd, event, false);
+               dock_hotplug_event(dd, event, DOCK_CALL_HANDLER);
 
        /*
-        * Now make sure that an acpi_device is created for each
-        * dependent device, or removed if this is an eject request.
-        * This will cause acpi_drivers to be stopped/started if they
-        * exist
+        * Now make sure that an acpi_device is created for each dependent
+        * device.  That will cause scan handlers to be attached to device
+        * objects or acpi_drivers to be stopped/started if they are present.
         */
-       list_for_each_entry(dd, &ds->dependent_devices, list) {
-               if (event == ACPI_NOTIFY_EJECT_REQUEST)
-                       dock_remove_acpi_device(dd->handle);
-               else
-                       dock_create_acpi_device(dd->handle);
-       }
-       mutex_unlock(&ds->hp_lock);
+       list_for_each_entry(dd, &ds->dependent_devices, list)
+               dock_create_acpi_device(dd->handle);
 }
 
 static void dock_event(struct dock_station *ds, u32 event, int num)
@@ -453,43 +423,12 @@ static void dock_event(struct dock_station *ds, u32 event, int num)
                kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
 
        list_for_each_entry(dd, &ds->dependent_devices, list)
-               dock_hotplug_event(dd, event, true);
+               dock_hotplug_event(dd, event, DOCK_CALL_UEVENT);
 
        if (num != DOCK_EVENT)
                kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
 }
 
-/**
- * eject_dock - respond to a dock eject request
- * @ds: the dock station
- *
- * This is called after _DCK is called, to execute the dock station's
- * _EJ0 method.
- */
-static void eject_dock(struct dock_station *ds)
-{
-       struct acpi_object_list arg_list;
-       union acpi_object arg;
-       acpi_status status;
-       acpi_handle tmp;
-
-       /* all dock devices should have _EJ0, but check anyway */
-       status = acpi_get_handle(ds->handle, "_EJ0", &tmp);
-       if (ACPI_FAILURE(status)) {
-               pr_debug("No _EJ0 support for dock device\n");
-               return;
-       }
-
-       arg_list.count = 1;
-       arg_list.pointer = &arg;
-       arg.type = ACPI_TYPE_INTEGER;
-       arg.integer.value = 1;
-
-       status = acpi_evaluate_object(ds->handle, "_EJ0", &arg_list, NULL);
-       if (ACPI_FAILURE(status))
-               pr_debug("Failed to evaluate _EJ0!\n");
-}
-
 /**
  * handle_dock - handle a dock event
  * @ds: the dock station
@@ -550,27 +489,6 @@ static inline void complete_undock(struct dock_station *ds)
        ds->flags &= ~(DOCK_UNDOCKING);
 }
 
-static void dock_lock(struct dock_station *ds, int lock)
-{
-       struct acpi_object_list arg_list;
-       union acpi_object arg;
-       acpi_status status;
-
-       arg_list.count = 1;
-       arg_list.pointer = &arg;
-       arg.type = ACPI_TYPE_INTEGER;
-       arg.integer.value = !!lock;
-       status = acpi_evaluate_object(ds->handle, "_LCK", &arg_list, NULL);
-       if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
-               if (lock)
-                       acpi_handle_warn(ds->handle,
-                               "Locking device failed (0x%x)\n", status);
-               else
-                       acpi_handle_warn(ds->handle,
-                               "Unlocking device failed (0x%x)\n", status);
-       }
-}
-
 /**
  * dock_in_progress - see if we are in the middle of handling a dock event
  * @ds: the dock station
@@ -587,37 +505,6 @@ static int dock_in_progress(struct dock_station *ds)
        return 0;
 }
 
-/**
- * register_dock_notifier - add yourself to the dock notifier list
- * @nb: the callers notifier block
- *
- * If a driver wishes to be notified about dock events, they can
- * use this function to put a notifier block on the dock notifier list.
- * this notifier call chain will be called after a dock event, but
- * before hotplugging any new devices.
- */
-int register_dock_notifier(struct notifier_block *nb)
-{
-       if (!dock_station_count)
-               return -ENODEV;
-
-       return atomic_notifier_chain_register(&dock_notifier_list, nb);
-}
-EXPORT_SYMBOL_GPL(register_dock_notifier);
-
-/**
- * unregister_dock_notifier - remove yourself from the dock notifier list
- * @nb: the callers notifier block
- */
-void unregister_dock_notifier(struct notifier_block *nb)
-{
-       if (!dock_station_count)
-               return;
-
-       atomic_notifier_chain_unregister(&dock_notifier_list, nb);
-}
-EXPORT_SYMBOL_GPL(unregister_dock_notifier);
-
 /**
  * register_hotplug_dock_device - register a hotplug function
  * @handle: the handle of the device
@@ -703,10 +590,10 @@ static int handle_eject_request(struct dock_station *ds, u32 event)
         */
        dock_event(ds, event, UNDOCK_EVENT);
 
-       hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST);
+       hot_remove_dock_devices(ds);
        undock(ds);
-       dock_lock(ds, 0);
-       eject_dock(ds);
+       acpi_evaluate_lck(ds->handle, 0);
+       acpi_evaluate_ej0(ds->handle);
        if (dock_present(ds)) {
                acpi_handle_err(ds->handle, "Unable to undock!\n");
                return -EBUSY;
@@ -717,18 +604,17 @@ static int handle_eject_request(struct dock_station *ds, u32 event)
 
 /**
  * dock_notify - act upon an acpi dock notification
- * @handle: the dock station handle
+ * @ds: dock station
  * @event: the acpi event
- * @data: our driver data struct
  *
  * If we are notified to dock, then check to see if the dock is
  * present and then dock.  Notify all drivers of the dock event,
  * and then hotplug and devices that may need hotplugging.
  */
-static void dock_notify(acpi_handle handle, u32 event, void *data)
+static void dock_notify(struct dock_station *ds, u32 event)
 {
-       struct dock_station *ds = data;
-       struct acpi_device *tmp;
+       acpi_handle handle = ds->handle;
+       struct acpi_device *ad;
        int surprise_removal = 0;
 
        /*
@@ -751,8 +637,7 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
        switch (event) {
        case ACPI_NOTIFY_BUS_CHECK:
        case ACPI_NOTIFY_DEVICE_CHECK:
-               if (!dock_in_progress(ds) && acpi_bus_get_device(ds->handle,
-                  &tmp)) {
+               if (!dock_in_progress(ds) && acpi_bus_get_device(handle, &ad)) {
                        begin_dock(ds);
                        dock(ds);
                        if (!dock_present(ds)) {
@@ -760,12 +645,10 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
                                complete_dock(ds);
                                break;
                        }
-                       atomic_notifier_call_chain(&dock_notifier_list,
-                                                  event, NULL);
                        hotplug_dock_devices(ds, event);
                        complete_dock(ds);
                        dock_event(ds, event, DOCK_EVENT);
-                       dock_lock(ds, 1);
+                       acpi_evaluate_lck(ds->handle, 1);
                        acpi_update_all_gpes();
                        break;
                }
@@ -789,9 +672,8 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
 }
 
 struct dock_data {
-       acpi_handle handle;
-       unsigned long event;
        struct dock_station *ds;
+       u32 event;
 };
 
 static void acpi_dock_deferred_cb(void *context)
@@ -799,52 +681,31 @@ static void acpi_dock_deferred_cb(void *context)
        struct dock_data *data = context;
 
        acpi_scan_lock_acquire();
-       dock_notify(data->handle, data->event, data->ds);
+       dock_notify(data->ds, data->event);
        acpi_scan_lock_release();
        kfree(data);
 }
 
-static int acpi_dock_notifier_call(struct notifier_block *this,
-       unsigned long event, void *data)
+static void dock_notify_handler(acpi_handle handle, u32 event, void *data)
 {
-       struct dock_station *dock_station;
-       acpi_handle handle = data;
+       struct dock_data *dd;
 
        if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK
           && event != ACPI_NOTIFY_EJECT_REQUEST)
-               return 0;
-
-       acpi_scan_lock_acquire();
-
-       list_for_each_entry(dock_station, &dock_stations, sibling) {
-               if (dock_station->handle == handle) {
-                       struct dock_data *dd;
-                       acpi_status status;
-
-                       dd = kmalloc(sizeof(*dd), GFP_KERNEL);
-                       if (!dd)
-                               break;
+               return;
 
-                       dd->handle = handle;
-                       dd->event = event;
-                       dd->ds = dock_station;
-                       status = acpi_os_hotplug_execute(acpi_dock_deferred_cb,
-                                                        dd);
-                       if (ACPI_FAILURE(status))
-                               kfree(dd);
+       dd = kmalloc(sizeof(*dd), GFP_KERNEL);
+       if (dd) {
+               acpi_status status;
 
-                       break;
-               }
+               dd->ds = data;
+               dd->event = event;
+               status = acpi_os_hotplug_execute(acpi_dock_deferred_cb, dd);
+               if (ACPI_FAILURE(status))
+                       kfree(dd);
        }
-
-       acpi_scan_lock_release();
-       return 0;
 }
 
-static struct notifier_block dock_acpi_notifier = {
-       .notifier_call = acpi_dock_notifier_call,
-};
-
 /**
  * find_dock_devices - find devices on the dock station
  * @handle: the handle of the device we are examining
@@ -856,29 +717,16 @@ static struct notifier_block dock_acpi_notifier = {
  * check to see if an object has an _EJD method.  If it does, then it
  * will see if it is dependent on the dock station.
  */
-static acpi_status
-find_dock_devices(acpi_handle handle, u32 lvl, void *context, void **rv)
+static acpi_status __init find_dock_devices(acpi_handle handle, u32 lvl,
+                                           void *context, void **rv)
 {
-       acpi_status status;
-       acpi_handle tmp, parent;
        struct dock_station *ds = context;
+       acpi_handle ejd = NULL;
 
-       status = acpi_bus_get_ejd(handle, &tmp);
-       if (ACPI_FAILURE(status)) {
-               /* try the parent device as well */
-               status = acpi_get_parent(handle, &parent);
-               if (ACPI_FAILURE(status))
-                       goto fdd_out;
-               /* see if parent is dependent on dock */
-               status = acpi_bus_get_ejd(parent, &tmp);
-               if (ACPI_FAILURE(status))
-                       goto fdd_out;
-       }
-
-       if (tmp == ds->handle)
+       acpi_bus_get_ejd(handle, &ejd);
+       if (ejd == ds->handle)
                add_dock_dependent_device(ds, handle);
 
-fdd_out:
        return AE_OK;
 }
 
@@ -988,13 +836,13 @@ static struct attribute_group dock_attribute_group = {
  */
 static int __init dock_add(acpi_handle handle)
 {
-       int ret, id;
-       struct dock_station ds, *dock_station;
+       struct dock_station *dock_station, ds = { NULL, };
        struct platform_device *dd;
+       acpi_status status;
+       int ret;
 
-       id = dock_station_count;
-       memset(&ds, 0, sizeof(ds));
-       dd = platform_device_register_data(NULL, "dock", id, &ds, sizeof(ds));
+       dd = platform_device_register_data(NULL, "dock", dock_station_count,
+                                          &ds, sizeof(ds));
        if (IS_ERR(dd))
                return PTR_ERR(dd);
 
@@ -1004,18 +852,15 @@ static int __init dock_add(acpi_handle handle)
        dock_station->dock_device = dd;
        dock_station->last_dock_time = jiffies - HZ;
 
-       mutex_init(&dock_station->hp_lock);
-       spin_lock_init(&dock_station->dd_lock);
        INIT_LIST_HEAD(&dock_station->sibling);
-       ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list);
        INIT_LIST_HEAD(&dock_station->dependent_devices);
 
        /* we want the dock device to send uevents */
        dev_set_uevent_suppress(&dd->dev, 0);
 
-       if (is_dock(handle))
+       if (acpi_dock_match(handle))
                dock_station->flags |= DOCK_IS_DOCK;
-       if (is_ata(handle))
+       if (acpi_ata_match(handle))
                dock_station->flags |= DOCK_IS_ATA;
        if (is_battery(handle))
                dock_station->flags |= DOCK_IS_BAT;
@@ -1034,11 +879,19 @@ static int __init dock_add(acpi_handle handle)
        if (ret)
                goto err_rmgroup;
 
+       status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+                                            dock_notify_handler, dock_station);
+       if (ACPI_FAILURE(status)) {
+               ret = -ENODEV;
+               goto err_rmgroup;
+       }
+
        dock_station_count++;
        list_add(&dock_station->sibling, &dock_stations);
        return 0;
 
 err_rmgroup:
+       remove_dock_dependent_devices(dock_station);
        sysfs_remove_group(&dd->dev.kobj, &dock_attribute_group);
 err_unregister:
        platform_device_unregister(dd);
@@ -1055,10 +908,10 @@ err_unregister:
  *
  * This is called by acpi_walk_namespace to look for dock stations and bays.
  */
-static __init acpi_status
+static acpi_status __init
 find_dock_and_bay(acpi_handle handle, u32 lvl, void *context, void **rv)
 {
-       if (is_dock(handle) || is_ejectable_bay(handle))
+       if (acpi_dock_match(handle) || is_ejectable_bay(handle))
                dock_add(handle);
 
        return AE_OK;
@@ -1078,7 +931,6 @@ void __init acpi_dock_init(void)
                return;
        }
 
-       register_acpi_bus_notifier(&dock_acpi_notifier);
        pr_info(PREFIX "%s: %d docks/bays found\n",
                ACPI_DOCK_DRIVER_DESCRIPTION, dock_station_count);
 }
index 80403c1..8dd2d4d 100644 (file)
@@ -948,7 +948,7 @@ static int ec_enlarge_storm_threshold(const struct dmi_system_id *id)
        return 0;
 }
 
-static struct dmi_system_id __initdata ec_dmi_table[] = {
+static struct dmi_system_id ec_dmi_table[] __initdata = {
        {
        ec_skip_dsdt_scan, "Compal JFL92", {
        DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"),
@@ -1049,10 +1049,8 @@ int __init acpi_ec_ecdt_probe(void)
                * which needs it, has fake EC._INI method, so use it as flag.
                * Keep boot_ec struct as it will be needed soon.
                */
-               acpi_handle dummy;
                if (!dmi_name_in_vendors("ASUS") ||
-                   ACPI_FAILURE(acpi_get_handle(boot_ec->handle, "_INI",
-                                                       &dummy)))
+                   !acpi_has_method(boot_ec->handle, "_INI"))
                        return -ENODEV;
        }
 install:
index 1442737..8247fcd 100644 (file)
 #define _COMPONENT             ACPI_SYSTEM_COMPONENT
 ACPI_MODULE_NAME("event");
 
-#ifdef CONFIG_ACPI_PROC_EVENT
-/* Global vars for handling event proc entry */
-static DEFINE_SPINLOCK(acpi_system_event_lock);
-int event_is_open = 0;
-extern struct list_head acpi_bus_event_list;
-extern wait_queue_head_t acpi_bus_event_queue;
-
-static int acpi_system_open_event(struct inode *inode, struct file *file)
-{
-       spin_lock_irq(&acpi_system_event_lock);
-
-       if (event_is_open)
-               goto out_busy;
-
-       event_is_open = 1;
-
-       spin_unlock_irq(&acpi_system_event_lock);
-       return 0;
-
-      out_busy:
-       spin_unlock_irq(&acpi_system_event_lock);
-       return -EBUSY;
-}
-
-static ssize_t
-acpi_system_read_event(struct file *file, char __user * buffer, size_t count,
-                      loff_t * ppos)
-{
-       int result = 0;
-       struct acpi_bus_event event;
-       static char str[ACPI_MAX_STRING];
-       static int chars_remaining = 0;
-       static char *ptr;
-
-       if (!chars_remaining) {
-               memset(&event, 0, sizeof(struct acpi_bus_event));
-
-               if ((file->f_flags & O_NONBLOCK)
-                   && (list_empty(&acpi_bus_event_list)))
-                       return -EAGAIN;
-
-               result = acpi_bus_receive_event(&event);
-               if (result)
-                       return result;
-
-               chars_remaining = sprintf(str, "%s %s %08x %08x\n",
-                                         event.device_class ? event.
-                                         device_class : "<unknown>",
-                                         event.bus_id ? event.
-                                         bus_id : "<unknown>", event.type,
-                                         event.data);
-               ptr = str;
-       }
-
-       if (chars_remaining < count) {
-               count = chars_remaining;
-       }
-
-       if (copy_to_user(buffer, ptr, count))
-               return -EFAULT;
-
-       *ppos += count;
-       chars_remaining -= count;
-       ptr += count;
-
-       return count;
-}
-
-static int acpi_system_close_event(struct inode *inode, struct file *file)
-{
-       spin_lock_irq(&acpi_system_event_lock);
-       event_is_open = 0;
-       spin_unlock_irq(&acpi_system_event_lock);
-       return 0;
-}
-
-static unsigned int acpi_system_poll_event(struct file *file, poll_table * wait)
-{
-       poll_wait(file, &acpi_bus_event_queue, wait);
-       if (!list_empty(&acpi_bus_event_list))
-               return POLLIN | POLLRDNORM;
-       return 0;
-}
-
-static const struct file_operations acpi_system_event_ops = {
-       .owner = THIS_MODULE,
-       .open = acpi_system_open_event,
-       .read = acpi_system_read_event,
-       .release = acpi_system_close_event,
-       .poll = acpi_system_poll_event,
-       .llseek = default_llseek,
-};
-#endif /* CONFIG_ACPI_PROC_EVENT */
-
 /* ACPI notifier chain */
 static BLOCKING_NOTIFIER_HEAD(acpi_chain_head);
 
@@ -280,9 +186,6 @@ static int acpi_event_genetlink_init(void)
 
 static int __init acpi_event_init(void)
 {
-#ifdef CONFIG_ACPI_PROC_EVENT
-       struct proc_dir_entry *entry;
-#endif
        int error = 0;
 
        if (acpi_disabled)
@@ -293,15 +196,6 @@ static int __init acpi_event_init(void)
        if (error)
                printk(KERN_WARNING PREFIX
                       "Failed to create genetlink family for ACPI event\n");
-
-#ifdef CONFIG_ACPI_PROC_EVENT
-       /* 'event' [R] */
-       entry = proc_create("event", S_IRUSR, acpi_root_dir,
-                           &acpi_system_event_ops);
-       if (!entry)
-               return -ENODEV;
-#endif
-
        return 0;
 }
 
index 5b02a0a..41ade65 100644 (file)
@@ -93,7 +93,7 @@ static int fan_get_cur_state(struct thermal_cooling_device *cdev, unsigned long
        if (result)
                return result;
 
-       *state = (acpi_state == ACPI_STATE_D3 ? 0 :
+       *state = (acpi_state == ACPI_STATE_D3_COLD ? 0 :
                 (acpi_state == ACPI_STATE_D0 ? 1 : -1));
        return 0;
 }
@@ -108,7 +108,7 @@ fan_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state)
                return -EINVAL;
 
        result = acpi_bus_set_power(device->handle,
-                               state ? ACPI_STATE_D0 : ACPI_STATE_D3);
+                               state ? ACPI_STATE_D0 : ACPI_STATE_D3_COLD);
 
        return result;
 }
index 408f6b2..9467229 100644 (file)
@@ -173,6 +173,15 @@ acpi_handle acpi_find_child(acpi_handle parent, u64 addr, bool is_bridge)
 }
 EXPORT_SYMBOL_GPL(acpi_find_child);
 
+static void acpi_physnode_link_name(char *buf, unsigned int node_id)
+{
+       if (node_id > 0)
+               snprintf(buf, PHYSICAL_NODE_NAME_SIZE,
+                        PHYSICAL_NODE_STRING "%u", node_id);
+       else
+               strcpy(buf, PHYSICAL_NODE_STRING);
+}
+
 int acpi_bind_one(struct device *dev, acpi_handle handle)
 {
        struct acpi_device *acpi_dev;
@@ -216,8 +225,15 @@ int acpi_bind_one(struct device *dev, acpi_handle handle)
        list_for_each_entry(pn, &acpi_dev->physical_node_list, node) {
                /* Sanity check. */
                if (pn->dev == dev) {
+                       mutex_unlock(&acpi_dev->physical_node_lock);
+
                        dev_warn(dev, "Already associated with ACPI node\n");
-                       goto err_free;
+                       kfree(physical_node);
+                       if (ACPI_HANDLE(dev) != handle)
+                               goto err;
+
+                       put_device(dev);
+                       return 0;
                }
                if (pn->node_id == node_id) {
                        physnode_list = &pn->node;
@@ -230,20 +246,23 @@ int acpi_bind_one(struct device *dev, acpi_handle handle)
        list_add(&physical_node->node, physnode_list);
        acpi_dev->physical_node_count++;
 
-       mutex_unlock(&acpi_dev->physical_node_lock);
-
        if (!ACPI_HANDLE(dev))
                ACPI_HANDLE_SET(dev, acpi_dev->handle);
 
-       if (!physical_node->node_id)
-               strcpy(physical_node_name, PHYSICAL_NODE_STRING);
-       else
-               sprintf(physical_node_name,
-                       "physical_node%d", physical_node->node_id);
+       acpi_physnode_link_name(physical_node_name, node_id);
        retval = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
-                       physical_node_name);
+                                  physical_node_name);
+       if (retval)
+               dev_err(&acpi_dev->dev, "Failed to create link %s (%d)\n",
+                       physical_node_name, retval);
+
        retval = sysfs_create_link(&dev->kobj, &acpi_dev->dev.kobj,
-               "firmware_node");
+                                  "firmware_node");
+       if (retval)
+               dev_err(dev, "Failed to create link firmware_node (%d)\n",
+                       retval);
+
+       mutex_unlock(&acpi_dev->physical_node_lock);
 
        if (acpi_dev->wakeup.flags.valid)
                device_set_wakeup_capable(dev, true);
@@ -254,11 +273,6 @@ int acpi_bind_one(struct device *dev, acpi_handle handle)
        ACPI_HANDLE_SET(dev, NULL);
        put_device(dev);
        return retval;
-
- err_free:
-       mutex_unlock(&acpi_dev->physical_node_lock);
-       kfree(physical_node);
-       goto err;
 }
 EXPORT_SYMBOL_GPL(acpi_bind_one);
 
@@ -267,48 +281,37 @@ int acpi_unbind_one(struct device *dev)
        struct acpi_device_physical_node *entry;
        struct acpi_device *acpi_dev;
        acpi_status status;
-       struct list_head *node, *next;
 
        if (!ACPI_HANDLE(dev))
                return 0;
 
        status = acpi_bus_get_device(ACPI_HANDLE(dev), &acpi_dev);
-       if (ACPI_FAILURE(status))
-               goto err;
+       if (ACPI_FAILURE(status)) {
+               dev_err(dev, "Oops, ACPI handle corrupt in %s()\n", __func__);
+               return -EINVAL;
+       }
 
        mutex_lock(&acpi_dev->physical_node_lock);
-       list_for_each_safe(node, next, &acpi_dev->physical_node_list) {
-               char physical_node_name[PHYSICAL_NODE_NAME_SIZE];
 
-               entry = list_entry(node, struct acpi_device_physical_node,
-                       node);
-               if (entry->dev != dev)
-                       continue;
+       list_for_each_entry(entry, &acpi_dev->physical_node_list, node)
+               if (entry->dev == dev) {
+                       char physnode_name[PHYSICAL_NODE_NAME_SIZE];
 
-               list_del(node);
+                       list_del(&entry->node);
+                       acpi_dev->physical_node_count--;
 
-               acpi_dev->physical_node_count--;
+                       acpi_physnode_link_name(physnode_name, entry->node_id);
+                       sysfs_remove_link(&acpi_dev->dev.kobj, physnode_name);
+                       sysfs_remove_link(&dev->kobj, "firmware_node");
+                       ACPI_HANDLE_SET(dev, NULL);
+                       /* acpi_bind_one() increase refcnt by one. */
+                       put_device(dev);
+                       kfree(entry);
+                       break;
+               }
 
-               if (!entry->node_id)
-                       strcpy(physical_node_name, PHYSICAL_NODE_STRING);
-               else
-                       sprintf(physical_node_name,
-                               "physical_node%d", entry->node_id);
-
-               sysfs_remove_link(&acpi_dev->dev.kobj, physical_node_name);
-               sysfs_remove_link(&dev->kobj, "firmware_node");
-               ACPI_HANDLE_SET(dev, NULL);
-               /* acpi_bind_one increase refcnt by one */
-               put_device(dev);
-               kfree(entry);
-       }
        mutex_unlock(&acpi_dev->physical_node_lock);
-
        return 0;
-
-err:
-       dev_err(dev, "Oops, 'acpi_handle' corrupt\n");
-       return -EINVAL;
 }
 EXPORT_SYMBOL_GPL(acpi_unbind_one);
 
index 5da44e8..20f4233 100644 (file)
@@ -23,6 +23,7 @@
 
 #define PREFIX "ACPI: "
 
+acpi_status acpi_os_initialize1(void);
 int init_acpi_device_notify(void);
 int acpi_scan_init(void);
 #ifdef CONFIG_ACPI_PCI_SLOT
index 33e609f..2e82e5d 100644 (file)
@@ -159,7 +159,7 @@ acpi_table_print_srat_entry(struct acpi_subtable_header *header)
  * distance than the others.
  * Do some quick checks here and only use the SLIT if it passes.
  */
-static __init int slit_valid(struct acpi_table_slit *slit)
+static int __init slit_valid(struct acpi_table_slit *slit)
 {
        int i, j;
        int d = slit->locality_count;
index 6ab2c35..e5f416c 100644 (file)
@@ -52,6 +52,7 @@
 #include <acpi/acpi.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/processor.h>
+#include "internal.h"
 
 #define _COMPONENT             ACPI_OS_SERVICES
 ACPI_MODULE_NAME("osl");
@@ -79,6 +80,8 @@ extern char line_buf[80];
 
 static int (*__acpi_os_prepare_sleep)(u8 sleep_state, u32 pm1a_ctrl,
                                      u32 pm1b_ctrl);
+static int (*__acpi_os_prepare_extended_sleep)(u8 sleep_state, u32 val_a,
+                                     u32 val_b);
 
 static acpi_osd_handler acpi_irq_handler;
 static void *acpi_irq_context;
@@ -140,7 +143,8 @@ static struct osi_linux {
        unsigned int    enable:1;
        unsigned int    dmi:1;
        unsigned int    cmdline:1;
-} osi_linux = {0, 0, 0};
+       unsigned int    default_disabling:1;
+} osi_linux = {0, 0, 0, 0};
 
 static u32 acpi_osi_handler(acpi_string interface, u32 supported)
 {
@@ -563,10 +567,6 @@ static const char * const table_sigs[] = {
        ACPI_SIG_WDRT, ACPI_SIG_DSDT, ACPI_SIG_FADT, ACPI_SIG_PSDT,
        ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT, NULL };
 
-/* Non-fatal errors: Affected tables/files are ignored */
-#define INVALID_TABLE(x, path, name)                                   \
-       { pr_err("ACPI OVERRIDE: " x " [%s%s]\n", path, name); continue; }
-
 #define ACPI_HEADER_SIZE sizeof(struct acpi_table_header)
 
 /* Must not increase 10 or needs code modification below */
@@ -593,9 +593,11 @@ void __init acpi_initrd_override(void *data, size_t size)
                data += offset;
                size -= offset;
 
-               if (file.size < sizeof(struct acpi_table_header))
-                       INVALID_TABLE("Table smaller than ACPI header",
-                                     cpio_path, file.name);
+               if (file.size < sizeof(struct acpi_table_header)) {
+                       pr_err("ACPI OVERRIDE: Table smaller than ACPI header [%s%s]\n",
+                               cpio_path, file.name);
+                       continue;
+               }
 
                table = file.data;
 
@@ -603,15 +605,21 @@ void __init acpi_initrd_override(void *data, size_t size)
                        if (!memcmp(table->signature, table_sigs[sig], 4))
                                break;
 
-               if (!table_sigs[sig])
-                       INVALID_TABLE("Unknown signature",
-                                     cpio_path, file.name);
-               if (file.size != table->length)
-                       INVALID_TABLE("File length does not match table length",
-                                     cpio_path, file.name);
-               if (acpi_table_checksum(file.data, table->length))
-                       INVALID_TABLE("Bad table checksum",
-                                     cpio_path, file.name);
+               if (!table_sigs[sig]) {
+                       pr_err("ACPI OVERRIDE: Unknown signature [%s%s]\n",
+                               cpio_path, file.name);
+                       continue;
+               }
+               if (file.size != table->length) {
+                       pr_err("ACPI OVERRIDE: File length does not match table length [%s%s]\n",
+                               cpio_path, file.name);
+                       continue;
+               }
+               if (acpi_table_checksum(file.data, table->length)) {
+                       pr_err("ACPI OVERRIDE: Bad table checksum [%s%s]\n",
+                               cpio_path, file.name);
+                       continue;
+               }
 
                pr_info("%4.4s ACPI table found in initrd [%s%s][0x%x]\n",
                        table->signature, cpio_path, file.name, table->length);
@@ -1351,8 +1359,8 @@ struct osi_setup_entry {
        bool enable;
 };
 
-static struct osi_setup_entry __initdata
-               osi_setup_entries[OSI_STRING_ENTRIES_MAX] = {
+static struct osi_setup_entry
+               osi_setup_entries[OSI_STRING_ENTRIES_MAX] __initdata = {
        {"Module Device", true},
        {"Processor Device", true},
        {"3.0 _SCP Extensions", true},
@@ -1376,6 +1384,17 @@ void __init acpi_osi_setup(char *str)
 
        if (*str == '!') {
                str++;
+               if (*str == '\0') {
+                       osi_linux.default_disabling = 1;
+                       return;
+               } else if (*str == '*') {
+                       acpi_update_interfaces(ACPI_DISABLE_ALL_STRINGS);
+                       for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
+                               osi = &osi_setup_entries[i];
+                               osi->enable = false;
+                       }
+                       return;
+               }
                enable = false;
        }
 
@@ -1441,6 +1460,13 @@ static void __init acpi_osi_setup_late(void)
        int i;
        acpi_status status;
 
+       if (osi_linux.default_disabling) {
+               status = acpi_update_interfaces(ACPI_DISABLE_ALL_VENDOR_STRINGS);
+
+               if (ACPI_SUCCESS(status))
+                       printk(KERN_INFO PREFIX "Disabled all _OSI OS vendors\n");
+       }
+
        for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
                osi = &osi_setup_entries[i];
                str = osi->string;
@@ -1779,6 +1805,28 @@ void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state,
        __acpi_os_prepare_sleep = func;
 }
 
+acpi_status acpi_os_prepare_extended_sleep(u8 sleep_state, u32 val_a,
+                                 u32 val_b)
+{
+       int rc = 0;
+       if (__acpi_os_prepare_extended_sleep)
+               rc = __acpi_os_prepare_extended_sleep(sleep_state,
+                                            val_a, val_b);
+       if (rc < 0)
+               return AE_ERROR;
+       else if (rc > 0)
+               return AE_CTRL_SKIP;
+
+       return AE_OK;
+}
+
+void acpi_os_set_prepare_extended_sleep(int (*func)(u8 sleep_state,
+                              u32 val_a, u32 val_b))
+{
+       __acpi_os_prepare_extended_sleep = func;
+}
+
+
 void alloc_acpi_hp_work(acpi_handle handle, u32 type, void *context,
                        void (*func)(struct work_struct *work))
 {
index 033d117..d678a18 100644 (file)
@@ -159,12 +159,16 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
        return AE_OK;
 }
 
-void acpi_pci_slot_enumerate(struct pci_bus *bus, acpi_handle handle)
+void acpi_pci_slot_enumerate(struct pci_bus *bus)
 {
-       mutex_lock(&slot_list_lock);
-       acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
-                           register_slot, NULL, bus, NULL);
-       mutex_unlock(&slot_list_lock);
+       acpi_handle handle = ACPI_HANDLE(bus->bridge);
+
+       if (handle) {
+               mutex_lock(&slot_list_lock);
+               acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
+                                   register_slot, NULL, bus, NULL);
+               mutex_unlock(&slot_list_lock);
+       }
 }
 
 void acpi_pci_slot_remove(struct pci_bus *bus)
index 5c28c89..0dbe5cd 100644 (file)
@@ -637,9 +637,7 @@ int acpi_device_sleep_wake(struct acpi_device *dev,
        }
 
        /* Execute _PSW */
-       arg_list.count = 1;
-       in_arg[0].integer.value = enable;
-       status = acpi_evaluate_object(dev->handle, "_PSW", &arg_list, NULL);
+       status = acpi_execute_simple_method(dev->handle, "_PSW", enable);
        if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
                printk(KERN_ERR PREFIX "_PSW execution failed\n");
                dev->wakeup.flags.valid = 0;
@@ -786,7 +784,7 @@ int acpi_power_get_inferred_state(struct acpi_device *device, int *state)
                }
        }
 
-       *state = ACPI_STATE_D3;
+       *state = ACPI_STATE_D3_COLD;
        return 0;
 }
 
index a5e9f4a..cf34d90 100644 (file)
@@ -28,7 +28,7 @@ static int __init set_no_mwait(const struct dmi_system_id *id)
        return 0;
 }
 
-static struct dmi_system_id __initdata processor_idle_dmi_table[] = {
+static struct dmi_system_id processor_idle_dmi_table[] __initdata = {
        {
        set_no_mwait, "Extensa 5220", {
        DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
index 870eaf5..e534ba6 100644 (file)
@@ -91,21 +91,17 @@ static void acpi_processor_notify(acpi_handle handle, u32 event, void *data)
                acpi_processor_ppc_has_changed(pr, 1);
                if (saved == pr->performance_platform_limit)
                        break;
-               acpi_bus_generate_proc_event(device, event,
-                                       pr->performance_platform_limit);
                acpi_bus_generate_netlink_event(device->pnp.device_class,
                                                  dev_name(&device->dev), event,
                                                  pr->performance_platform_limit);
                break;
        case ACPI_PROCESSOR_NOTIFY_POWER:
                acpi_processor_cst_has_changed(pr);
-               acpi_bus_generate_proc_event(device, event, 0);
                acpi_bus_generate_netlink_event(device->pnp.device_class,
                                                  dev_name(&device->dev), event, 0);
                break;
        case ACPI_PROCESSOR_NOTIFY_THROTTLING:
                acpi_processor_tstate_has_changed(pr);
-               acpi_bus_generate_proc_event(device, event, 0);
                acpi_bus_generate_netlink_event(device->pnp.device_class,
                                                  dev_name(&device->dev), event, 0);
                break;
@@ -179,7 +175,9 @@ static int __acpi_processor_start(struct acpi_device *device)
        acpi_processor_load_module(pr);
 #endif
        acpi_processor_get_throttling_info(pr);
-       acpi_processor_get_limit_info(pr);
+
+       if (pr->flags.throttling)
+               pr->flags.limit = 1;
 
        if (!cpuidle_get_driver() || cpuidle_get_driver() == &acpi_idle_driver)
                acpi_processor_power_init(pr);
index 1e9732d..51d7948 100644 (file)
@@ -164,17 +164,12 @@ static void acpi_processor_ppc_ost(acpi_handle handle, int status)
                {.type = ACPI_TYPE_INTEGER,},
        };
        struct acpi_object_list arg_list = {2, params};
-       acpi_handle temp;
 
-       params[0].integer.value = ACPI_PROCESSOR_NOTIFY_PERFORMANCE;
-       params[1].integer.value =  status;
-
-       /* when there is no _OST , skip it */
-       if (ACPI_FAILURE(acpi_get_handle(handle, "_OST", &temp)))
-               return;
-
-       acpi_evaluate_object(handle, "_OST", &arg_list, NULL);
-       return;
+       if (acpi_has_method(handle, "_OST")) {
+               params[0].integer.value = ACPI_PROCESSOR_NOTIFY_PERFORMANCE;
+               params[1].integer.value =  status;
+               acpi_evaluate_object(handle, "_OST", &arg_list, NULL);
+       }
 }
 
 int acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag)
@@ -468,14 +463,11 @@ static int acpi_processor_get_performance_states(struct acpi_processor *pr)
 int acpi_processor_get_performance_info(struct acpi_processor *pr)
 {
        int result = 0;
-       acpi_status status = AE_OK;
-       acpi_handle handle = NULL;
 
        if (!pr || !pr->performance || !pr->handle)
                return -EINVAL;
 
-       status = acpi_get_handle(pr->handle, "_PCT", &handle);
-       if (ACPI_FAILURE(status)) {
+       if (!acpi_has_method(pr->handle, "_PCT")) {
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                                  "ACPI-based processor performance control unavailable\n"));
                return -ENODEV;
@@ -501,7 +493,7 @@ int acpi_processor_get_performance_info(struct acpi_processor *pr)
         */
  update_bios:
 #ifdef CONFIG_X86
-       if (ACPI_SUCCESS(acpi_get_handle(pr->handle, "_PPC", &handle))){
+       if (acpi_has_method(pr->handle, "_PPC")) {
                if(boot_cpu_has(X86_FEATURE_EST))
                        printk(KERN_WARNING FW_BUG "BIOS needs update for CPU "
                               "frequency support\n");
index e8e6527..d1d2e7f 100644 (file)
@@ -186,18 +186,6 @@ static int cpufreq_set_cur_state(unsigned int cpu, int state)
 
 #endif
 
-int acpi_processor_get_limit_info(struct acpi_processor *pr)
-{
-
-       if (!pr)
-               return -EINVAL;
-
-       if (pr->flags.throttling)
-               pr->flags.limit = 1;
-
-       return 0;
-}
-
 /* thermal coolign device callbacks */
 static int acpi_processor_max_state(struct acpi_processor *pr)
 {
index 3322b47..b7201fc 100644 (file)
@@ -505,14 +505,12 @@ int acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list,
                           void *preproc_data)
 {
        struct res_proc_context c;
-       acpi_handle not_used;
        acpi_status status;
 
        if (!adev || !adev->handle || !list_empty(list))
                return -EINVAL;
 
-       status = acpi_get_handle(adev->handle, METHOD_NAME__CRS, &not_used);
-       if (ACPI_FAILURE(status))
+       if (!acpi_has_method(adev->handle, METHOD_NAME__CRS))
                return 0;
 
        c.list = list;
index b6241ee..aef7e1c 100644 (file)
@@ -873,14 +873,9 @@ static void acpi_sbs_callback(void *context)
        u8 saved_charger_state = sbs->charger_present;
        u8 saved_battery_state;
        acpi_ac_get_present(sbs);
-       if (sbs->charger_present != saved_charger_state) {
-#ifdef CONFIG_ACPI_PROC_EVENT
-               acpi_bus_generate_proc_event4(ACPI_AC_CLASS, ACPI_AC_DIR_NAME,
-                                             ACPI_SBS_NOTIFY_STATUS,
-                                             sbs->charger_present);
-#endif
+       if (sbs->charger_present != saved_charger_state)
                kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE);
-       }
+
        if (sbs->manager_present) {
                for (id = 0; id < MAX_SBS_BAT; ++id) {
                        if (!(sbs->batteries_supported & (1 << id)))
@@ -890,12 +885,6 @@ static void acpi_sbs_callback(void *context)
                        acpi_battery_read(bat);
                        if (saved_battery_state == bat->present)
                                continue;
-#ifdef CONFIG_ACPI_PROC_EVENT
-                       acpi_bus_generate_proc_event4(ACPI_BATTERY_CLASS,
-                                                     bat->name,
-                                                     ACPI_SBS_NOTIFY_STATUS,
-                                                     bat->present);
-#endif
                        kobject_uevent(&bat->bat.dev->kobj, KOBJ_CHANGE);
                }
        }
index 8a46c92..e763651 100644 (file)
@@ -193,9 +193,6 @@ static acpi_status acpi_bus_online_companions(acpi_handle handle, u32 lvl,
 static int acpi_scan_hot_remove(struct acpi_device *device)
 {
        acpi_handle handle = device->handle;
-       acpi_handle not_used;
-       struct acpi_object_list arg_list;
-       union acpi_object arg;
        struct device *errdev;
        acpi_status status;
        unsigned long long sta;
@@ -258,32 +255,15 @@ static int acpi_scan_hot_remove(struct acpi_device *device)
        put_device(&device->dev);
        device = NULL;
 
-       if (ACPI_SUCCESS(acpi_get_handle(handle, "_LCK", &not_used))) {
-               arg_list.count = 1;
-               arg_list.pointer = &arg;
-               arg.type = ACPI_TYPE_INTEGER;
-               arg.integer.value = 0;
-               acpi_evaluate_object(handle, "_LCK", &arg_list, NULL);
-       }
-
-       arg_list.count = 1;
-       arg_list.pointer = &arg;
-       arg.type = ACPI_TYPE_INTEGER;
-       arg.integer.value = 1;
-
+       acpi_evaluate_lck(handle, 0);
        /*
         * TBD: _EJD support.
         */
-       status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL);
-       if (ACPI_FAILURE(status)) {
-               if (status == AE_NOT_FOUND) {
-                       return -ENODEV;
-               } else {
-                       acpi_handle_warn(handle, "Eject failed (0x%x)\n",
-                                                               status);
-                       return -EIO;
-               }
-       }
+       status = acpi_evaluate_ej0(handle);
+       if (status == AE_NOT_FOUND)
+               return -ENODEV;
+       else if (ACPI_FAILURE(status))
+               return -EIO;
 
        /*
         * Verify if eject was indeed successful.  If not, log an error
@@ -654,7 +634,6 @@ static int acpi_device_setup_files(struct acpi_device *dev)
 {
        struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
        acpi_status status;
-       acpi_handle temp;
        unsigned long long sun;
        int result = 0;
 
@@ -680,8 +659,7 @@ static int acpi_device_setup_files(struct acpi_device *dev)
        /*
         * If device has _STR, 'description' file is created
         */
-       status = acpi_get_handle(dev->handle, "_STR", &temp);
-       if (ACPI_SUCCESS(status)) {
+       if (acpi_has_method(dev->handle, "_STR")) {
                status = acpi_evaluate_object(dev->handle, "_STR",
                                        NULL, &buffer);
                if (ACPI_FAILURE(status))
@@ -711,8 +689,7 @@ static int acpi_device_setup_files(struct acpi_device *dev)
          * If device has _EJ0, 'eject' file is created that is used to trigger
          * hot-removal function from userland.
          */
-       status = acpi_get_handle(dev->handle, "_EJ0", &temp);
-       if (ACPI_SUCCESS(status)) {
+       if (acpi_has_method(dev->handle, "_EJ0")) {
                result = device_create_file(&dev->dev, &dev_attr_eject);
                if (result)
                        return result;
@@ -734,9 +711,6 @@ end:
 
 static void acpi_device_remove_files(struct acpi_device *dev)
 {
-       acpi_status status;
-       acpi_handle temp;
-
        if (dev->flags.power_manageable) {
                device_remove_file(&dev->dev, &dev_attr_power_state);
                if (dev->power.flags.power_resources)
@@ -747,20 +721,17 @@ static void acpi_device_remove_files(struct acpi_device *dev)
        /*
         * If device has _STR, remove 'description' file
         */
-       status = acpi_get_handle(dev->handle, "_STR", &temp);
-       if (ACPI_SUCCESS(status)) {
+       if (acpi_has_method(dev->handle, "_STR")) {
                kfree(dev->pnp.str_obj);
                device_remove_file(&dev->dev, &dev_attr_description);
        }
        /*
         * If device has _EJ0, remove 'eject' file.
         */
-       status = acpi_get_handle(dev->handle, "_EJ0", &temp);
-       if (ACPI_SUCCESS(status))
+       if (acpi_has_method(dev->handle, "_EJ0"))
                device_remove_file(&dev->dev, &dev_attr_eject);
 
-       status = acpi_get_handle(dev->handle, "_SUN", &temp);
-       if (ACPI_SUCCESS(status))
+       if (acpi_has_method(dev->handle, "_SUN"))
                device_remove_file(&dev->dev, &dev_attr_sun);
 
        if (dev->pnp.unique_id)
@@ -999,6 +970,28 @@ struct bus_type acpi_bus_type = {
        .uevent         = acpi_device_uevent,
 };
 
+static void acpi_bus_data_handler(acpi_handle handle, void *context)
+{
+       /* Intentionally empty. */
+}
+
+int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device)
+{
+       acpi_status status;
+
+       if (!device)
+               return -EINVAL;
+
+       status = acpi_get_data(handle, acpi_bus_data_handler, (void **)device);
+       if (ACPI_FAILURE(status) || !*device) {
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n",
+                                 handle));
+               return -ENODEV;
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(acpi_bus_get_device);
+
 int acpi_device_add(struct acpi_device *device,
                    void (*release)(struct device *))
 {
@@ -1210,14 +1203,6 @@ acpi_bus_get_ejd(acpi_handle handle, acpi_handle *ejd)
 }
 EXPORT_SYMBOL_GPL(acpi_bus_get_ejd);
 
-void acpi_bus_data_handler(acpi_handle handle, void *context)
-{
-
-       /* TBD */
-
-       return;
-}
-
 static int acpi_bus_extract_wakeup_device_power_package(acpi_handle handle,
                                        struct acpi_device_wakeup *wakeup)
 {
@@ -1336,13 +1321,10 @@ static void acpi_bus_set_run_wake_flags(struct acpi_device *device)
 
 static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
 {
-       acpi_handle temp;
-       acpi_status status = 0;
        int err;
 
        /* Presence of _PRW indicates wake capable */
-       status = acpi_get_handle(device->handle, "_PRW", &temp);
-       if (ACPI_FAILURE(status))
+       if (!acpi_has_method(device->handle, "_PRW"))
                return;
 
        err = acpi_bus_extract_wakeup_device_power_package(device->handle,
@@ -1372,7 +1354,6 @@ static void acpi_bus_init_power_state(struct acpi_device *device, int state)
        struct acpi_device_power_state *ps = &device->power.states[state];
        char pathname[5] = { '_', 'P', 'R', '0' + state, '\0' };
        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-       acpi_handle handle;
        acpi_status status;
 
        INIT_LIST_HEAD(&ps->resources);
@@ -1395,8 +1376,7 @@ static void acpi_bus_init_power_state(struct acpi_device *device, int state)
 
        /* Evaluate "_PSx" to see if we can do explicit sets */
        pathname[2] = 'S';
-       status = acpi_get_handle(device->handle, pathname, &handle);
-       if (ACPI_SUCCESS(status))
+       if (acpi_has_method(device->handle, pathname))
                ps->flags.explicit_set = 1;
 
        /*
@@ -1415,28 +1395,21 @@ static void acpi_bus_init_power_state(struct acpi_device *device, int state)
 
 static void acpi_bus_get_power_flags(struct acpi_device *device)
 {
-       acpi_status status;
-       acpi_handle handle;
        u32 i;
 
        /* Presence of _PS0|_PR0 indicates 'power manageable' */
-       status = acpi_get_handle(device->handle, "_PS0", &handle);
-       if (ACPI_FAILURE(status)) {
-               status = acpi_get_handle(device->handle, "_PR0", &handle);
-               if (ACPI_FAILURE(status))
-                       return;
-       }
+       if (!acpi_has_method(device->handle, "_PS0") &&
+           !acpi_has_method(device->handle, "_PR0"))
+               return;
 
        device->flags.power_manageable = 1;
 
        /*
         * Power Management Flags
         */
-       status = acpi_get_handle(device->handle, "_PSC", &handle);
-       if (ACPI_SUCCESS(status))
+       if (acpi_has_method(device->handle, "_PSC"))
                device->power.flags.explicit_get = 1;
-       status = acpi_get_handle(device->handle, "_IRC", &handle);
-       if (ACPI_SUCCESS(status))
+       if (acpi_has_method(device->handle, "_IRC"))
                device->power.flags.inrush_current = 1;
 
        /*
@@ -1450,8 +1423,8 @@ static void acpi_bus_get_power_flags(struct acpi_device *device)
        /* Set defaults for D0 and D3 states (always valid) */
        device->power.states[ACPI_STATE_D0].flags.valid = 1;
        device->power.states[ACPI_STATE_D0].power = 100;
-       device->power.states[ACPI_STATE_D3].flags.valid = 1;
-       device->power.states[ACPI_STATE_D3].power = 0;
+       device->power.states[ACPI_STATE_D3_COLD].flags.valid = 1;
+       device->power.states[ACPI_STATE_D3_COLD].power = 0;
 
        /* Set D3cold's explicit_set flag if _PS3 exists. */
        if (device->power.states[ACPI_STATE_D3_HOT].flags.explicit_set)
@@ -1470,28 +1443,18 @@ static void acpi_bus_get_power_flags(struct acpi_device *device)
 
 static void acpi_bus_get_flags(struct acpi_device *device)
 {
-       acpi_status status = AE_OK;
-       acpi_handle temp = NULL;
-
        /* Presence of _STA indicates 'dynamic_status' */
-       status = acpi_get_handle(device->handle, "_STA", &temp);
-       if (ACPI_SUCCESS(status))
+       if (acpi_has_method(device->handle, "_STA"))
                device->flags.dynamic_status = 1;
 
        /* Presence of _RMV indicates 'removable' */
-       status = acpi_get_handle(device->handle, "_RMV", &temp);
-       if (ACPI_SUCCESS(status))
+       if (acpi_has_method(device->handle, "_RMV"))
                device->flags.removable = 1;
 
        /* Presence of _EJD|_EJ0 indicates 'ejectable' */
-       status = acpi_get_handle(device->handle, "_EJD", &temp);
-       if (ACPI_SUCCESS(status))
+       if (acpi_has_method(device->handle, "_EJD") ||
+           acpi_has_method(device->handle, "_EJ0"))
                device->flags.ejectable = 1;
-       else {
-               status = acpi_get_handle(device->handle, "_EJ0", &temp);
-               if (ACPI_SUCCESS(status))
-                       device->flags.ejectable = 1;
-       }
 }
 
 static void acpi_device_get_busid(struct acpi_device *device)
@@ -1532,47 +1495,46 @@ static void acpi_device_get_busid(struct acpi_device *device)
        }
 }
 
+/*
+ * acpi_ata_match - see if an acpi object is an ATA device
+ *
+ * If an acpi object has one of the ACPI ATA methods defined,
+ * then we can safely call it an ATA device.
+ */
+bool acpi_ata_match(acpi_handle handle)
+{
+       return acpi_has_method(handle, "_GTF") ||
+              acpi_has_method(handle, "_GTM") ||
+              acpi_has_method(handle, "_STM") ||
+              acpi_has_method(handle, "_SDD");
+}
+
 /*
  * acpi_bay_match - see if an acpi object is an ejectable driver bay
  *
  * If an acpi object is ejectable and has one of the ACPI ATA methods defined,
  * then we can safely call it an ejectable drive bay
  */
-static int acpi_bay_match(acpi_handle handle)
+bool acpi_bay_match(acpi_handle handle)
 {
-       acpi_status status;
-       acpi_handle tmp;
        acpi_handle phandle;
 
-       status = acpi_get_handle(handle, "_EJ0", &tmp);
-       if (ACPI_FAILURE(status))
-               return -ENODEV;
-
-       if ((ACPI_SUCCESS(acpi_get_handle(handle, "_GTF", &tmp))) ||
-               (ACPI_SUCCESS(acpi_get_handle(handle, "_GTM", &tmp))) ||
-               (ACPI_SUCCESS(acpi_get_handle(handle, "_STM", &tmp))) ||
-               (ACPI_SUCCESS(acpi_get_handle(handle, "_SDD", &tmp))))
-               return 0;
+       if (!acpi_has_method(handle, "_EJ0"))
+               return false;
+       if (acpi_ata_match(handle))
+               return true;
+       if (ACPI_FAILURE(acpi_get_parent(handle, &phandle)))
+               return false;
 
-       if (acpi_get_parent(handle, &phandle))
-               return -ENODEV;
-
-        if ((ACPI_SUCCESS(acpi_get_handle(phandle, "_GTF", &tmp))) ||
-                (ACPI_SUCCESS(acpi_get_handle(phandle, "_GTM", &tmp))) ||
-                (ACPI_SUCCESS(acpi_get_handle(phandle, "_STM", &tmp))) ||
-                (ACPI_SUCCESS(acpi_get_handle(phandle, "_SDD", &tmp))))
-                return 0;
-
-       return -ENODEV;
+       return acpi_ata_match(phandle);
 }
 
 /*
  * acpi_dock_match - see if an acpi object has a _DCK method
  */
-static int acpi_dock_match(acpi_handle handle)
+bool acpi_dock_match(acpi_handle handle)
 {
-       acpi_handle tmp;
-       return acpi_get_handle(handle, "_DCK", &tmp);
+       return acpi_has_method(handle, "_DCK");
 }
 
 const char *acpi_device_hid(struct acpi_device *device)
@@ -1610,34 +1572,26 @@ static void acpi_add_id(struct acpi_device_pnp *pnp, const char *dev_id)
  * lacks the SMBUS01 HID and the methods do not have the necessary "_"
  * prefix.  Work around this.
  */
-static int acpi_ibm_smbus_match(acpi_handle handle)
+static bool acpi_ibm_smbus_match(acpi_handle handle)
 {
-       acpi_handle h_dummy;
-       struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL};
-       int result;
+       char node_name[ACPI_PATH_SEGMENT_LENGTH];
+       struct acpi_buffer path = { sizeof(node_name), node_name };
 
        if (!dmi_name_in_vendors("IBM"))
-               return -ENODEV;
+               return false;
 
        /* Look for SMBS object */
-       result = acpi_get_name(handle, ACPI_SINGLE_NAME, &path);
-       if (result)
-               return result;
-
-       if (strcmp("SMBS", path.pointer)) {
-               result = -ENODEV;
-               goto out;
-       }
+       if (ACPI_FAILURE(acpi_get_name(handle, ACPI_SINGLE_NAME, &path)) ||
+           strcmp("SMBS", path.pointer))
+               return false;
 
        /* Does it have the necessary (but misnamed) methods? */
-       result = -ENODEV;
-       if (ACPI_SUCCESS(acpi_get_handle(handle, "SBI", &h_dummy)) &&
-           ACPI_SUCCESS(acpi_get_handle(handle, "SBR", &h_dummy)) &&
-           ACPI_SUCCESS(acpi_get_handle(handle, "SBW", &h_dummy)))
-               result = 0;
-out:
-       kfree(path.pointer);
-       return result;
+       if (acpi_has_method(handle, "SBI") &&
+           acpi_has_method(handle, "SBR") &&
+           acpi_has_method(handle, "SBW"))
+               return true;
+
+       return false;
 }
 
 static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp,
@@ -1685,11 +1639,11 @@ static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp,
                 */
                if (acpi_is_video_device(handle))
                        acpi_add_id(pnp, ACPI_VIDEO_HID);
-               else if (ACPI_SUCCESS(acpi_bay_match(handle)))
+               else if (acpi_bay_match(handle))
                        acpi_add_id(pnp, ACPI_BAY_HID);
-               else if (ACPI_SUCCESS(acpi_dock_match(handle)))
+               else if (acpi_dock_match(handle))
                        acpi_add_id(pnp, ACPI_DOCK_HID);
-               else if (!acpi_ibm_smbus_match(handle))
+               else if (acpi_ibm_smbus_match(handle))
                        acpi_add_id(pnp, ACPI_SMBUS_IBM_HID);
                else if (list_empty(&pnp->ids) && handle == ACPI_ROOT_OBJECT) {
                        acpi_add_id(pnp, ACPI_BUS_HID); /* \_SB, LNXSYBUS */
@@ -1900,7 +1854,6 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
        struct acpi_device *device = NULL;
        int type;
        unsigned long long sta;
-       acpi_status status;
        int result;
 
        acpi_bus_get_device(handle, &device);
@@ -1921,10 +1874,8 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
        if (!(sta & ACPI_STA_DEVICE_PRESENT) &&
            !(sta & ACPI_STA_DEVICE_FUNCTIONING)) {
                struct acpi_device_wakeup wakeup;
-               acpi_handle temp;
 
-               status = acpi_get_handle(handle, "_PRW", &temp);
-               if (ACPI_SUCCESS(status)) {
+               if (acpi_has_method(handle, "_PRW")) {
                        acpi_bus_extract_wakeup_device_power_package(handle,
                                                                     &wakeup);
                        acpi_power_resources_list_free(&wakeup.resources);
index 187ab61..14df305 100644 (file)
@@ -31,12 +31,9 @@ static u8 sleep_states[ACPI_S_STATE_COUNT];
 
 static void acpi_sleep_tts_switch(u32 acpi_state)
 {
-       union acpi_object in_arg = { ACPI_TYPE_INTEGER };
-       struct acpi_object_list arg_list = { 1, &in_arg };
-       acpi_status status = AE_OK;
+       acpi_status status;
 
-       in_arg.integer.value = acpi_state;
-       status = acpi_evaluate_object(NULL, "\\_TTS", &arg_list, NULL);
+       status = acpi_execute_simple_method(NULL, "\\_TTS", acpi_state);
        if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
                /*
                 * OS can't evaluate the _TTS object correctly. Some warning
@@ -141,7 +138,7 @@ static int __init init_nvs_nosave(const struct dmi_system_id *d)
        return 0;
 }
 
-static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
+static struct dmi_system_id acpisleep_dmi_table[] __initdata = {
        {
        .callback = init_old_suspend_ordering,
        .ident = "Abit KN9 (nForce4 variant)",
@@ -423,10 +420,21 @@ static void acpi_pm_finish(void)
 }
 
 /**
- *     acpi_pm_end - Finish up suspend sequence.
+ * acpi_pm_start - Start system PM transition.
+ */
+static void acpi_pm_start(u32 acpi_state)
+{
+       acpi_target_sleep_state = acpi_state;
+       acpi_sleep_tts_switch(acpi_target_sleep_state);
+       acpi_scan_lock_acquire();
+}
+
+/**
+ * acpi_pm_end - Finish up system PM transition.
  */
 static void acpi_pm_end(void)
 {
+       acpi_scan_lock_release();
        /*
         * This is necessary in case acpi_pm_finish() is not called during a
         * failing transition to a sleep state.
@@ -454,21 +462,19 @@ static u32 acpi_suspend_states[] = {
 static int acpi_suspend_begin(suspend_state_t pm_state)
 {
        u32 acpi_state = acpi_suspend_states[pm_state];
-       int error = 0;
+       int error;
 
        error = (nvs_nosave || nvs_nosave_s3) ? 0 : suspend_nvs_alloc();
        if (error)
                return error;
 
-       if (sleep_states[acpi_state]) {
-               acpi_target_sleep_state = acpi_state;
-               acpi_sleep_tts_switch(acpi_target_sleep_state);
-       } else {
-               printk(KERN_ERR "ACPI does not support this state: %d\n",
-                       pm_state);
-               error = -ENOSYS;
+       if (!sleep_states[acpi_state]) {
+               pr_err("ACPI does not support sleep state S%u\n", acpi_state);
+               return -ENOSYS;
        }
-       return error;
+
+       acpi_pm_start(acpi_state);
+       return 0;
 }
 
 /**
@@ -634,10 +640,8 @@ static int acpi_hibernation_begin(void)
        int error;
 
        error = nvs_nosave ? 0 : suspend_nvs_alloc();
-       if (!error) {
-               acpi_target_sleep_state = ACPI_STATE_S4;
-               acpi_sleep_tts_switch(acpi_target_sleep_state);
-       }
+       if (!error)
+               acpi_pm_start(ACPI_STATE_S4);
 
        return error;
 }
@@ -716,8 +720,10 @@ static int acpi_hibernation_begin_old(void)
        if (!error) {
                if (!nvs_nosave)
                        error = suspend_nvs_alloc();
-               if (!error)
+               if (!error) {
                        acpi_target_sleep_state = ACPI_STATE_S4;
+                       acpi_scan_lock_acquire();
+               }
        }
        return error;
 }
index a33821c..9063239 100644 (file)
 
 #define ACPI_THERMAL_CLASS             "thermal_zone"
 #define ACPI_THERMAL_DEVICE_NAME       "Thermal Zone"
-#define ACPI_THERMAL_FILE_STATE                "state"
-#define ACPI_THERMAL_FILE_TEMPERATURE  "temperature"
-#define ACPI_THERMAL_FILE_TRIP_POINTS  "trip_points"
-#define ACPI_THERMAL_FILE_COOLING_MODE "cooling_mode"
-#define ACPI_THERMAL_FILE_POLLING_FREQ "polling_frequency"
 #define ACPI_THERMAL_NOTIFY_TEMPERATURE        0x80
 #define ACPI_THERMAL_NOTIFY_THRESHOLDS 0x81
 #define ACPI_THERMAL_NOTIFY_DEVICES    0x82
@@ -190,7 +185,6 @@ struct acpi_thermal {
        struct thermal_zone_device *thermal_zone;
        int tz_enabled;
        int kelvin_offset;
-       struct mutex lock;
 };
 
 /* --------------------------------------------------------------------------
@@ -239,26 +233,16 @@ static int acpi_thermal_get_polling_frequency(struct acpi_thermal *tz)
 
 static int acpi_thermal_set_cooling_mode(struct acpi_thermal *tz, int mode)
 {
-       acpi_status status = AE_OK;
-       union acpi_object arg0 = { ACPI_TYPE_INTEGER };
-       struct acpi_object_list arg_list = { 1, &arg0 };
-       acpi_handle handle = NULL;
-
-
        if (!tz)
                return -EINVAL;
 
-       status = acpi_get_handle(tz->device->handle, "_SCP", &handle);
-       if (ACPI_FAILURE(status)) {
+       if (!acpi_has_method(tz->device->handle, "_SCP")) {
                ACPI_DEBUG_PRINT((ACPI_DB_INFO, "_SCP not present\n"));
                return -ENODEV;
-       }
-
-       arg0.integer.value = mode;
-
-       status = acpi_evaluate_object(handle, NULL, &arg_list, NULL);
-       if (ACPI_FAILURE(status))
+       } else if (ACPI_FAILURE(acpi_execute_simple_method(tz->device->handle,
+                                                          "_SCP", mode))) {
                return -ENODEV;
+       }
 
        return 0;
 }
@@ -769,7 +753,6 @@ static int thermal_notify(struct thermal_zone_device *thermal, int trip,
        else
                return 0;
 
-       acpi_bus_generate_proc_event(tz->device, type, 1);
        acpi_bus_generate_netlink_event(tz->device->pnp.device_class,
                                        dev_name(&tz->device->dev), type, 1);
 
@@ -850,12 +833,13 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
                if (ACPI_SUCCESS(status) && (dev == device)) {
                        if (bind)
                                result = thermal_zone_bind_cooling_device
-                                               (thermal, -1, cdev,
-                                                THERMAL_NO_LIMIT,
+                                               (thermal, THERMAL_TRIPS_NONE,
+                                                cdev, THERMAL_NO_LIMIT,
                                                 THERMAL_NO_LIMIT);
                        else
                                result = thermal_zone_unbind_cooling_device
-                                               (thermal, -1, cdev);
+                                               (thermal, THERMAL_TRIPS_NONE,
+                                                cdev);
                        if (result)
                                goto failed;
                }
@@ -980,14 +964,12 @@ static void acpi_thermal_notify(struct acpi_device *device, u32 event)
        case ACPI_THERMAL_NOTIFY_THRESHOLDS:
                acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_THRESHOLDS);
                acpi_thermal_check(tz);
-               acpi_bus_generate_proc_event(device, event, 0);
                acpi_bus_generate_netlink_event(device->pnp.device_class,
                                                  dev_name(&device->dev), event, 0);
                break;
        case ACPI_THERMAL_NOTIFY_DEVICES:
                acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_DEVICES);
                acpi_thermal_check(tz);
-               acpi_bus_generate_proc_event(device, event, 0);
                acpi_bus_generate_netlink_event(device->pnp.device_class,
                                                  dev_name(&device->dev), event, 0);
                break;
@@ -1101,8 +1083,6 @@ static int acpi_thermal_add(struct acpi_device *device)
        strcpy(acpi_device_name(device), ACPI_THERMAL_DEVICE_NAME);
        strcpy(acpi_device_class(device), ACPI_THERMAL_CLASS);
        device->driver_data = tz;
-       mutex_init(&tz->lock);
-
 
        result = acpi_thermal_get_info(tz);
        if (result)
@@ -1135,7 +1115,6 @@ static int acpi_thermal_remove(struct acpi_device *device)
        tz = acpi_driver_data(device);
 
        acpi_thermal_unregister_thermal_zone(tz);
-       mutex_destroy(&tz->lock);
        kfree(tz);
        return 0;
 }
index 7443713..552248b 100644 (file)
@@ -495,3 +495,73 @@ acpi_handle_printk(const char *level, acpi_handle handle, const char *fmt, ...)
        kfree(buffer.pointer);
 }
 EXPORT_SYMBOL(acpi_handle_printk);
+
+/**
+ * acpi_has_method: Check whether @handle has a method named @name
+ * @handle: ACPI device handle
+ * @name: name of object or method
+ *
+ * Check whether @handle has a method named @name.
+ */
+bool acpi_has_method(acpi_handle handle, char *name)
+{
+       acpi_handle tmp;
+
+       return ACPI_SUCCESS(acpi_get_handle(handle, name, &tmp));
+}
+EXPORT_SYMBOL(acpi_has_method);
+
+acpi_status acpi_execute_simple_method(acpi_handle handle, char *method,
+                                      u64 arg)
+{
+       union acpi_object obj = { .type = ACPI_TYPE_INTEGER };
+       struct acpi_object_list arg_list = { .count = 1, .pointer = &obj, };
+
+       obj.integer.value = arg;
+
+       return acpi_evaluate_object(handle, method, &arg_list, NULL);
+}
+EXPORT_SYMBOL(acpi_execute_simple_method);
+
+/**
+ * acpi_evaluate_ej0: Evaluate _EJ0 method for hotplug operations
+ * @handle: ACPI device handle
+ *
+ * Evaluate device's _EJ0 method for hotplug operations.
+ */
+acpi_status acpi_evaluate_ej0(acpi_handle handle)
+{
+       acpi_status status;
+
+       status = acpi_execute_simple_method(handle, "_EJ0", 1);
+       if (status == AE_NOT_FOUND)
+               acpi_handle_warn(handle, "No _EJ0 support for device\n");
+       else if (ACPI_FAILURE(status))
+               acpi_handle_warn(handle, "Eject failed (0x%x)\n", status);
+
+       return status;
+}
+
+/**
+ * acpi_evaluate_lck: Evaluate _LCK method to lock/unlock device
+ * @handle: ACPI device handle
+ * @lock: lock device if non-zero, otherwise unlock device
+ *
+ * Evaluate device's _LCK method if present to lock/unlock device
+ */
+acpi_status acpi_evaluate_lck(acpi_handle handle, int lock)
+{
+       acpi_status status;
+
+       status = acpi_execute_simple_method(handle, "_LCK", !!lock);
+       if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+               if (lock)
+                       acpi_handle_warn(handle,
+                               "Locking device failed (0x%x)\n", status);
+               else
+                       acpi_handle_warn(handle,
+                               "Unlocking device failed (0x%x)\n", status);
+       }
+
+       return status;
+}
index e1284b8..aebcf63 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  video.c - ACPI Video Driver ($Revision:$)
+ *  video.c - ACPI Video Driver
  *
  *  Copyright (C) 2004 Luming Yu <luming.yu@intel.com>
  *  Copyright (C) 2004 Bruno Ducrot <ducrot@poupinou.org>
@@ -88,7 +88,7 @@ module_param(allow_duplicates, bool, 0644);
 static bool use_bios_initial_backlight = 1;
 module_param(use_bios_initial_backlight, bool, 0644);
 
-static int register_count = 0;
+static int register_count;
 static int acpi_video_bus_add(struct acpi_device *device);
 static int acpi_video_bus_remove(struct acpi_device *device);
 static void acpi_video_bus_notify(struct acpi_device *device, u32 event);
@@ -118,26 +118,26 @@ struct acpi_video_bus_flags {
 };
 
 struct acpi_video_bus_cap {
-       u8 _DOS:1;              /*Enable/Disable output switching */
-       u8 _DOD:1;              /*Enumerate all devices attached to display adapter */
-       u8 _ROM:1;              /*Get ROM Data */
-       u8 _GPD:1;              /*Get POST Device */
-       u8 _SPD:1;              /*Set POST Device */
-       u8 _VPO:1;              /*Video POST Options */
+       u8 _DOS:1;              /* Enable/Disable output switching */
+       u8 _DOD:1;              /* Enumerate all devices attached to display adapter */
+       u8 _ROM:1;              /* Get ROM Data */
+       u8 _GPD:1;              /* Get POST Device */
+       u8 _SPD:1;              /* Set POST Device */
+       u8 _VPO:1;              /* Video POST Options */
        u8 reserved:2;
 };
 
 struct acpi_video_device_attrib {
        u32 display_index:4;    /* A zero-based instance of the Display */
-       u32 display_port_attachment:4;  /*This field differentiates the display type */
-       u32 display_type:4;     /*Describe the specific type in use */
-       u32 vendor_specific:4;  /*Chipset Vendor Specific */
-       u32 bios_can_detect:1;  /*BIOS can detect the device */
-       u32 depend_on_vga:1;    /*Non-VGA output device whose power is related to 
+       u32 display_port_attachment:4;  /* This field differentiates the display type */
+       u32 display_type:4;     /* Describe the specific type in use */
+       u32 vendor_specific:4;  /* Chipset Vendor Specific */
+       u32 bios_can_detect:1;  /* BIOS can detect the device */
+       u32 depend_on_vga:1;    /* Non-VGA output device whose power is related to
                                   the VGA device. */
-       u32 pipe_id:3;          /*For VGA multiple-head devices. */
-       u32 reserved:10;        /*Must be 0 */
-       u32 device_id_scheme:1; /*Device ID Scheme */
+       u32 pipe_id:3;          /* For VGA multiple-head devices. */
+       u32 reserved:10;        /* Must be 0 */
+       u32 device_id_scheme:1; /* Device ID Scheme */
 };
 
 struct acpi_video_enumerated_device {
@@ -174,19 +174,17 @@ struct acpi_video_device_flags {
 };
 
 struct acpi_video_device_cap {
-       u8 _ADR:1;              /*Return the unique ID */
-       u8 _BCL:1;              /*Query list of brightness control levels supported */
-       u8 _BCM:1;              /*Set the brightness level */
+       u8 _ADR:1;              /* Return the unique ID */
+       u8 _BCL:1;              /* Query list of brightness control levels supported */
+       u8 _BCM:1;              /* Set the brightness level */
        u8 _BQC:1;              /* Get current brightness level */
        u8 _BCQ:1;              /* Some buggy BIOS uses _BCQ instead of _BQC */
-       u8 _DDC:1;              /*Return the EDID for this device */
+       u8 _DDC:1;              /* Return the EDID for this device */
 };
 
 struct acpi_video_brightness_flags {
        u8 _BCL_no_ac_battery_levels:1; /* no AC/Battery levels in _BCL */
-       u8 _BCL_reversed:1;             /* _BCL package is in a reversed order*/
-       u8 _BCL_use_index:1;            /* levels in _BCL are index values */
-       u8 _BCM_use_index:1;            /* input of _BCM is an index value */
+       u8 _BCL_reversed:1;             /* _BCL package is in a reversed order */
        u8 _BQC_use_index:1;            /* _BQC returns an index value */
 };
 
@@ -231,21 +229,22 @@ static int acpi_video_get_next_level(struct acpi_video_device *device,
 static int acpi_video_switch_brightness(struct acpi_video_device *device,
                                         int event);
 
-/*backlight device sysfs support*/
+/* backlight device sysfs support */
 static int acpi_video_get_brightness(struct backlight_device *bd)
 {
        unsigned long long cur_level;
        int i;
-       struct acpi_video_device *vd =
-               (struct acpi_video_device *)bl_get_data(bd);
+       struct acpi_video_device *vd = bl_get_data(bd);
 
        if (acpi_video_device_lcd_get_level_current(vd, &cur_level, false))
                return -EINVAL;
        for (i = 2; i < vd->brightness->count; i++) {
                if (vd->brightness->levels[i] == cur_level)
-                       /* The first two entries are special - see page 575
-                          of the ACPI spec 3.0 */
-                       return i-2;
+                       /*
+                        * The first two entries are special - see page 575
+                        * of the ACPI spec 3.0
+                        */
+                       return i - 2;
        }
        return 0;
 }
@@ -253,8 +252,7 @@ static int acpi_video_get_brightness(struct backlight_device *bd)
 static int acpi_video_set_brightness(struct backlight_device *bd)
 {
        int request_level = bd->props.brightness + 2;
-       struct acpi_video_device *vd =
-               (struct acpi_video_device *)bl_get_data(bd);
+       struct acpi_video_device *vd = bl_get_data(bd);
 
        return acpi_video_device_lcd_set_level(vd,
                                vd->brightness->levels[request_level]);
@@ -302,11 +300,11 @@ video_set_cur_state(struct thermal_cooling_device *cooling_dev, unsigned long st
        struct acpi_video_device *video = acpi_driver_data(device);
        int level;
 
-       if ( state >= video->brightness->count - 2)
+       if (state >= video->brightness->count - 2)
                return -EINVAL;
 
        state = video->brightness->count - state;
-       level = video->brightness->levels[state -1];
+       level = video->brightness->levels[state - 1];
        return acpi_video_device_lcd_set_level(video, level);
 }
 
@@ -316,9 +314,11 @@ static const struct thermal_cooling_device_ops video_cooling_ops = {
        .set_cur_state = video_set_cur_state,
 };
 
-/* --------------------------------------------------------------------------
-                               Video Management
-   -------------------------------------------------------------------------- */
+/*
+ * --------------------------------------------------------------------------
+ *                             Video Management
+ * --------------------------------------------------------------------------
+ */
 
 static int
 acpi_video_device_lcd_query_levels(struct acpi_video_device *device,
@@ -345,7 +345,7 @@ acpi_video_device_lcd_query_levels(struct acpi_video_device *device,
 
        return 0;
 
-      err:
+err:
        kfree(buffer.pointer);
 
        return status;
@@ -355,14 +355,10 @@ static int
 acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level)
 {
        int status;
-       union acpi_object arg0 = { ACPI_TYPE_INTEGER };
-       struct acpi_object_list args = { 1, &arg0 };
        int state;
 
-       arg0.integer.value = level;
-
-       status = acpi_evaluate_object(device->dev->handle, "_BCM",
-                                     &args, NULL);
+       status = acpi_execute_simple_method(device->dev->handle,
+                                           "_BCM", level);
        if (ACPI_FAILURE(status)) {
                ACPI_ERROR((AE_INFO, "Evaluating _BCM failed"));
                return -EIO;
@@ -546,7 +542,7 @@ acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
                                if (device->brightness->levels[i] == *level) {
                                        device->brightness->curr = *level;
                                        return 0;
-                       }
+                               }
                        /*
                         * BQC returned an invalid level.
                         * Stop using it.
@@ -556,7 +552,8 @@ acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
                                      buf));
                        device->cap._BQC = device->cap._BCQ = 0;
                } else {
-                       /* Fixme:
+                       /*
+                        * Fixme:
                         * should we return an error or ignore this failure?
                         * dev->brightness->curr is a cached value which stores
                         * the correct current backlight level in most cases.
@@ -615,8 +612,8 @@ acpi_video_device_EDID(struct acpi_video_device *device,
 
 /*
  *  Arg:
- *     video           : video bus device pointer
- *     bios_flag       : 
+ *     video           : video bus device pointer
+ *     bios_flag       :
  *             0.      The system BIOS should NOT automatically switch(toggle)
  *                     the active display output.
  *             1.      The system BIOS should automatically switch (toggle) the
@@ -628,9 +625,9 @@ acpi_video_device_EDID(struct acpi_video_device *device,
  *     lcd_flag        :
  *             0.      The system BIOS should automatically control the brightness level
  *                     of the LCD when the power changes from AC to DC
- *             1.      The system BIOS should NOT automatically control the brightness 
+ *             1.      The system BIOS should NOT automatically control the brightness
  *                     level of the LCD when the power changes from AC to DC.
- * Return Value:
+ *  Return Value:
  *             -EINVAL wrong arg.
  */
 
@@ -638,18 +635,15 @@ static int
 acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag)
 {
        acpi_status status;
-       union acpi_object arg0 = { ACPI_TYPE_INTEGER };
-       struct acpi_object_list args = { 1, &arg0 };
 
        if (!video->cap._DOS)
                return 0;
 
        if (bios_flag < 0 || bios_flag > 3 || lcd_flag < 0 || lcd_flag > 1)
                return -EINVAL;
-       arg0.integer.value = (lcd_flag << 2) | bios_flag;
-       video->dos_setting = arg0.integer.value;
-       status = acpi_evaluate_object(video->device->handle, "_DOS",
-               &args, NULL);
+       video->dos_setting = (lcd_flag << 2) | bios_flag;
+       status = acpi_execute_simple_method(video->device->handle, "_DOS",
+                                           (lcd_flag << 2) | bios_flag);
        if (ACPI_FAILURE(status))
                return -EIO;
 
@@ -717,8 +711,8 @@ static int acpi_video_bqc_quirk(struct acpi_video_device *device,
 
 
 /*
- *  Arg:       
- *     device  : video output device (LCD, CRT, ..)
+ *  Arg:
+ *     device  : video output device (LCD, CRT, ..)
  *
  *  Return Value:
  *     Maximum brightness level
@@ -806,16 +800,6 @@ acpi_video_init_brightness(struct acpi_video_device *device)
        br->count = count;
        device->brightness = br;
 
-       /* Check the input/output of _BQC/_BCL/_BCM */
-       if ((max_level < 100) && (max_level <= (count - 2)))
-               br->flags._BCL_use_index = 1;
-
-       /*
-        * _BCM is always consistent with _BCL,
-        * at least for all the laptops we have ever seen.
-        */
-       br->flags._BCM_use_index = br->flags._BCL_use_index;
-
        /* _BQC uses INDEX while _BCL uses VALUE in some laptops */
        br->curr = level = max_level;
 
@@ -877,7 +861,7 @@ out:
  *     device  : video output device (LCD, CRT, ..)
  *
  *  Return Value:
- *     None
+ *     None
  *
  *  Find out all required AML methods defined under the output
  *  device.
@@ -885,31 +869,21 @@ out:
 
 static void acpi_video_device_find_cap(struct acpi_video_device *device)
 {
-       acpi_handle h_dummy1;
-
-       if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_ADR", &h_dummy1))) {
+       if (acpi_has_method(device->dev->handle, "_ADR"))
                device->cap._ADR = 1;
-       }
-       if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_BCL", &h_dummy1))) {
+       if (acpi_has_method(device->dev->handle, "_BCL"))
                device->cap._BCL = 1;
-       }
-       if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_BCM", &h_dummy1))) {
+       if (acpi_has_method(device->dev->handle, "_BCM"))
                device->cap._BCM = 1;
-       }
-       if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle,"_BQC",&h_dummy1)))
+       if (acpi_has_method(device->dev->handle, "_BQC")) {
                device->cap._BQC = 1;
-       else if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_BCQ",
-                               &h_dummy1))) {
+       } else if (acpi_has_method(device->dev->handle, "_BCQ")) {
                printk(KERN_WARNING FW_BUG "_BCQ is used instead of _BQC\n");
                device->cap._BCQ = 1;
        }
 
-       if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DDC", &h_dummy1))) {
+       if (acpi_has_method(device->dev->handle, "_DDC"))
                device->cap._DDC = 1;
-       }
-
-       if (acpi_video_init_brightness(device))
-               return;
 
        if (acpi_video_backlight_support()) {
                struct backlight_properties props;
@@ -917,9 +891,12 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
                acpi_handle acpi_parent;
                struct device *parent = NULL;
                int result;
-               static int count = 0;
+               static int count;
                char *name;
 
+               result = acpi_video_init_brightness(device);
+               if (result)
+                       return;
                name = kasprintf(GFP_KERNEL, "acpi_video%d", count);
                if (!name)
                        return;
@@ -979,46 +956,33 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
                if (result)
                        printk(KERN_ERR PREFIX "Create sysfs link\n");
 
-       } else {
-               /* Remove the brightness object. */
-               kfree(device->brightness->levels);
-               kfree(device->brightness);
-               device->brightness = NULL;
        }
 }
 
 /*
- *  Arg:       
- *     device  : video output device (VGA)
+ *  Arg:
+ *     device  : video output device (VGA)
  *
  *  Return Value:
- *     None
+ *     None
  *
  *  Find out all required AML methods defined under the video bus device.
  */
 
 static void acpi_video_bus_find_cap(struct acpi_video_bus *video)
 {
-       acpi_handle h_dummy1;
-
-       if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_DOS", &h_dummy1))) {
+       if (acpi_has_method(video->device->handle, "_DOS"))
                video->cap._DOS = 1;
-       }
-       if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_DOD", &h_dummy1))) {
+       if (acpi_has_method(video->device->handle, "_DOD"))
                video->cap._DOD = 1;
-       }
-       if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_ROM", &h_dummy1))) {
+       if (acpi_has_method(video->device->handle, "_ROM"))
                video->cap._ROM = 1;
-       }
-       if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_GPD", &h_dummy1))) {
+       if (acpi_has_method(video->device->handle, "_GPD"))
                video->cap._GPD = 1;
-       }
-       if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_SPD", &h_dummy1))) {
+       if (acpi_has_method(video->device->handle, "_SPD"))
                video->cap._SPD = 1;
-       }
-       if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_VPO", &h_dummy1))) {
+       if (acpi_has_method(video->device->handle, "_VPO"))
                video->cap._VPO = 1;
-       }
 }
 
 /*
@@ -1039,7 +1003,8 @@ static int acpi_video_bus_check(struct acpi_video_bus *video)
                return -ENODEV;
        pci_dev_put(dev);
 
-       /* Since there is no HID, CID and so on for VGA driver, we have
+       /*
+        * Since there is no HID, CID and so on for VGA driver, we have
         * to check well known required nodes.
         */
 
@@ -1069,12 +1034,14 @@ static int acpi_video_bus_check(struct acpi_video_bus *video)
        return status;
 }
 
-/* --------------------------------------------------------------------------
-                                 Driver Interface
-   -------------------------------------------------------------------------- */
+/*
+ * --------------------------------------------------------------------------
+ *                               Driver Interface
+ * --------------------------------------------------------------------------
+ */
 
 /* device interface */
-static struct acpi_video_device_attrib*
+static struct acpi_video_device_attrib *
 acpi_video_get_device_attr(struct acpi_video_bus *video, unsigned long device_id)
 {
        struct acpi_video_enumerated_device *ids;
@@ -1112,7 +1079,7 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
        unsigned long long device_id;
        int status, device_type;
        struct acpi_video_device *data;
-       struct acpi_video_device_attribattribute;
+       struct acpi_video_device_attrib *attribute;
 
        status =
            acpi_evaluate_integer(device->handle, "_ADR", NULL, &device_id);
@@ -1134,7 +1101,7 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
 
        attribute = acpi_video_get_device_attr(video, device_id);
 
-       if((attribute != NULL) && attribute->device_id_scheme) {
+       if (attribute && attribute->device_id_scheme) {
                switch (attribute->display_type) {
                case ACPI_VIDEO_DISPLAY_CRT:
                        data->flags.crt = 1;
@@ -1152,24 +1119,24 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
                        data->flags.unknown = 1;
                        break;
                }
-               if(attribute->bios_can_detect)
+               if (attribute->bios_can_detect)
                        data->flags.bios = 1;
        } else {
                /* Check for legacy IDs */
                device_type = acpi_video_get_device_type(video, device_id);
                /* Ignore bits 16 and 18-20 */
                switch (device_type & 0xffe2ffff) {
-                       case ACPI_VIDEO_DISPLAY_LEGACY_MONITOR:
-                               data->flags.crt = 1;
-                               break;
-                       case ACPI_VIDEO_DISPLAY_LEGACY_PANEL:
-                               data->flags.lcd = 1;
-                               break;
-                       case ACPI_VIDEO_DISPLAY_LEGACY_TV:
-                               data->flags.tvout = 1;
-                               break;
-                       default:
-                               data->flags.unknown = 1;
+               case ACPI_VIDEO_DISPLAY_LEGACY_MONITOR:
+                       data->flags.crt = 1;
+                       break;
+               case ACPI_VIDEO_DISPLAY_LEGACY_PANEL:
+                       data->flags.lcd = 1;
+                       break;
+               case ACPI_VIDEO_DISPLAY_LEGACY_TV:
+                       data->flags.tvout = 1;
+                       break;
+               default:
+                       data->flags.unknown = 1;
                }
        }
 
@@ -1192,12 +1159,12 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
 
 /*
  *  Arg:
- *     video   : video bus device 
+ *     video   : video bus device
  *
  *  Return:
- *     none
- *  
- *  Enumerate the video device list of the video bus, 
+ *     none
+ *
+ *  Enumerate the video device list of the video bus,
  *  bind the ids with the corresponding video devices
  *  under the video bus.
  */
@@ -1216,13 +1183,13 @@ static void acpi_video_device_rebind(struct acpi_video_bus *video)
 
 /*
  *  Arg:
- *     video   : video bus device 
- *     device  : video output device under the video 
- *             bus
+ *     video   : video bus device
+ *     device  : video output device under the video
+ *             bus
  *
  *  Return:
- *     none
- *  
+ *     none
+ *
  *  Bind the ids with the corresponding video devices
  *  under the video bus.
  */
@@ -1245,11 +1212,11 @@ acpi_video_device_bind(struct acpi_video_bus *video,
 
 /*
  *  Arg:
- *     video   : video bus device 
+ *     video   : video bus device
  *
  *  Return:
- *     < 0     : error
- *  
+ *     < 0     : error
+ *
  *  Call _DOD to enumerate all devices attached to display adapter
  *
  */
@@ -1310,7 +1277,7 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video)
        video->attached_array = active_list;
        video->attached_count = count;
 
- out:
+out:
        kfree(buffer.pointer);
        return status;
 }
@@ -1577,7 +1544,6 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event)
        switch (event) {
        case ACPI_VIDEO_NOTIFY_SWITCH:  /* User requested a switch,
                                         * most likely via hotkey. */
-               acpi_bus_generate_proc_event(device, event, 0);
                keycode = KEY_SWITCHVIDEOMODE;
                break;
 
@@ -1585,20 +1551,16 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event)
                                         * connector. */
                acpi_video_device_enumerate(video);
                acpi_video_device_rebind(video);
-               acpi_bus_generate_proc_event(device, event, 0);
                keycode = KEY_SWITCHVIDEOMODE;
                break;
 
        case ACPI_VIDEO_NOTIFY_CYCLE:   /* Cycle Display output hotkey pressed. */
-               acpi_bus_generate_proc_event(device, event, 0);
                keycode = KEY_SWITCHVIDEOMODE;
                break;
        case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT:     /* Next Display output hotkey pressed. */
-               acpi_bus_generate_proc_event(device, event, 0);
                keycode = KEY_VIDEO_NEXT;
                break;
        case ACPI_VIDEO_NOTIFY_PREV_OUTPUT:     /* previous Display output hotkey pressed. */
-               acpi_bus_generate_proc_event(device, event, 0);
                keycode = KEY_VIDEO_PREV;
                break;
 
@@ -1641,31 +1603,26 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data)
        case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS:        /* Cycle brightness */
                if (brightness_switch_enabled)
                        acpi_video_switch_brightness(video_device, event);
-               acpi_bus_generate_proc_event(device, event, 0);
                keycode = KEY_BRIGHTNESS_CYCLE;
                break;
        case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS:  /* Increase brightness */
                if (brightness_switch_enabled)
                        acpi_video_switch_brightness(video_device, event);
-               acpi_bus_generate_proc_event(device, event, 0);
                keycode = KEY_BRIGHTNESSUP;
                break;
        case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS:  /* Decrease brightness */
                if (brightness_switch_enabled)
                        acpi_video_switch_brightness(video_device, event);
-               acpi_bus_generate_proc_event(device, event, 0);
                keycode = KEY_BRIGHTNESSDOWN;
                break;
        case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightness */
                if (brightness_switch_enabled)
                        acpi_video_switch_brightness(video_device, event);
-               acpi_bus_generate_proc_event(device, event, 0);
                keycode = KEY_BRIGHTNESS_ZERO;
                break;
        case ACPI_VIDEO_NOTIFY_DISPLAY_OFF:     /* display device off */
                if (brightness_switch_enabled)
                        acpi_video_switch_brightness(video_device, event);
-               acpi_bus_generate_proc_event(device, event, 0);
                keycode = KEY_DISPLAY_OFF;
                break;
        default:
@@ -1765,7 +1722,7 @@ static int acpi_video_bus_add(struct acpi_device *device)
        if (!strcmp(device->pnp.bus_id, "VID")) {
                if (instance)
                        device->pnp.bus_id[3] = '0' + instance;
-               instance ++;
+               instance++;
        }
        /* a hack to fix the duplicate name "VGA" problem on Pa 3553 */
        if (!strcmp(device->pnp.bus_id, "VGA")) {
index c339774..940edbf 100644 (file)
@@ -53,14 +53,13 @@ acpi_backlight_cap_match(acpi_handle handle, u32 level, void *context,
                          void **retyurn_value)
 {
        long *cap = context;
-       acpi_handle h_dummy;
 
-       if (ACPI_SUCCESS(acpi_get_handle(handle, "_BCM", &h_dummy)) &&
-           ACPI_SUCCESS(acpi_get_handle(handle, "_BCL", &h_dummy))) {
+       if (acpi_has_method(handle, "_BCM") &&
+           acpi_has_method(handle, "_BCL")) {
                ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found generic backlight "
                                  "support\n"));
                *cap |= ACPI_VIDEO_BACKLIGHT;
-               if (ACPI_FAILURE(acpi_get_handle(handle, "_BQC", &h_dummy)))
+               if (!acpi_has_method(handle, "_BQC"))
                        printk(KERN_WARNING FW_BUG PREFIX "No _BQC method, "
                                "cannot determine initial brightness\n");
                /* We have backlight support, no need to scan further */
@@ -79,22 +78,20 @@ acpi_backlight_cap_match(acpi_handle handle, u32 level, void *context,
  */
 long acpi_is_video_device(acpi_handle handle)
 {
-       acpi_handle h_dummy;
        long video_caps = 0;
 
        /* Is this device able to support video switching ? */
-       if (ACPI_SUCCESS(acpi_get_handle(handle, "_DOD", &h_dummy)) ||
-           ACPI_SUCCESS(acpi_get_handle(handle, "_DOS", &h_dummy)))
+       if (acpi_has_method(handle, "_DOD") || acpi_has_method(handle, "_DOS"))
                video_caps |= ACPI_VIDEO_OUTPUT_SWITCHING;
 
        /* Is this device able to retrieve a video ROM ? */
-       if (ACPI_SUCCESS(acpi_get_handle(handle, "_ROM", &h_dummy)))
+       if (acpi_has_method(handle, "_ROM"))
                video_caps |= ACPI_VIDEO_ROM_AVAILABLE;
 
        /* Is this device able to configure which video head to be POSTed ? */
-       if (ACPI_SUCCESS(acpi_get_handle(handle, "_VPO", &h_dummy)) &&
-           ACPI_SUCCESS(acpi_get_handle(handle, "_GPD", &h_dummy)) &&
-           ACPI_SUCCESS(acpi_get_handle(handle, "_SPD", &h_dummy)))
+       if (acpi_has_method(handle, "_VPO") &&
+           acpi_has_method(handle, "_GPD") &&
+           acpi_has_method(handle, "_SPD"))
                video_caps |= ACPI_VIDEO_DEVICE_POSTING;
 
        /* Only check for backlight functionality if one of the above hit. */
index cf4e702..da8170d 100644 (file)
@@ -947,11 +947,11 @@ static void pata_acpi_set_state(struct ata_port *ap, pm_message_t state)
                        continue;
 
                acpi_bus_set_power(dev_handle, state.event & PM_EVENT_RESUME ?
-                                               ACPI_STATE_D0 : ACPI_STATE_D3);
+                                       ACPI_STATE_D0 : ACPI_STATE_D3_COLD);
        }
 
        if (!(state.event & PM_EVENT_RESUME))
-               acpi_bus_set_power(port_handle, ACPI_STATE_D3);
+               acpi_bus_set_power(port_handle, ACPI_STATE_D3_COLD);
 }
 
 /**
index 1c41722..20fd337 100644 (file)
@@ -289,24 +289,24 @@ static int sata_pmp_configure(struct ata_device *dev, int print_info)
 
        /* Disable sending Early R_OK.
         * With "cached read" HDD testing and multiple ports busy on a SATA
-        * host controller, 3726 PMP will very rarely drop a deferred
+        * host controller, 3x26 PMP will very rarely drop a deferred
         * R_OK that was intended for the host. Symptom will be all
         * 5 drives under test will timeout, get reset, and recover.
         */
-       if (vendor == 0x1095 && devid == 0x3726) {
+       if (vendor == 0x1095 && (devid == 0x3726 || devid == 0x3826)) {
                u32 reg;
 
                err_mask = sata_pmp_read(&ap->link, PMP_GSCR_SII_POL, &reg);
                if (err_mask) {
                        rc = -EIO;
-                       reason = "failed to read Sil3726 Private Register";
+                       reason = "failed to read Sil3x26 Private Register";
                        goto fail;
                }
                reg &= ~0x1;
                err_mask = sata_pmp_write(&ap->link, PMP_GSCR_SII_POL, reg);
                if (err_mask) {
                        rc = -EIO;
-                       reason = "failed to write Sil3726 Private Register";
+                       reason = "failed to write Sil3x26 Private Register";
                        goto fail;
                }
        }
@@ -383,8 +383,8 @@ static void sata_pmp_quirks(struct ata_port *ap)
        u16 devid = sata_pmp_gscr_devid(gscr);
        struct ata_link *link;
 
-       if (vendor == 0x1095 && devid == 0x3726) {
-               /* sil3726 quirks */
+       if (vendor == 0x1095 && (devid == 0x3726 || devid == 0x3826)) {
+               /* sil3x26 quirks */
                ata_for_each_link(link, ap, EDGE) {
                        /* link reports offline after LPM */
                        link->flags |= ATA_LFLAG_NO_LPM;
index 19720a0..851bd3f 100644 (file)
@@ -293,6 +293,7 @@ static void fsl_sata_set_irq_coalescing(struct ata_host *host,
 {
        struct sata_fsl_host_priv *host_priv = host->private_data;
        void __iomem *hcr_base = host_priv->hcr_base;
+       unsigned long flags;
 
        if (count > ICC_MAX_INT_COUNT_THRESHOLD)
                count = ICC_MAX_INT_COUNT_THRESHOLD;
@@ -305,12 +306,12 @@ static void fsl_sata_set_irq_coalescing(struct ata_host *host,
                        (count > ICC_MIN_INT_COUNT_THRESHOLD))
                ticks = ICC_SAFE_INT_TICKS;
 
-       spin_lock(&host->lock);
+       spin_lock_irqsave(&host->lock, flags);
        iowrite32((count << 24 | ticks), hcr_base + ICC);
 
        intr_coalescing_count = count;
        intr_coalescing_ticks = ticks;
-       spin_unlock(&host->lock);
+       spin_unlock_irqrestore(&host->lock, flags);
 
        DPRINTK("interrupt coalescing, count = 0x%x, ticks = %x\n",
                        intr_coalescing_count, intr_coalescing_ticks);
index d047d92..e9a4f46 100644 (file)
@@ -86,11 +86,11 @@ struct ecx_plat_data {
 
 #define SGPIO_SIGNALS                  3
 #define ECX_ACTIVITY_BITS              0x300000
-#define ECX_ACTIVITY_SHIFT             2
+#define ECX_ACTIVITY_SHIFT             0
 #define ECX_LOCATE_BITS                        0x80000
 #define ECX_LOCATE_SHIFT               1
 #define ECX_FAULT_BITS                 0x400000
-#define ECX_FAULT_SHIFT                        0
+#define ECX_FAULT_SHIFT                        2
 static inline int sgpio_bit_shift(struct ecx_plat_data *pdata, u32 port,
                                u32 shift)
 {
index 5a9b656..9f098a8 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/sched.h>
 #include <linux/async.h>
 #include <linux/suspend.h>
+#include <trace/events/power.h>
 #include <linux/cpuidle.h>
 #include "../base.h"
 #include "power.h"
@@ -56,6 +57,30 @@ static pm_message_t pm_transition;
 
 static int async_error;
 
+static char *pm_verb(int event)
+{
+       switch (event) {
+       case PM_EVENT_SUSPEND:
+               return "suspend";
+       case PM_EVENT_RESUME:
+               return "resume";
+       case PM_EVENT_FREEZE:
+               return "freeze";
+       case PM_EVENT_QUIESCE:
+               return "quiesce";
+       case PM_EVENT_HIBERNATE:
+               return "hibernate";
+       case PM_EVENT_THAW:
+               return "thaw";
+       case PM_EVENT_RESTORE:
+               return "restore";
+       case PM_EVENT_RECOVER:
+               return "recover";
+       default:
+               return "(unknown PM event)";
+       }
+}
+
 /**
  * device_pm_sleep_init - Initialize system suspend-related device fields.
  * @dev: Device object being initialized.
@@ -172,16 +197,21 @@ static ktime_t initcall_debug_start(struct device *dev)
 }
 
 static void initcall_debug_report(struct device *dev, ktime_t calltime,
-                                 int error)
+                                 int error, pm_message_t state, char *info)
 {
-       ktime_t delta, rettime;
+       ktime_t rettime;
+       s64 nsecs;
+
+       rettime = ktime_get();
+       nsecs = (s64) ktime_to_ns(ktime_sub(rettime, calltime));
 
        if (pm_print_times_enabled) {
-               rettime = ktime_get();
-               delta = ktime_sub(rettime, calltime);
                pr_info("call %s+ returned %d after %Ld usecs\n", dev_name(dev),
-                       error, (unsigned long long)ktime_to_ns(delta) >> 10);
+                       error, (unsigned long long)nsecs >> 10);
        }
+
+       trace_device_pm_report_time(dev, info, nsecs, pm_verb(state.event),
+                                   error);
 }
 
 /**
@@ -309,30 +339,6 @@ static pm_callback_t pm_noirq_op(const struct dev_pm_ops *ops, pm_message_t stat
        return NULL;
 }
 
-static char *pm_verb(int event)
-{
-       switch (event) {
-       case PM_EVENT_SUSPEND:
-               return "suspend";
-       case PM_EVENT_RESUME:
-               return "resume";
-       case PM_EVENT_FREEZE:
-               return "freeze";
-       case PM_EVENT_QUIESCE:
-               return "quiesce";
-       case PM_EVENT_HIBERNATE:
-               return "hibernate";
-       case PM_EVENT_THAW:
-               return "thaw";
-       case PM_EVENT_RESTORE:
-               return "restore";
-       case PM_EVENT_RECOVER:
-               return "recover";
-       default:
-               return "(unknown PM event)";
-       }
-}
-
 static void pm_dev_dbg(struct device *dev, pm_message_t state, char *info)
 {
        dev_dbg(dev, "%s%s%s\n", info, pm_verb(state.event),
@@ -379,7 +385,7 @@ static int dpm_run_callback(pm_callback_t cb, struct device *dev,
        error = cb(dev);
        suspend_report_result(cb, error);
 
-       initcall_debug_report(dev, calltime, error);
+       initcall_debug_report(dev, calltime, error, state, info);
 
        return error;
 }
@@ -1027,7 +1033,8 @@ EXPORT_SYMBOL_GPL(dpm_suspend_end);
  * @cb: Suspend callback to execute.
  */
 static int legacy_suspend(struct device *dev, pm_message_t state,
-                         int (*cb)(struct device *dev, pm_message_t state))
+                         int (*cb)(struct device *dev, pm_message_t state),
+                         char *info)
 {
        int error;
        ktime_t calltime;
@@ -1037,7 +1044,7 @@ static int legacy_suspend(struct device *dev, pm_message_t state,
        error = cb(dev, state);
        suspend_report_result(cb, error);
 
-       initcall_debug_report(dev, calltime, error);
+       initcall_debug_report(dev, calltime, error, state, info);
 
        return error;
 }
@@ -1097,7 +1104,8 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
                        goto Run;
                } else if (dev->class->suspend) {
                        pm_dev_dbg(dev, state, "legacy class ");
-                       error = legacy_suspend(dev, state, dev->class->suspend);
+                       error = legacy_suspend(dev, state, dev->class->suspend,
+                                               "legacy class ");
                        goto End;
                }
        }
@@ -1108,7 +1116,8 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
                        callback = pm_op(dev->bus->pm, state);
                } else if (dev->bus->suspend) {
                        pm_dev_dbg(dev, state, "legacy bus ");
-                       error = legacy_suspend(dev, state, dev->bus->suspend);
+                       error = legacy_suspend(dev, state, dev->bus->suspend,
+                                               "legacy bus ");
                        goto End;
                }
        }
index c8ec186..ef89897 100644 (file)
@@ -460,6 +460,7 @@ int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
        srcu_notifier_call_chain(&dev_opp->head, OPP_EVENT_ADD, new_opp);
        return 0;
 }
+EXPORT_SYMBOL_GPL(opp_add);
 
 /**
  * opp_set_availability() - helper to set the availability of an opp
index bf2349d..7cc1fe2 100644 (file)
@@ -876,11 +876,6 @@ found:
        if (useinput)
                sonypi_report_input_event(event);
 
-#ifdef CONFIG_ACPI
-       if (sonypi_acpi_device)
-               acpi_bus_generate_proc_event(sonypi_acpi_device, 1, event);
-#endif
-
        kfifo_in_locked(&sonypi_device.fifo, (unsigned char *)&event,
                        sizeof(event), &sonypi_device.fifo_lock);
        kill_fasync(&sonypi_device.fifo_async, SIGIO, POLL_IN);
index 0e2cd5c..b3fb81d 100644 (file)
@@ -1,5 +1,6 @@
+menu "CPU Idle"
 
-menuconfig CPU_IDLE
+config CPU_IDLE
        bool "CPU idle PM support"
        default y if ACPI || PPC_PSERIES
        select CPU_IDLE_GOV_LADDER if (!NO_HZ && !NO_HZ_IDLE)
@@ -29,20 +30,13 @@ config CPU_IDLE_GOV_MENU
        bool "Menu governor (for tickless system)"
        default y
 
-config CPU_IDLE_CALXEDA
-       bool "CPU Idle Driver for Calxeda processors"
-       depends on ARCH_HIGHBANK
-       select ARM_CPU_SUSPEND
-       help
-         Select this to enable cpuidle on Calxeda processors.
-
-config CPU_IDLE_ZYNQ
-       bool "CPU Idle Driver for Xilinx Zynq processors"
-       depends on ARCH_ZYNQ
-       help
-         Select this to enable cpuidle on Xilinx Zynq processors.
+menu "ARM CPU Idle Drivers"
+depends on ARM
+source "drivers/cpuidle/Kconfig.arm"
+endmenu
 
 endif
 
 config ARCH_NEEDS_CPU_IDLE_COUPLED
        def_bool n
+endmenu
diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm
new file mode 100644 (file)
index 0000000..b330219
--- /dev/null
@@ -0,0 +1,29 @@
+#
+# ARM CPU Idle drivers
+#
+
+config ARM_HIGHBANK_CPUIDLE
+       bool "CPU Idle Driver for Calxeda processors"
+       depends on ARCH_HIGHBANK
+       select ARM_CPU_SUSPEND
+       help
+         Select this to enable cpuidle on Calxeda processors.
+
+config ARM_KIRKWOOD_CPUIDLE
+       bool "CPU Idle Driver for Marvell Kirkwood SoCs"
+       depends on ARCH_KIRKWOOD
+       help
+         This adds the CPU Idle driver for Marvell Kirkwood SoCs.
+
+config ARM_ZYNQ_CPUIDLE
+       bool "CPU Idle Driver for Xilinx Zynq processors"
+       depends on ARCH_ZYNQ
+       help
+         Select this to enable cpuidle on Xilinx Zynq processors.
+
+config ARM_U8500_CPUIDLE
+       bool "Cpu Idle Driver for the ST-E u8500 processors"
+       depends on ARCH_U8500
+       help
+         Select this to enable cpuidle for ST-E u8500 processors
+
index 8767a7b..0b9d200 100644 (file)
@@ -5,6 +5,9 @@
 obj-y += cpuidle.o driver.o governor.o sysfs.o governors/
 obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o
 
-obj-$(CONFIG_CPU_IDLE_CALXEDA) += cpuidle-calxeda.o
-obj-$(CONFIG_ARCH_KIRKWOOD) += cpuidle-kirkwood.o
-obj-$(CONFIG_CPU_IDLE_ZYNQ) += cpuidle-zynq.o
+##################################################################################
+# ARM SoC drivers
+obj-$(CONFIG_ARM_HIGHBANK_CPUIDLE)     += cpuidle-calxeda.o
+obj-$(CONFIG_ARM_KIRKWOOD_CPUIDLE)     += cpuidle-kirkwood.o
+obj-$(CONFIG_ARM_ZYNQ_CPUIDLE)         += cpuidle-zynq.o
+obj-$(CONFIG_ARM_U8500_CPUIDLE)         += cpuidle-ux500.o
index 0e6e408..3460584 100644 (file)
@@ -35,7 +35,7 @@
 #include <asm/cp15.h>
 
 extern void highbank_set_cpu_jump(int cpu, void *jump_addr);
-extern void *scu_base_addr;
+extern void __iomem *scu_base_addr;
 
 static noinline void calxeda_idle_restore(void)
 {
index 521b0a7..41ba843 100644 (file)
@@ -60,9 +60,6 @@ static int kirkwood_cpuidle_probe(struct platform_device *pdev)
        struct resource *res;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (res == NULL)
-               return -EINVAL;
-
        ddr_operation_base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(ddr_operation_base))
                return PTR_ERR(ddr_operation_base);
@@ -70,7 +67,7 @@ static int kirkwood_cpuidle_probe(struct platform_device *pdev)
        return cpuidle_register(&kirkwood_idle_driver, NULL);
 }
 
-int kirkwood_cpuidle_remove(struct platform_device *pdev)
+static int kirkwood_cpuidle_remove(struct platform_device *pdev)
 {
        cpuidle_unregister(&kirkwood_idle_driver);
        return 0;
diff --git a/drivers/cpuidle/cpuidle-ux500.c b/drivers/cpuidle/cpuidle-ux500.c
new file mode 100644 (file)
index 0000000..e056465
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2012 Linaro : Daniel Lezcano <daniel.lezcano@linaro.org> (IBM)
+ *
+ * Based on the work of Rickard Andersson <rickard.andersson@stericsson.com>
+ * and Jonas Aaberg <jonas.aberg@stericsson.com>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/cpuidle.h>
+#include <linux/spinlock.h>
+#include <linux/atomic.h>
+#include <linux/smp.h>
+#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/platform_data/arm-ux500-pm.h>
+#include <linux/platform_device.h>
+
+#include <asm/cpuidle.h>
+#include <asm/proc-fns.h>
+
+static atomic_t master = ATOMIC_INIT(0);
+static DEFINE_SPINLOCK(master_lock);
+
+static inline int ux500_enter_idle(struct cpuidle_device *dev,
+                                  struct cpuidle_driver *drv, int index)
+{
+       int this_cpu = smp_processor_id();
+       bool recouple = false;
+
+       if (atomic_inc_return(&master) == num_online_cpus()) {
+
+               /* With this lock, we prevent the other cpu to exit and enter
+                * this function again and become the master */
+               if (!spin_trylock(&master_lock))
+                       goto wfi;
+
+               /* decouple the gic from the A9 cores */
+               if (prcmu_gic_decouple()) {
+                       spin_unlock(&master_lock);
+                       goto out;
+               }
+
+               /* If an error occur, we will have to recouple the gic
+                * manually */
+               recouple = true;
+
+               /* At this state, as the gic is decoupled, if the other
+                * cpu is in WFI, we have the guarantee it won't be wake
+                * up, so we can safely go to retention */
+               if (!prcmu_is_cpu_in_wfi(this_cpu ? 0 : 1))
+                       goto out;
+
+               /* The prcmu will be in charge of watching the interrupts
+                * and wake up the cpus */
+               if (prcmu_copy_gic_settings())
+                       goto out;
+
+               /* Check in the meantime an interrupt did
+                * not occur on the gic ... */
+               if (prcmu_gic_pending_irq())
+                       goto out;
+
+               /* ... and the prcmu */
+               if (prcmu_pending_irq())
+                       goto out;
+
+               /* Go to the retention state, the prcmu will wait for the
+                * cpu to go WFI and this is what happens after exiting this
+                * 'master' critical section */
+               if (prcmu_set_power_state(PRCMU_AP_IDLE, true, true))
+                       goto out;
+
+               /* When we switch to retention, the prcmu is in charge
+                * of recoupling the gic automatically */
+               recouple = false;
+
+               spin_unlock(&master_lock);
+       }
+wfi:
+       cpu_do_idle();
+out:
+       atomic_dec(&master);
+
+       if (recouple) {
+               prcmu_gic_recouple();
+               spin_unlock(&master_lock);
+       }
+
+       return index;
+}
+
+static struct cpuidle_driver ux500_idle_driver = {
+       .name = "ux500_idle",
+       .owner = THIS_MODULE,
+       .states = {
+               ARM_CPUIDLE_WFI_STATE,
+               {
+                       .enter            = ux500_enter_idle,
+                       .exit_latency     = 70,
+                       .target_residency = 260,
+                       .flags            = CPUIDLE_FLAG_TIME_VALID |
+                                           CPUIDLE_FLAG_TIMER_STOP,
+                       .name             = "ApIdle",
+                       .desc             = "ARM Retention",
+               },
+       },
+       .safe_state_index = 0,
+       .state_count = 2,
+};
+
+static int __init dbx500_cpuidle_probe(struct platform_device *pdev)
+{
+       /* Configure wake up reasons */
+       prcmu_enable_wakeups(PRCMU_WAKEUP(ARM) | PRCMU_WAKEUP(RTC) |
+                            PRCMU_WAKEUP(ABB));
+
+       return cpuidle_register(&ux500_idle_driver, NULL);
+}
+
+static struct platform_driver dbx500_cpuidle_plat_driver = {
+       .driver = {
+               .name = "cpuidle-dbx500",
+               .owner = THIS_MODULE,
+       },
+       .probe = dbx500_cpuidle_probe,
+};
+
+module_platform_driver(dbx500_cpuidle_plat_driver);
index fdc432f..d75040d 100644 (file)
@@ -42,8 +42,6 @@ void disable_cpuidle(void)
        off = 1;
 }
 
-static int __cpuidle_register_device(struct cpuidle_device *dev);
-
 /**
  * cpuidle_play_dead - cpu off-lining
  *
@@ -278,7 +276,7 @@ static void poll_idle_init(struct cpuidle_driver *drv) {}
  */
 int cpuidle_enable_device(struct cpuidle_device *dev)
 {
-       int ret, i;
+       int ret;
        struct cpuidle_driver *drv;
 
        if (!dev)
@@ -292,15 +290,12 @@ int cpuidle_enable_device(struct cpuidle_device *dev)
        if (!drv || !cpuidle_curr_governor)
                return -EIO;
 
+       if (!dev->registered)
+               return -EINVAL;
+
        if (!dev->state_count)
                dev->state_count = drv->state_count;
 
-       if (dev->registered == 0) {
-               ret = __cpuidle_register_device(dev);
-               if (ret)
-                       return ret;
-       }
-
        poll_idle_init(drv);
 
        ret = cpuidle_add_device_sysfs(dev);
@@ -311,12 +306,6 @@ int cpuidle_enable_device(struct cpuidle_device *dev)
            (ret = cpuidle_curr_governor->enable(drv, dev)))
                goto fail_sysfs;
 
-       for (i = 0; i < dev->state_count; i++) {
-               dev->states_usage[i].usage = 0;
-               dev->states_usage[i].time = 0;
-       }
-       dev->last_residency = 0;
-
        smp_wmb();
 
        dev->enabled = 1;
@@ -360,6 +349,23 @@ void cpuidle_disable_device(struct cpuidle_device *dev)
 
 EXPORT_SYMBOL_GPL(cpuidle_disable_device);
 
+static void __cpuidle_unregister_device(struct cpuidle_device *dev)
+{
+       struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
+
+       list_del(&dev->device_list);
+       per_cpu(cpuidle_devices, dev->cpu) = NULL;
+       module_put(drv->owner);
+}
+
+static int __cpuidle_device_init(struct cpuidle_device *dev)
+{
+       memset(dev->states_usage, 0, sizeof(dev->states_usage));
+       dev->last_residency = 0;
+
+       return 0;
+}
+
 /**
  * __cpuidle_register_device - internal register function called before register
  * and enable routines
@@ -377,24 +383,15 @@ static int __cpuidle_register_device(struct cpuidle_device *dev)
 
        per_cpu(cpuidle_devices, dev->cpu) = dev;
        list_add(&dev->device_list, &cpuidle_detected_devices);
-       ret = cpuidle_add_sysfs(dev);
-       if (ret)
-               goto err_sysfs;
 
        ret = cpuidle_coupled_register_device(dev);
-       if (ret)
-               goto err_coupled;
+       if (ret) {
+               __cpuidle_unregister_device(dev);
+               return ret;
+       }
 
        dev->registered = 1;
        return 0;
-
-err_coupled:
-       cpuidle_remove_sysfs(dev);
-err_sysfs:
-       list_del(&dev->device_list);
-       per_cpu(cpuidle_devices, dev->cpu) = NULL;
-       module_put(drv->owner);
-       return ret;
 }
 
 /**
@@ -403,25 +400,44 @@ err_sysfs:
  */
 int cpuidle_register_device(struct cpuidle_device *dev)
 {
-       int ret;
+       int ret = -EBUSY;
 
        if (!dev)
                return -EINVAL;
 
        mutex_lock(&cpuidle_lock);
 
-       if ((ret = __cpuidle_register_device(dev))) {
-               mutex_unlock(&cpuidle_lock);
-               return ret;
-       }
+       if (dev->registered)
+               goto out_unlock;
+
+       ret = __cpuidle_device_init(dev);
+       if (ret)
+               goto out_unlock;
+
+       ret = __cpuidle_register_device(dev);
+       if (ret)
+               goto out_unlock;
+
+       ret = cpuidle_add_sysfs(dev);
+       if (ret)
+               goto out_unregister;
+
+       ret = cpuidle_enable_device(dev);
+       if (ret)
+               goto out_sysfs;
 
-       cpuidle_enable_device(dev);
        cpuidle_install_idle_handler();
 
+out_unlock:
        mutex_unlock(&cpuidle_lock);
 
-       return 0;
+       return ret;
 
+out_sysfs:
+       cpuidle_remove_sysfs(dev);
+out_unregister:
+       __cpuidle_unregister_device(dev);
+       goto out_unlock;
 }
 
 EXPORT_SYMBOL_GPL(cpuidle_register_device);
@@ -432,8 +448,6 @@ EXPORT_SYMBOL_GPL(cpuidle_register_device);
  */
 void cpuidle_unregister_device(struct cpuidle_device *dev)
 {
-       struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
-
        if (dev->registered == 0)
                return;
 
@@ -442,14 +456,12 @@ void cpuidle_unregister_device(struct cpuidle_device *dev)
        cpuidle_disable_device(dev);
 
        cpuidle_remove_sysfs(dev);
-       list_del(&dev->device_list);
-       per_cpu(cpuidle_devices, dev->cpu) = NULL;
+
+       __cpuidle_unregister_device(dev);
 
        cpuidle_coupled_unregister_device(dev);
 
        cpuidle_resume_and_unlock();
-
-       module_put(drv->owner);
 }
 
 EXPORT_SYMBOL_GPL(cpuidle_unregister_device);
index 9b78405..9f08e8c 100644 (file)
@@ -192,14 +192,4 @@ static int __init init_ladder(void)
        return cpuidle_register_governor(&ladder_governor);
 }
 
-/**
- * exit_ladder - exits the governor
- */
-static void __exit exit_ladder(void)
-{
-       cpuidle_unregister_governor(&ladder_governor);
-}
-
-MODULE_LICENSE("GPL");
-module_init(init_ladder);
-module_exit(exit_ladder);
+postcore_initcall(init_ladder);
index bc580b6..cf7f2f0 100644 (file)
 #include <linux/math64.h>
 #include <linux/module.h>
 
+/*
+ * Please note when changing the tuning values:
+ * If (MAX_INTERESTING-1) * RESOLUTION > UINT_MAX, the result of
+ * a scaling operation multiplication may overflow on 32 bit platforms.
+ * In that case, #define RESOLUTION as ULL to get 64 bit result:
+ * #define RESOLUTION 1024ULL
+ *
+ * The default values do not overflow.
+ */
 #define BUCKETS 12
 #define INTERVALS 8
 #define RESOLUTION 1024
@@ -114,11 +123,11 @@ struct menu_device {
        int             needs_update;
 
        unsigned int    expected_us;
-       u64             predicted_us;
+       unsigned int    predicted_us;
        unsigned int    exit_us;
        unsigned int    bucket;
-       u64             correction_factor[BUCKETS];
-       u32             intervals[INTERVALS];
+       unsigned int    correction_factor[BUCKETS];
+       unsigned int    intervals[INTERVALS];
        int             interval_ptr;
 };
 
@@ -199,16 +208,20 @@ static u64 div_round64(u64 dividend, u32 divisor)
  */
 static void get_typical_interval(struct menu_device *data)
 {
-       int i = 0, divisor = 0;
-       uint64_t max = 0, avg = 0, stddev = 0;
-       int64_t thresh = LLONG_MAX; /* Discard outliers above this value. */
+       int i, divisor;
+       unsigned int max, thresh;
+       uint64_t avg, stddev;
+
+       thresh = UINT_MAX; /* Discard outliers above this value */
 
 again:
 
-       /* first calculate average and standard deviation of the past */
-       max = avg = divisor = stddev = 0;
+       /* First calculate the average of past intervals */
+       max = 0;
+       avg = 0;
+       divisor = 0;
        for (i = 0; i < INTERVALS; i++) {
-               int64_t value = data->intervals[i];
+               unsigned int value = data->intervals[i];
                if (value <= thresh) {
                        avg += value;
                        divisor++;
@@ -218,15 +231,38 @@ again:
        }
        do_div(avg, divisor);
 
+       /* Then try to determine standard deviation */
+       stddev = 0;
        for (i = 0; i < INTERVALS; i++) {
-               int64_t value = data->intervals[i];
+               unsigned int value = data->intervals[i];
                if (value <= thresh) {
                        int64_t diff = value - avg;
                        stddev += diff * diff;
                }
        }
        do_div(stddev, divisor);
-       stddev = int_sqrt(stddev);
+       /*
+        * The typical interval is obtained when standard deviation is small
+        * or standard deviation is small compared to the average interval.
+        *
+        * int_sqrt() formal parameter type is unsigned long. When the
+        * greatest difference to an outlier exceeds ~65 ms * sqrt(divisor)
+        * the resulting squared standard deviation exceeds the input domain
+        * of int_sqrt on platforms where unsigned long is 32 bits in size.
+        * In such case reject the candidate average.
+        *
+        * Use this result only if there is no timer to wake us up sooner.
+        */
+       if (likely(stddev <= ULONG_MAX)) {
+               stddev = int_sqrt(stddev);
+               if (((avg > stddev * 6) && (divisor * 4 >= INTERVALS * 3))
+                                                       || stddev <= 20) {
+                       if (data->expected_us > avg)
+                               data->predicted_us = avg;
+                       return;
+               }
+       }
+
        /*
         * If we have outliers to the upside in our distribution, discard
         * those by setting the threshold to exclude these outliers, then
@@ -235,20 +271,12 @@ again:
         *
         * This can deal with workloads that have long pauses interspersed
         * with sporadic activity with a bunch of short pauses.
-        *
-        * The typical interval is obtained when standard deviation is small
-        * or standard deviation is small compared to the average interval.
         */
-       if (((avg > stddev * 6) && (divisor * 4 >= INTERVALS * 3))
-                                                       || stddev <= 20) {
-               data->predicted_us = avg;
+       if ((divisor * 4) <= INTERVALS * 3)
                return;
 
-       } else if ((divisor * 4) > INTERVALS * 3) {
-               /* Exclude the max interval */
-               thresh = max - 1;
-               goto again;
-       }
+       thresh = max - 1;
+       goto again;
 }
 
 /**
@@ -293,8 +321,13 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
        if (data->correction_factor[data->bucket] == 0)
                data->correction_factor[data->bucket] = RESOLUTION * DECAY;
 
-       /* Make sure to round up for half microseconds */
-       data->predicted_us = div_round64(data->expected_us * data->correction_factor[data->bucket],
+       /*
+        * Force the result of multiplication to be 64 bits even if both
+        * operands are 32 bits.
+        * Make sure to round up for half microseconds.
+        */
+       data->predicted_us = div_round64((uint64_t)data->expected_us *
+                                        data->correction_factor[data->bucket],
                                         RESOLUTION * DECAY);
 
        get_typical_interval(data);
@@ -360,7 +393,7 @@ static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev)
        unsigned int last_idle_us = cpuidle_get_last_residency(dev);
        struct cpuidle_state *target = &drv->states[last_idx];
        unsigned int measured_us;
-       u64 new_factor;
+       unsigned int new_factor;
 
        /*
         * Ugh, this idle state doesn't support residency measurements, so we
@@ -381,10 +414,9 @@ static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev)
                measured_us -= data->exit_us;
 
 
-       /* update our correction ratio */
-
-       new_factor = data->correction_factor[data->bucket]
-                       * (DECAY - 1) / DECAY;
+       /* Update our correction ratio */
+       new_factor = data->correction_factor[data->bucket];
+       new_factor -= new_factor / DECAY;
 
        if (data->expected_us > 0 && measured_us < MAX_INTERESTING)
                new_factor += RESOLUTION * measured_us / data->expected_us;
@@ -397,9 +429,11 @@ static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev)
 
        /*
         * We don't want 0 as factor; we always want at least
-        * a tiny bit of estimated time.
+        * a tiny bit of estimated time. Fortunately, due to rounding,
+        * new_factor will stay nonzero regardless of measured_us values
+        * and the compiler can eliminate this test as long as DECAY > 1.
         */
-       if (new_factor == 0)
+       if (DECAY == 1 && unlikely(new_factor == 0))
                new_factor = 1;
 
        data->correction_factor[data->bucket] = new_factor;
@@ -442,14 +476,4 @@ static int __init init_menu(void)
        return cpuidle_register_governor(&menu_governor);
 }
 
-/**
- * exit_menu - exits the governor
- */
-static void __exit exit_menu(void)
-{
-       cpuidle_unregister_governor(&menu_governor);
-}
-
-MODULE_LICENSE("GPL");
-module_init(init_menu);
-module_exit(exit_menu);
+postcore_initcall(init_menu);
index 428754a..8739cc0 100644 (file)
 #include <linux/sysfs.h>
 #include <linux/slab.h>
 #include <linux/cpu.h>
+#include <linux/completion.h>
 #include <linux/capability.h>
 #include <linux/device.h>
+#include <linux/kobject.h>
 
 #include "cpuidle.h"
 
@@ -33,7 +35,8 @@ static ssize_t show_available_governors(struct device *dev,
 
        mutex_lock(&cpuidle_lock);
        list_for_each_entry(tmp, &cpuidle_governors, governor_list) {
-               if (i >= (ssize_t) ((PAGE_SIZE/sizeof(char)) - CPUIDLE_NAME_LEN - 2))
+               if (i >= (ssize_t) ((PAGE_SIZE/sizeof(char)) -
+                                   CPUIDLE_NAME_LEN - 2))
                        goto out;
                i += scnprintf(&buf[i], CPUIDLE_NAME_LEN, "%s ", tmp->name);
        }
@@ -166,13 +169,28 @@ struct cpuidle_attr {
 #define define_one_rw(_name, show, store) \
        static struct cpuidle_attr attr_##_name = __ATTR(_name, 0644, show, store)
 
-#define kobj_to_cpuidledev(k) container_of(k, struct cpuidle_device, kobj)
 #define attr_to_cpuidleattr(a) container_of(a, struct cpuidle_attr, attr)
-static ssize_t cpuidle_show(struct kobject * kobj, struct attribute * attr ,char * buf)
+
+struct cpuidle_device_kobj {
+       struct cpuidle_device *dev;
+       struct completion kobj_unregister;
+       struct kobject kobj;
+};
+
+static inline struct cpuidle_device *to_cpuidle_device(struct kobject *kobj)
+{
+       struct cpuidle_device_kobj *kdev =
+               container_of(kobj, struct cpuidle_device_kobj, kobj);
+
+       return kdev->dev;
+}
+
+static ssize_t cpuidle_show(struct kobject *kobj, struct attribute *attr,
+                           char *buf)
 {
        int ret = -EIO;
-       struct cpuidle_device *dev = kobj_to_cpuidledev(kobj);
-       struct cpuidle_attr * cattr = attr_to_cpuidleattr(attr);
+       struct cpuidle_device *dev = to_cpuidle_device(kobj);
+       struct cpuidle_attr *cattr = attr_to_cpuidleattr(attr);
 
        if (cattr->show) {
                mutex_lock(&cpuidle_lock);
@@ -182,12 +200,12 @@ static ssize_t cpuidle_show(struct kobject * kobj, struct attribute * attr ,char
        return ret;
 }
 
-static ssize_t cpuidle_store(struct kobject * kobj, struct attribute * attr,
-                    const char * buf, size_t count)
+static ssize_t cpuidle_store(struct kobject *kobj, struct attribute *attr,
+                            const char *buf, size_t count)
 {
        int ret = -EIO;
-       struct cpuidle_device *dev = kobj_to_cpuidledev(kobj);
-       struct cpuidle_attr * cattr = attr_to_cpuidleattr(attr);
+       struct cpuidle_device *dev = to_cpuidle_device(kobj);
+       struct cpuidle_attr *cattr = attr_to_cpuidleattr(attr);
 
        if (cattr->store) {
                mutex_lock(&cpuidle_lock);
@@ -204,9 +222,10 @@ static const struct sysfs_ops cpuidle_sysfs_ops = {
 
 static void cpuidle_sysfs_release(struct kobject *kobj)
 {
-       struct cpuidle_device *dev = kobj_to_cpuidledev(kobj);
+       struct cpuidle_device_kobj *kdev =
+               container_of(kobj, struct cpuidle_device_kobj, kobj);
 
-       complete(&dev->kobj_unregister);
+       complete(&kdev->kobj_unregister);
 }
 
 static struct kobj_type ktype_cpuidle = {
@@ -237,8 +256,8 @@ static ssize_t show_state_##_name(struct cpuidle_state *state, \
 
 #define define_store_state_ull_function(_name) \
 static ssize_t store_state_##_name(struct cpuidle_state *state, \
-               struct cpuidle_state_usage *state_usage, \
-               const char *buf, size_t size) \
+                                  struct cpuidle_state_usage *state_usage, \
+                                  const char *buf, size_t size)        \
 { \
        unsigned long long value; \
        int err; \
@@ -256,14 +275,16 @@ static ssize_t store_state_##_name(struct cpuidle_state *state, \
 
 #define define_show_state_ull_function(_name) \
 static ssize_t show_state_##_name(struct cpuidle_state *state, \
-                       struct cpuidle_state_usage *state_usage, char *buf) \
+                                 struct cpuidle_state_usage *state_usage, \
+                                 char *buf)                            \
 { \
        return sprintf(buf, "%llu\n", state_usage->_name);\
 }
 
 #define define_show_state_str_function(_name) \
 static ssize_t show_state_##_name(struct cpuidle_state *state, \
-                       struct cpuidle_state_usage *state_usage, char *buf) \
+                                 struct cpuidle_state_usage *state_usage, \
+                                 char *buf)                            \
 { \
        if (state->_name[0] == '\0')\
                return sprintf(buf, "<null>\n");\
@@ -309,8 +330,9 @@ struct cpuidle_state_kobj {
 #define kobj_to_state(k) (kobj_to_state_obj(k)->state)
 #define kobj_to_state_usage(k) (kobj_to_state_obj(k)->state_usage)
 #define attr_to_stateattr(a) container_of(a, struct cpuidle_state_attr, attr)
-static ssize_t cpuidle_state_show(struct kobject * kobj,
-       struct attribute * attr ,char * buf)
+
+static ssize_t cpuidle_state_show(struct kobject *kobj, struct attribute *attr,
+                                 char * buf)
 {
        int ret = -EIO;
        struct cpuidle_state *state = kobj_to_state(kobj);
@@ -323,8 +345,8 @@ static ssize_t cpuidle_state_show(struct kobject * kobj,
        return ret;
 }
 
-static ssize_t cpuidle_state_store(struct kobject *kobj,
-       struct attribute *attr, const char *buf, size_t size)
+static ssize_t cpuidle_state_store(struct kobject *kobj, struct attribute *attr,
+                                  const char *buf, size_t size)
 {
        int ret = -EIO;
        struct cpuidle_state *state = kobj_to_state(kobj);
@@ -371,6 +393,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device)
 {
        int i, ret = -ENOMEM;
        struct cpuidle_state_kobj *kobj;
+       struct cpuidle_device_kobj *kdev = device->kobj_dev;
        struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device);
 
        /* state statistics */
@@ -383,7 +406,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device)
                init_completion(&kobj->kobj_unregister);
 
                ret = kobject_init_and_add(&kobj->kobj, &ktype_state_cpuidle,
-                                          &device->kobj, "state%d", i);
+                                          &kdev->kobj, "state%d", i);
                if (ret) {
                        kfree(kobj);
                        goto error_state;
@@ -449,8 +472,8 @@ static void cpuidle_driver_sysfs_release(struct kobject *kobj)
        complete(&driver_kobj->kobj_unregister);
 }
 
-static ssize_t cpuidle_driver_show(struct kobject *kobj, struct attribute * attr,
-                                  char * buf)
+static ssize_t cpuidle_driver_show(struct kobject *kobj, struct attribute *attr,
+                                  char *buf)
 {
        int ret = -EIO;
        struct cpuidle_driver_kobj *driver_kobj = kobj_to_driver_kobj(kobj);
@@ -500,6 +523,7 @@ static struct kobj_type ktype_driver_cpuidle = {
 static int cpuidle_add_driver_sysfs(struct cpuidle_device *dev)
 {
        struct cpuidle_driver_kobj *kdrv;
+       struct cpuidle_device_kobj *kdev = dev->kobj_dev;
        struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
        int ret;
 
@@ -511,7 +535,7 @@ static int cpuidle_add_driver_sysfs(struct cpuidle_device *dev)
        init_completion(&kdrv->kobj_unregister);
 
        ret = kobject_init_and_add(&kdrv->kobj, &ktype_driver_cpuidle,
-                                  &dev->kobj, "driver");
+                                  &kdev->kobj, "driver");
        if (ret) {
                kfree(kdrv);
                return ret;
@@ -580,16 +604,28 @@ void cpuidle_remove_device_sysfs(struct cpuidle_device *device)
  */
 int cpuidle_add_sysfs(struct cpuidle_device *dev)
 {
+       struct cpuidle_device_kobj *kdev;
        struct device *cpu_dev = get_cpu_device((unsigned long)dev->cpu);
        int error;
 
-       init_completion(&dev->kobj_unregister);
+       kdev = kzalloc(sizeof(*kdev), GFP_KERNEL);
+       if (!kdev)
+               return -ENOMEM;
+       kdev->dev = dev;
+       dev->kobj_dev = kdev;
 
-       error = kobject_init_and_add(&dev->kobj, &ktype_cpuidle, &cpu_dev->kobj,
-                                    "cpuidle");
-       if (!error)
-               kobject_uevent(&dev->kobj, KOBJ_ADD);
-       return error;
+       init_completion(&kdev->kobj_unregister);
+
+       error = kobject_init_and_add(&kdev->kobj, &ktype_cpuidle, &cpu_dev->kobj,
+                                  "cpuidle");
+       if (error) {
+               kfree(kdev);
+               return error;
+       }
+
+       kobject_uevent(&kdev->kobj, KOBJ_ADD);
+
+       return 0;
 }
 
 /**
@@ -598,6 +634,9 @@ int cpuidle_add_sysfs(struct cpuidle_device *dev)
  */
 void cpuidle_remove_sysfs(struct cpuidle_device *dev)
 {
-       kobject_put(&dev->kobj);
-       wait_for_completion(&dev->kobj_unregister);
+       struct cpuidle_device_kobj *kdev = dev->kobj_dev;
+
+       kobject_put(&kdev->kobj);
+       wait_for_completion(&kdev->kobj_unregister);
+       kfree(kdev);
 }
index 19e3660..3bc8414 100644 (file)
@@ -500,7 +500,8 @@ static bool psb_intel_sdvo_read_response(struct psb_intel_sdvo *psb_intel_sdvo,
                                  &status))
                goto log_fail;
 
-       while (status == SDVO_CMD_STATUS_PENDING && retry--) {
+       while ((status == SDVO_CMD_STATUS_PENDING ||
+               status == SDVO_CMD_STATUS_TARGET_NOT_SPECIFIED) && retry--) {
                udelay(15);
                if (!psb_intel_sdvo_read_byte(psb_intel_sdvo,
                                          SDVO_I2C_CMD_STATUS,
index dc53a52..9e65783 100644 (file)
@@ -85,9 +85,17 @@ static void i915_gem_unmap_dma_buf(struct dma_buf_attachment *attachment,
                                   struct sg_table *sg,
                                   enum dma_data_direction dir)
 {
+       struct drm_i915_gem_object *obj = attachment->dmabuf->priv;
+
+       mutex_lock(&obj->base.dev->struct_mutex);
+
        dma_unmap_sg(attachment->dev, sg->sgl, sg->nents, dir);
        sg_free_table(sg);
        kfree(sg);
+
+       i915_gem_object_unpin_pages(obj);
+
+       mutex_unlock(&obj->base.dev->struct_mutex);
 }
 
 static void i915_gem_dmabuf_release(struct dma_buf *dma_buf)
index 6f51429..53cddd9 100644 (file)
                                        will not assert AGPBUSY# and will only
                                        be delivered when out of C3. */
 #define   INSTPM_FORCE_ORDERING                                (1<<7) /* GEN6+ */
+#define   INSTPM_TLB_INVALIDATE        (1<<9)
+#define   INSTPM_SYNC_FLUSH    (1<<5)
 #define ACTHD          0x020c8
 #define FW_BLC         0x020d8
 #define FW_BLC2                0x020dc
index e38b457..be79f47 100644 (file)
@@ -10042,6 +10042,8 @@ struct intel_display_error_state {
 
        u32 power_well_driver;
 
+       int num_transcoders;
+
        struct intel_cursor_error_state {
                u32 control;
                u32 position;
@@ -10050,16 +10052,7 @@ struct intel_display_error_state {
        } cursor[I915_MAX_PIPES];
 
        struct intel_pipe_error_state {
-               enum transcoder cpu_transcoder;
-               u32 conf;
                u32 source;
-
-               u32 htotal;
-               u32 hblank;
-               u32 hsync;
-               u32 vtotal;
-               u32 vblank;
-               u32 vsync;
        } pipe[I915_MAX_PIPES];
 
        struct intel_plane_error_state {
@@ -10071,6 +10064,19 @@ struct intel_display_error_state {
                u32 surface;
                u32 tile_offset;
        } plane[I915_MAX_PIPES];
+
+       struct intel_transcoder_error_state {
+               enum transcoder cpu_transcoder;
+
+               u32 conf;
+
+               u32 htotal;
+               u32 hblank;
+               u32 hsync;
+               u32 vtotal;
+               u32 vblank;
+               u32 vsync;
+       } transcoder[4];
 };
 
 struct intel_display_error_state *
@@ -10078,9 +10084,17 @@ intel_display_capture_error_state(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct intel_display_error_state *error;
-       enum transcoder cpu_transcoder;
+       int transcoders[] = {
+               TRANSCODER_A,
+               TRANSCODER_B,
+               TRANSCODER_C,
+               TRANSCODER_EDP,
+       };
        int i;
 
+       if (INTEL_INFO(dev)->num_pipes == 0)
+               return NULL;
+
        error = kmalloc(sizeof(*error), GFP_ATOMIC);
        if (error == NULL)
                return NULL;
@@ -10089,9 +10103,6 @@ intel_display_capture_error_state(struct drm_device *dev)
                error->power_well_driver = I915_READ(HSW_PWR_WELL_DRIVER);
 
        for_each_pipe(i) {
-               cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, i);
-               error->pipe[i].cpu_transcoder = cpu_transcoder;
-
                if (INTEL_INFO(dev)->gen <= 6 || IS_VALLEYVIEW(dev)) {
                        error->cursor[i].control = I915_READ(CURCNTR(i));
                        error->cursor[i].position = I915_READ(CURPOS(i));
@@ -10115,14 +10126,25 @@ intel_display_capture_error_state(struct drm_device *dev)
                        error->plane[i].tile_offset = I915_READ(DSPTILEOFF(i));
                }
 
-               error->pipe[i].conf = I915_READ(PIPECONF(cpu_transcoder));
                error->pipe[i].source = I915_READ(PIPESRC(i));
-               error->pipe[i].htotal = I915_READ(HTOTAL(cpu_transcoder));
-               error->pipe[i].hblank = I915_READ(HBLANK(cpu_transcoder));
-               error->pipe[i].hsync = I915_READ(HSYNC(cpu_transcoder));
-               error->pipe[i].vtotal = I915_READ(VTOTAL(cpu_transcoder));
-               error->pipe[i].vblank = I915_READ(VBLANK(cpu_transcoder));
-               error->pipe[i].vsync = I915_READ(VSYNC(cpu_transcoder));
+       }
+
+       error->num_transcoders = INTEL_INFO(dev)->num_pipes;
+       if (HAS_DDI(dev_priv->dev))
+               error->num_transcoders++; /* Account for eDP. */
+
+       for (i = 0; i < error->num_transcoders; i++) {
+               enum transcoder cpu_transcoder = transcoders[i];
+
+               error->transcoder[i].cpu_transcoder = cpu_transcoder;
+
+               error->transcoder[i].conf = I915_READ(PIPECONF(cpu_transcoder));
+               error->transcoder[i].htotal = I915_READ(HTOTAL(cpu_transcoder));
+               error->transcoder[i].hblank = I915_READ(HBLANK(cpu_transcoder));
+               error->transcoder[i].hsync = I915_READ(HSYNC(cpu_transcoder));
+               error->transcoder[i].vtotal = I915_READ(VTOTAL(cpu_transcoder));
+               error->transcoder[i].vblank = I915_READ(VBLANK(cpu_transcoder));
+               error->transcoder[i].vsync = I915_READ(VSYNC(cpu_transcoder));
        }
 
        /* In the code above we read the registers without checking if the power
@@ -10144,22 +10166,16 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
 {
        int i;
 
+       if (!error)
+               return;
+
        err_printf(m, "Num Pipes: %d\n", INTEL_INFO(dev)->num_pipes);
        if (HAS_POWER_WELL(dev))
                err_printf(m, "PWR_WELL_CTL2: %08x\n",
                           error->power_well_driver);
        for_each_pipe(i) {
                err_printf(m, "Pipe [%d]:\n", i);
-               err_printf(m, "  CPU transcoder: %c\n",
-                          transcoder_name(error->pipe[i].cpu_transcoder));
-               err_printf(m, "  CONF: %08x\n", error->pipe[i].conf);
                err_printf(m, "  SRC: %08x\n", error->pipe[i].source);
-               err_printf(m, "  HTOTAL: %08x\n", error->pipe[i].htotal);
-               err_printf(m, "  HBLANK: %08x\n", error->pipe[i].hblank);
-               err_printf(m, "  HSYNC: %08x\n", error->pipe[i].hsync);
-               err_printf(m, "  VTOTAL: %08x\n", error->pipe[i].vtotal);
-               err_printf(m, "  VBLANK: %08x\n", error->pipe[i].vblank);
-               err_printf(m, "  VSYNC: %08x\n", error->pipe[i].vsync);
 
                err_printf(m, "Plane [%d]:\n", i);
                err_printf(m, "  CNTR: %08x\n", error->plane[i].control);
@@ -10180,5 +10196,17 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
                err_printf(m, "  POS: %08x\n", error->cursor[i].position);
                err_printf(m, "  BASE: %08x\n", error->cursor[i].base);
        }
+
+       for (i = 0; i < error->num_transcoders; i++) {
+               err_printf(m, "  CPU transcoder: %c\n",
+                          transcoder_name(error->transcoder[i].cpu_transcoder));
+               err_printf(m, "  CONF: %08x\n", error->transcoder[i].conf);
+               err_printf(m, "  HTOTAL: %08x\n", error->transcoder[i].htotal);
+               err_printf(m, "  HBLANK: %08x\n", error->transcoder[i].hblank);
+               err_printf(m, "  HSYNC: %08x\n", error->transcoder[i].hsync);
+               err_printf(m, "  VTOTAL: %08x\n", error->transcoder[i].vtotal);
+               err_printf(m, "  VBLANK: %08x\n", error->transcoder[i].vblank);
+               err_printf(m, "  VSYNC: %08x\n", error->transcoder[i].vsync);
+       }
 }
 #endif
index 664118d..079ef01 100644 (file)
@@ -968,6 +968,18 @@ void intel_ring_setup_status_page(struct intel_ring_buffer *ring)
 
        I915_WRITE(mmio, (u32)ring->status_page.gfx_addr);
        POSTING_READ(mmio);
+
+       /* Flush the TLB for this page */
+       if (INTEL_INFO(dev)->gen >= 6) {
+               u32 reg = RING_INSTPM(ring->mmio_base);
+               I915_WRITE(reg,
+                          _MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE |
+                                             INSTPM_SYNC_FLUSH));
+               if (wait_for((I915_READ(reg) & INSTPM_SYNC_FLUSH) == 0,
+                            1000))
+                       DRM_ERROR("%s: wait for SyncFlush to complete for TLB invalidation timed out\n",
+                                 ring->name);
+       }
 }
 
 static int
index d829172..7a4e089 100644 (file)
@@ -98,6 +98,8 @@ nouveau_mm_head(struct nouveau_mm *mm, u8 type, u32 size_max, u32 size_min,
        u32 splitoff;
        u32 s, e;
 
+       BUG_ON(!type);
+
        list_for_each_entry(this, &mm->free, fl_entry) {
                e = this->offset + this->length;
                s = this->offset;
@@ -162,6 +164,8 @@ nouveau_mm_tail(struct nouveau_mm *mm, u8 type, u32 size_max, u32 size_min,
        struct nouveau_mm_node *prev, *this, *next;
        u32 mask = align - 1;
 
+       BUG_ON(!type);
+
        list_for_each_entry_reverse(this, &mm->free, fl_entry) {
                u32 e = this->offset + this->length;
                u32 s = this->offset;
index d550226..9d2cd20 100644 (file)
@@ -20,8 +20,8 @@ nouveau_mc(void *obj)
        return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_MC];
 }
 
-#define nouveau_mc_create(p,e,o,d)                                             \
-       nouveau_mc_create_((p), (e), (o), sizeof(**d), (void **)d)
+#define nouveau_mc_create(p,e,o,m,d)                                           \
+       nouveau_mc_create_((p), (e), (o), (m), sizeof(**d), (void **)d)
 #define nouveau_mc_destroy(p) ({                                               \
        struct nouveau_mc *pmc = (p); _nouveau_mc_dtor(nv_object(pmc));        \
 })
@@ -33,7 +33,8 @@ nouveau_mc(void *obj)
 })
 
 int  nouveau_mc_create_(struct nouveau_object *, struct nouveau_object *,
-                       struct nouveau_oclass *, int, void **);
+                       struct nouveau_oclass *, const struct nouveau_mc_intr *,
+                       int, void **);
 void _nouveau_mc_dtor(struct nouveau_object *);
 int  _nouveau_mc_init(struct nouveau_object *);
 int  _nouveau_mc_fini(struct nouveau_object *, bool);
index 19e3a9a..ab7ef0a 100644 (file)
@@ -40,15 +40,15 @@ nv49_ram_create(struct nouveau_object *parent, struct nouveau_object *engine,
                return ret;
 
        switch (pfb914 & 0x00000003) {
-       case 0x00000000: pfb->ram->type = NV_MEM_TYPE_DDR1; break;
-       case 0x00000001: pfb->ram->type = NV_MEM_TYPE_DDR2; break;
-       case 0x00000002: pfb->ram->type = NV_MEM_TYPE_GDDR3; break;
+       case 0x00000000: ram->type = NV_MEM_TYPE_DDR1; break;
+       case 0x00000001: ram->type = NV_MEM_TYPE_DDR2; break;
+       case 0x00000002: ram->type = NV_MEM_TYPE_GDDR3; break;
        case 0x00000003: break;
        }
 
-       pfb->ram->size  =  nv_rd32(pfb, 0x10020c) & 0xff000000;
-       pfb->ram->parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1;
-       pfb->ram->tags  =  nv_rd32(pfb, 0x100320);
+       ram->size  =  nv_rd32(pfb, 0x10020c) & 0xff000000;
+       ram->parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1;
+       ram->tags  =  nv_rd32(pfb, 0x100320);
        return 0;
 }
 
index 7192aa6..63a6aab 100644 (file)
@@ -38,8 +38,8 @@ nv4e_ram_create(struct nouveau_object *parent, struct nouveau_object *engine,
        if (ret)
                return ret;
 
-       pfb->ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000;
-       pfb->ram->type = NV_MEM_TYPE_STOLEN;
+       ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000;
+       ram->type = NV_MEM_TYPE_STOLEN;
        return 0;
 }
 
index bcca883..cce65cc 100644 (file)
@@ -30,8 +30,9 @@ struct nvc0_ltcg_priv {
        struct nouveau_ltcg base;
        u32 part_nr;
        u32 subp_nr;
-       struct nouveau_mm tags;
        u32 num_tags;
+       u32 tag_base;
+       struct nouveau_mm tags;
        struct nouveau_mm_node *tag_ram;
 };
 
@@ -117,10 +118,6 @@ nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv)
        u32 tag_size, tag_margin, tag_align;
        int ret;
 
-       nv_wr32(priv, 0x17e8d8, priv->part_nr);
-       if (nv_device(pfb)->card_type >= NV_E0)
-               nv_wr32(priv, 0x17e000, priv->part_nr);
-
        /* tags for 1/4 of VRAM should be enough (8192/4 per GiB of VRAM) */
        priv->num_tags = (pfb->ram->size >> 17) / 4;
        if (priv->num_tags > (1 << 17))
@@ -142,7 +139,7 @@ nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv)
        tag_size += tag_align;
        tag_size  = (tag_size + 0xfff) >> 12; /* round up */
 
-       ret = nouveau_mm_tail(&pfb->vram, 0, tag_size, tag_size, 1,
+       ret = nouveau_mm_tail(&pfb->vram, 1, tag_size, tag_size, 1,
                              &priv->tag_ram);
        if (ret) {
                priv->num_tags = 0;
@@ -152,7 +149,7 @@ nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv)
                tag_base += tag_align - 1;
                ret = do_div(tag_base, tag_align);
 
-               nv_wr32(priv, 0x17e8d4, tag_base);
+               priv->tag_base = tag_base;
        }
        ret = nouveau_mm_init(&priv->tags, 0, priv->num_tags, 1);
 
@@ -182,8 +179,6 @@ nvc0_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        }
        priv->subp_nr = nv_rd32(priv, 0x17e8dc) >> 28;
 
-       nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */
-
        ret = nvc0_ltcg_init_tag_ram(pfb, priv);
        if (ret)
                return ret;
@@ -209,13 +204,32 @@ nvc0_ltcg_dtor(struct nouveau_object *object)
        nouveau_ltcg_destroy(ltcg);
 }
 
+static int
+nvc0_ltcg_init(struct nouveau_object *object)
+{
+       struct nouveau_ltcg *ltcg = (struct nouveau_ltcg *)object;
+       struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg;
+       int ret;
+
+       ret = nouveau_ltcg_init(ltcg);
+       if (ret)
+               return ret;
+
+       nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */
+       nv_wr32(priv, 0x17e8d8, priv->part_nr);
+       if (nv_device(ltcg)->card_type >= NV_E0)
+               nv_wr32(priv, 0x17e000, priv->part_nr);
+       nv_wr32(priv, 0x17e8d4, priv->tag_base);
+       return 0;
+}
+
 struct nouveau_oclass
 nvc0_ltcg_oclass = {
        .handle = NV_SUBDEV(LTCG, 0xc0),
        .ofuncs = &(struct nouveau_ofuncs) {
                .ctor = nvc0_ltcg_ctor,
                .dtor = nvc0_ltcg_dtor,
-               .init = _nouveau_ltcg_init,
+               .init = nvc0_ltcg_init,
                .fini = _nouveau_ltcg_fini,
        },
 };
index 1c0330b..ec9cd6f 100644 (file)
@@ -80,7 +80,9 @@ _nouveau_mc_dtor(struct nouveau_object *object)
 
 int
 nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine,
-                  struct nouveau_oclass *oclass, int length, void **pobject)
+                  struct nouveau_oclass *oclass,
+                  const struct nouveau_mc_intr *intr_map,
+                  int length, void **pobject)
 {
        struct nouveau_device *device = nv_device(parent);
        struct nouveau_mc *pmc;
@@ -92,6 +94,8 @@ nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine,
        if (ret)
                return ret;
 
+       pmc->intr_map = intr_map;
+
        ret = request_irq(device->pdev->irq, nouveau_mc_intr,
                          IRQF_SHARED, "nouveau", pmc);
        if (ret < 0)
index 8c76971..64aa4ed 100644 (file)
@@ -50,12 +50,11 @@ nv04_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nv04_mc_priv *priv;
        int ret;
 
-       ret = nouveau_mc_create(parent, engine, oclass, &priv);
+       ret = nouveau_mc_create(parent, engine, oclass, nv04_mc_intr, &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
 
-       priv->base.intr_map = nv04_mc_intr;
        return 0;
 }
 
index 5191937..d989178 100644 (file)
@@ -36,12 +36,11 @@ nv44_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nv44_mc_priv *priv;
        int ret;
 
-       ret = nouveau_mc_create(parent, engine, oclass, &priv);
+       ret = nouveau_mc_create(parent, engine, oclass, nv04_mc_intr, &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
 
-       priv->base.intr_map = nv04_mc_intr;
        return 0;
 }
 
index f25fc5f..2b1afe2 100644 (file)
@@ -53,12 +53,11 @@ nv50_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nv50_mc_priv *priv;
        int ret;
 
-       ret = nouveau_mc_create(parent, engine, oclass, &priv);
+       ret = nouveau_mc_create(parent, engine, oclass, nv50_mc_intr, &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
 
-       priv->base.intr_map = nv50_mc_intr;
        return 0;
 }
 
index e82fd21..0d57b4d 100644 (file)
@@ -54,12 +54,11 @@ nv98_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nv98_mc_priv *priv;
        int ret;
 
-       ret = nouveau_mc_create(parent, engine, oclass, &priv);
+       ret = nouveau_mc_create(parent, engine, oclass, nv98_mc_intr, &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
 
-       priv->base.intr_map = nv98_mc_intr;
        return 0;
 }
 
index c5da3ba..104175c 100644 (file)
@@ -57,12 +57,11 @@ nvc0_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nvc0_mc_priv *priv;
        int ret;
 
-       ret = nouveau_mc_create(parent, engine, oclass, &priv);
+       ret = nouveau_mc_create(parent, engine, oclass, nvc0_mc_intr, &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
 
-       priv->base.intr_map = nvc0_mc_intr;
        return 0;
 }
 
index 0782bd2..6a13ffb 100644 (file)
@@ -606,6 +606,24 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode)
        regp->ramdac_a34 = 0x1;
 }
 
+static int
+nv_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)
+{
+       struct nv04_display *disp = nv04_display(crtc->dev);
+       struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb);
+       struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+       int ret;
+
+       ret = nouveau_bo_pin(nvfb->nvbo, TTM_PL_FLAG_VRAM);
+       if (ret == 0) {
+               if (disp->image[nv_crtc->index])
+                       nouveau_bo_unpin(disp->image[nv_crtc->index]);
+               nouveau_bo_ref(nvfb->nvbo, &disp->image[nv_crtc->index]);
+       }
+
+       return ret;
+}
+
 /**
  * Sets up registers for the given mode/adjusted_mode pair.
  *
@@ -622,10 +640,15 @@ nv_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
        struct drm_device *dev = crtc->dev;
        struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
        struct nouveau_drm *drm = nouveau_drm(dev);
+       int ret;
 
        NV_DEBUG(drm, "CTRC mode on CRTC %d:\n", nv_crtc->index);
        drm_mode_debug_printmodeline(adjusted_mode);
 
+       ret = nv_crtc_swap_fbs(crtc, old_fb);
+       if (ret)
+               return ret;
+
        /* unlock must come after turning off FP_TG_CONTROL in output_prepare */
        nv_lock_vga_crtc_shadow(dev, nv_crtc->index, -1);
 
@@ -722,6 +745,7 @@ static void nv_crtc_commit(struct drm_crtc *crtc)
 
 static void nv_crtc_destroy(struct drm_crtc *crtc)
 {
+       struct nv04_display *disp = nv04_display(crtc->dev);
        struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 
        if (!nv_crtc)
@@ -729,6 +753,10 @@ static void nv_crtc_destroy(struct drm_crtc *crtc)
 
        drm_crtc_cleanup(crtc);
 
+       if (disp->image[nv_crtc->index])
+               nouveau_bo_unpin(disp->image[nv_crtc->index]);
+       nouveau_bo_ref(NULL, &disp->image[nv_crtc->index]);
+
        nouveau_bo_unmap(nv_crtc->cursor.nvbo);
        nouveau_bo_unpin(nv_crtc->cursor.nvbo);
        nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
@@ -753,6 +781,16 @@ nv_crtc_gamma_load(struct drm_crtc *crtc)
        nouveau_hw_load_state_palette(dev, nv_crtc->index, &nv04_display(dev)->mode_reg);
 }
 
+static void
+nv_crtc_disable(struct drm_crtc *crtc)
+{
+       struct nv04_display *disp = nv04_display(crtc->dev);
+       struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+       if (disp->image[nv_crtc->index])
+               nouveau_bo_unpin(disp->image[nv_crtc->index]);
+       nouveau_bo_ref(NULL, &disp->image[nv_crtc->index]);
+}
+
 static void
 nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t start,
                  uint32_t size)
@@ -791,7 +829,6 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
        struct drm_framebuffer *drm_fb;
        struct nouveau_framebuffer *fb;
        int arb_burst, arb_lwm;
-       int ret;
 
        NV_DEBUG(drm, "index %d\n", nv_crtc->index);
 
@@ -801,10 +838,8 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
                return 0;
        }
 
-
        /* If atomic, we want to switch to the fb we were passed, so
-        * now we update pointers to do that.  (We don't pin; just
-        * assume we're already pinned and update the base address.)
+        * now we update pointers to do that.
         */
        if (atomic) {
                drm_fb = passed_fb;
@@ -812,17 +847,6 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
        } else {
                drm_fb = crtc->fb;
                fb = nouveau_framebuffer(crtc->fb);
-               /* If not atomic, we can go ahead and pin, and unpin the
-                * old fb we were passed.
-                */
-               ret = nouveau_bo_pin(fb->nvbo, TTM_PL_FLAG_VRAM);
-               if (ret)
-                       return ret;
-
-               if (passed_fb) {
-                       struct nouveau_framebuffer *ofb = nouveau_framebuffer(passed_fb);
-                       nouveau_bo_unpin(ofb->nvbo);
-               }
        }
 
        nv_crtc->fb.offset = fb->nvbo->bo.offset;
@@ -877,6 +901,9 @@ static int
 nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
                        struct drm_framebuffer *old_fb)
 {
+       int ret = nv_crtc_swap_fbs(crtc, old_fb);
+       if (ret)
+               return ret;
        return nv04_crtc_do_mode_set_base(crtc, old_fb, x, y, false);
 }
 
@@ -1027,6 +1054,7 @@ static const struct drm_crtc_helper_funcs nv04_crtc_helper_funcs = {
        .mode_set_base = nv04_crtc_mode_set_base,
        .mode_set_base_atomic = nv04_crtc_mode_set_base_atomic,
        .load_lut = nv_crtc_gamma_load,
+       .disable = nv_crtc_disable,
 };
 
 int
index a0a031d..9928187 100644 (file)
@@ -81,6 +81,7 @@ struct nv04_display {
        uint32_t saved_vga_font[4][16384];
        uint32_t dac_users[4];
        struct nouveau_object *core;
+       struct nouveau_bo *image[2];
 };
 
 static inline struct nv04_display *
index 907d20e..a03e75d 100644 (file)
@@ -577,6 +577,9 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
                ret = nv50_display_flip_next(crtc, fb, chan, 0);
                if (ret)
                        goto fail_unreserve;
+       } else {
+               struct nv04_display *dispnv04 = nv04_display(dev);
+               nouveau_bo_ref(new_bo, &dispnv04->image[nouveau_crtc(crtc)->index]);
        }
 
        ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence);
index 3af5bcd..625f80d 100644 (file)
@@ -131,7 +131,7 @@ nv40_calc_pll(struct drm_device *dev, u32 reg, struct nvbios_pll *pll,
        if (clk < pll->vco1.max_freq)
                pll->vco2.max_freq = 0;
 
-       pclk->pll_calc(pclk, pll, clk, &coef);
+       ret = pclk->pll_calc(pclk, pll, clk, &coef);
        if (ret == 0)
                return -ERANGE;
 
index 274b8e1..9f19259 100644 (file)
@@ -2163,7 +2163,7 @@ void cik_mm_wdoorbell(struct radeon_device *rdev, u32 offset, u32 v);
                WREG32(reg, tmp_);                              \
        } while (0)
 #define WREG32_AND(reg, and) WREG32_P(reg, 0, and)
-#define WREG32_OR(reg, or) WREG32_P(reg, or, ~or)
+#define WREG32_OR(reg, or) WREG32_P(reg, or, ~(or))
 #define WREG32_PLL_P(reg, val, mask)                           \
        do {                                                    \
                uint32_t tmp_ = RREG32_PLL(reg);                \
index f1c1575..b79f4f5 100644 (file)
@@ -356,6 +356,14 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
                return -EINVAL;
        }
 
+       if (bo->tbo.sync_obj) {
+               r = radeon_fence_wait(bo->tbo.sync_obj, false);
+               if (r) {
+                       DRM_ERROR("Failed waiting for UVD message (%d)!\n", r);
+                       return r;
+               }
+       }
+
        r = radeon_bo_kmap(bo, &ptr);
        if (r) {
                DRM_ERROR("Failed mapping the UVD message (%d)!\n", r);
index bcc68ec..f5e92cf 100644 (file)
@@ -744,10 +744,10 @@ static void rv770_init_golden_registers(struct radeon_device *rdev)
                                                 (const u32)ARRAY_SIZE(r7xx_golden_dyn_gpr_registers));
                radeon_program_register_sequence(rdev,
                                                 rv730_golden_registers,
-                                                (const u32)ARRAY_SIZE(rv770_golden_registers));
+                                                (const u32)ARRAY_SIZE(rv730_golden_registers));
                radeon_program_register_sequence(rdev,
                                                 rv730_mgcg_init,
-                                                (const u32)ARRAY_SIZE(rv770_mgcg_init));
+                                                (const u32)ARRAY_SIZE(rv730_mgcg_init));
                break;
        case CHIP_RV710:
                radeon_program_register_sequence(rdev,
@@ -758,18 +758,18 @@ static void rv770_init_golden_registers(struct radeon_device *rdev)
                                                 (const u32)ARRAY_SIZE(r7xx_golden_dyn_gpr_registers));
                radeon_program_register_sequence(rdev,
                                                 rv710_golden_registers,
-                                                (const u32)ARRAY_SIZE(rv770_golden_registers));
+                                                (const u32)ARRAY_SIZE(rv710_golden_registers));
                radeon_program_register_sequence(rdev,
                                                 rv710_mgcg_init,
-                                                (const u32)ARRAY_SIZE(rv770_mgcg_init));
+                                                (const u32)ARRAY_SIZE(rv710_mgcg_init));
                break;
        case CHIP_RV740:
                radeon_program_register_sequence(rdev,
                                                 rv740_golden_registers,
-                                                (const u32)ARRAY_SIZE(rv770_golden_registers));
+                                                (const u32)ARRAY_SIZE(rv740_golden_registers));
                radeon_program_register_sequence(rdev,
                                                 rv740_mgcg_init,
-                                                (const u32)ARRAY_SIZE(rv770_mgcg_init));
+                                                (const u32)ARRAY_SIZE(rv740_mgcg_init));
                break;
        default:
                break;
index f1a6796..140c8ef 100644 (file)
@@ -520,11 +520,12 @@ void ide_acpi_set_state(ide_hwif_t *hwif, int on)
        ide_port_for_each_present_dev(i, drive, hwif) {
                if (drive->acpidata->obj_handle)
                        acpi_bus_set_power(drive->acpidata->obj_handle,
-                                          on ? ACPI_STATE_D0 : ACPI_STATE_D3);
+                               on ? ACPI_STATE_D0 : ACPI_STATE_D3_COLD);
        }
 
        if (!on)
-               acpi_bus_set_power(hwif->acpidata->obj_handle, ACPI_STATE_D3);
+               acpi_bus_set_power(hwif->acpidata->obj_handle,
+                                  ACPI_STATE_D3_COLD);
 }
 
 /**
index 5f4749e..c1cd569 100644 (file)
@@ -232,7 +232,8 @@ static int adjd_s311_read_raw(struct iio_dev *indio_dev,
 
        switch (mask) {
        case IIO_CHAN_INFO_RAW:
-               ret = adjd_s311_read_data(indio_dev, chan->address, val);
+               ret = adjd_s311_read_data(indio_dev,
+                       ADJD_S311_DATA_REG(chan->address), val);
                if (ret < 0)
                        return ret;
                return IIO_VAL_INT;
index dc112a7..4296155 100644 (file)
@@ -959,23 +959,21 @@ out:
        return r;
 }
 
-static void remove_mapping(struct mq_policy *mq, dm_oblock_t oblock)
+static void mq_remove_mapping(struct dm_cache_policy *p, dm_oblock_t oblock)
 {
-       struct entry *e = hash_lookup(mq, oblock);
+       struct mq_policy *mq = to_mq_policy(p);
+       struct entry *e;
+
+       mutex_lock(&mq->lock);
+
+       e = hash_lookup(mq, oblock);
 
        BUG_ON(!e || !e->in_cache);
 
        del(mq, e);
        e->in_cache = false;
        push(mq, e);
-}
 
-static void mq_remove_mapping(struct dm_cache_policy *p, dm_oblock_t oblock)
-{
-       struct mq_policy *mq = to_mq_policy(p);
-
-       mutex_lock(&mq->lock);
-       remove_mapping(mq, oblock);
        mutex_unlock(&mq->lock);
 }
 
index 3c157fa..0d68eb1 100644 (file)
@@ -3093,6 +3093,10 @@ static struct mfd_cell db8500_prcmu_devs[] = {
                .platform_data = &db8500_cpufreq_table,
                .pdata_size = sizeof(db8500_cpufreq_table),
        },
+       {
+               .name = "cpuidle-dbx500",
+               .of_compatible = "stericsson,cpuidle-dbx500",
+       },
        {
                .name = "db8500-thermal",
                .num_resources = ARRAY_SIZE(db8500_thsens_resources),
index ce9b387..00b88cb 100644 (file)
@@ -1333,6 +1333,8 @@ enum {
        BNX2X_SP_RTNL_VFPF_CHANNEL_DOWN,
        BNX2X_SP_RTNL_VFPF_STORM_RX_MODE,
        BNX2X_SP_RTNL_HYPERVISOR_VLAN,
+       BNX2X_SP_RTNL_TX_STOP,
+       BNX2X_SP_RTNL_TX_RESUME,
 };
 
 struct bnx2x_prev_path_list {
index f9122f2..fcf2761 100644 (file)
 #include "bnx2x_dcb.h"
 
 /* forward declarations of dcbx related functions */
-static int bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp);
 static void bnx2x_pfc_set_pfc(struct bnx2x *bp);
 static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp);
-static int bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp);
 static void bnx2x_dcbx_get_ets_pri_pg_tbl(struct bnx2x *bp,
                                          u32 *set_configuration_ets_pg,
                                          u32 *pri_pg_tbl);
@@ -425,30 +423,52 @@ static void bnx2x_pfc_set_pfc(struct bnx2x *bp)
                bnx2x_pfc_clear(bp);
 }
 
-static int bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp)
+int bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp)
 {
        struct bnx2x_func_state_params func_params = {NULL};
+       int rc;
 
        func_params.f_obj = &bp->func_obj;
        func_params.cmd = BNX2X_F_CMD_TX_STOP;
 
+       __set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags);
+       __set_bit(RAMROD_RETRY, &func_params.ramrod_flags);
+
        DP(BNX2X_MSG_DCB, "STOP TRAFFIC\n");
-       return bnx2x_func_state_change(bp, &func_params);
+
+       rc = bnx2x_func_state_change(bp, &func_params);
+       if (rc) {
+               BNX2X_ERR("Unable to hold traffic for HW configuration\n");
+               bnx2x_panic();
+       }
+
+       return rc;
 }
 
-static int bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp)
+int bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp)
 {
        struct bnx2x_func_state_params func_params = {NULL};
        struct bnx2x_func_tx_start_params *tx_params =
                &func_params.params.tx_start;
+       int rc;
 
        func_params.f_obj = &bp->func_obj;
        func_params.cmd = BNX2X_F_CMD_TX_START;
 
+       __set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags);
+       __set_bit(RAMROD_RETRY, &func_params.ramrod_flags);
+
        bnx2x_dcbx_fw_struct(bp, tx_params);
 
        DP(BNX2X_MSG_DCB, "START TRAFFIC\n");
-       return bnx2x_func_state_change(bp, &func_params);
+
+       rc = bnx2x_func_state_change(bp, &func_params);
+       if (rc) {
+               BNX2X_ERR("Unable to resume traffic after HW configuration\n");
+               bnx2x_panic();
+       }
+
+       return rc;
 }
 
 static void bnx2x_dcbx_2cos_limit_update_ets_config(struct bnx2x *bp)
@@ -744,7 +764,9 @@ void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state)
                        if (IS_MF(bp))
                                bnx2x_link_sync_notify(bp);
 
-                       bnx2x_dcbx_stop_hw_tx(bp);
+                       set_bit(BNX2X_SP_RTNL_TX_STOP, &bp->sp_rtnl_state);
+
+                       schedule_delayed_work(&bp->sp_rtnl_task, 0);
 
                        return;
                }
@@ -757,7 +779,9 @@ void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state)
                /* ets may affect cmng configuration: reinit it in hw */
                bnx2x_set_local_cmng(bp);
 
-               bnx2x_dcbx_resume_hw_tx(bp);
+               set_bit(BNX2X_SP_RTNL_TX_RESUME, &bp->sp_rtnl_state);
+
+               schedule_delayed_work(&bp->sp_rtnl_task, 0);
 
                return;
        case BNX2X_DCBX_STATE_TX_RELEASED:
@@ -2367,21 +2391,24 @@ static u8 bnx2x_dcbnl_get_featcfg(struct net_device *netdev, int featid,
                case DCB_FEATCFG_ATTR_PG:
                        if (bp->dcbx_local_feat.ets.enabled)
                                *flags |= DCB_FEATCFG_ENABLE;
-                       if (bp->dcbx_error & DCBX_LOCAL_ETS_ERROR)
+                       if (bp->dcbx_error & (DCBX_LOCAL_ETS_ERROR |
+                                             DCBX_REMOTE_MIB_ERROR))
                                *flags |= DCB_FEATCFG_ERROR;
                        break;
                case DCB_FEATCFG_ATTR_PFC:
                        if (bp->dcbx_local_feat.pfc.enabled)
                                *flags |= DCB_FEATCFG_ENABLE;
                        if (bp->dcbx_error & (DCBX_LOCAL_PFC_ERROR |
-                           DCBX_LOCAL_PFC_MISMATCH))
+                                             DCBX_LOCAL_PFC_MISMATCH |
+                                             DCBX_REMOTE_MIB_ERROR))
                                *flags |= DCB_FEATCFG_ERROR;
                        break;
                case DCB_FEATCFG_ATTR_APP:
                        if (bp->dcbx_local_feat.app.enabled)
                                *flags |= DCB_FEATCFG_ENABLE;
                        if (bp->dcbx_error & (DCBX_LOCAL_APP_ERROR |
-                           DCBX_LOCAL_APP_MISMATCH))
+                                             DCBX_LOCAL_APP_MISMATCH |
+                                             DCBX_REMOTE_MIB_ERROR))
                                *flags |= DCB_FEATCFG_ERROR;
                        break;
                default:
index 125bd1b..804b8f6 100644 (file)
@@ -199,4 +199,7 @@ extern const struct dcbnl_rtnl_ops bnx2x_dcbnl_ops;
 int bnx2x_dcbnl_update_applist(struct bnx2x *bp, bool delall);
 #endif /* BCM_DCBNL */
 
+int bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp);
+int bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp);
+
 #endif /* BNX2X_DCB_H */
index 955d6cf..8bdc8b9 100644 (file)
@@ -2261,6 +2261,23 @@ static void bnx2x_set_requested_fc(struct bnx2x *bp)
                bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_BOTH;
 }
 
+static void bnx2x_init_dropless_fc(struct bnx2x *bp)
+{
+       u32 pause_enabled = 0;
+
+       if (!CHIP_IS_E1(bp) && bp->dropless_fc && bp->link_vars.link_up) {
+               if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_TX)
+                       pause_enabled = 1;
+
+               REG_WR(bp, BAR_USTRORM_INTMEM +
+                          USTORM_ETH_PAUSE_ENABLED_OFFSET(BP_PORT(bp)),
+                      pause_enabled);
+       }
+
+       DP(NETIF_MSG_IFUP | NETIF_MSG_LINK, "dropless_fc is %s\n",
+          pause_enabled ? "enabled" : "disabled");
+}
+
 int bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode)
 {
        int rc, cfx_idx = bnx2x_get_link_cfg_idx(bp);
@@ -2294,6 +2311,8 @@ int bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode)
 
                bnx2x_release_phy_lock(bp);
 
+               bnx2x_init_dropless_fc(bp);
+
                bnx2x_calc_fc_adv(bp);
 
                if (bp->link_vars.link_up) {
@@ -2315,6 +2334,8 @@ void bnx2x_link_set(struct bnx2x *bp)
                bnx2x_phy_init(&bp->link_params, &bp->link_vars);
                bnx2x_release_phy_lock(bp);
 
+               bnx2x_init_dropless_fc(bp);
+
                bnx2x_calc_fc_adv(bp);
        } else
                BNX2X_ERR("Bootcode is missing - can not set link\n");
@@ -2556,20 +2577,9 @@ static void bnx2x_link_attn(struct bnx2x *bp)
 
        bnx2x_link_update(&bp->link_params, &bp->link_vars);
 
-       if (bp->link_vars.link_up) {
+       bnx2x_init_dropless_fc(bp);
 
-               /* dropless flow control */
-               if (!CHIP_IS_E1(bp) && bp->dropless_fc) {
-                       int port = BP_PORT(bp);
-                       u32 pause_enabled = 0;
-
-                       if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_TX)
-                               pause_enabled = 1;
-
-                       REG_WR(bp, BAR_USTRORM_INTMEM +
-                              USTORM_ETH_PAUSE_ENABLED_OFFSET(port),
-                              pause_enabled);
-               }
+       if (bp->link_vars.link_up) {
 
                if (bp->link_vars.mac_type != MAC_TYPE_EMAC) {
                        struct host_port_stats *pstats;
@@ -9645,6 +9655,12 @@ sp_rtnl_not_reset:
                               &bp->sp_rtnl_state))
                bnx2x_pf_set_vfs_vlan(bp);
 
+       if (test_and_clear_bit(BNX2X_SP_RTNL_TX_STOP, &bp->sp_rtnl_state))
+               bnx2x_dcbx_stop_hw_tx(bp);
+
+       if (test_and_clear_bit(BNX2X_SP_RTNL_TX_RESUME, &bp->sp_rtnl_state))
+               bnx2x_dcbx_resume_hw_tx(bp);
+
        /* work which needs rtnl lock not-taken (as it takes the lock itself and
         * can be called from other contexts as well)
         */
@@ -11147,6 +11163,9 @@ static bool bnx2x_get_dropless_info(struct bnx2x *bp)
        int tmp;
        u32 cfg;
 
+       if (IS_VF(bp))
+               return 0;
+
        if (IS_MF(bp) && !CHIP_IS_E1x(bp)) {
                /* Take function: tmp = func */
                tmp = BP_ABS_FUNC(bp);
index 44104fb..ad83f4b 100644 (file)
@@ -1747,11 +1747,8 @@ void bnx2x_iov_init_dq(struct bnx2x *bp)
 
 void bnx2x_iov_init_dmae(struct bnx2x *bp)
 {
-       DP(BNX2X_MSG_IOV, "SRIOV is %s\n", IS_SRIOV(bp) ? "ON" : "OFF");
-       if (!IS_SRIOV(bp))
-               return;
-
-       REG_WR(bp, DMAE_REG_BACKWARD_COMP_EN, 0);
+       if (pci_find_ext_capability(bp->pdev, PCI_EXT_CAP_ID_SRIOV))
+               REG_WR(bp, DMAE_REG_BACKWARD_COMP_EN, 0);
 }
 
 static int bnx2x_vf_bus(struct bnx2x *bp, int vfid)
@@ -3084,8 +3081,9 @@ void bnx2x_disable_sriov(struct bnx2x *bp)
        pci_disable_sriov(bp->pdev);
 }
 
-static int bnx2x_vf_ndo_sanity(struct bnx2x *bp, int vfidx,
-                              struct bnx2x_virtf *vf)
+static int bnx2x_vf_ndo_prep(struct bnx2x *bp, int vfidx,
+                            struct bnx2x_virtf **vf,
+                            struct pf_vf_bulletin_content **bulletin)
 {
        if (bp->state != BNX2X_STATE_OPEN) {
                BNX2X_ERR("vf ndo called though PF is down\n");
@@ -3103,12 +3101,22 @@ static int bnx2x_vf_ndo_sanity(struct bnx2x *bp, int vfidx,
                return -EINVAL;
        }
 
-       if (!vf) {
+       /* init members */
+       *vf = BP_VF(bp, vfidx);
+       *bulletin = BP_VF_BULLETIN(bp, vfidx);
+
+       if (!*vf) {
                BNX2X_ERR("vf ndo called but vf was null. vfidx was %d\n",
                          vfidx);
                return -EINVAL;
        }
 
+       if (!*bulletin) {
+               BNX2X_ERR("vf ndo called but Bulletin Board struct is null. vfidx was %d\n",
+                         vfidx);
+               return -EINVAL;
+       }
+
        return 0;
 }
 
@@ -3116,17 +3124,19 @@ int bnx2x_get_vf_config(struct net_device *dev, int vfidx,
                        struct ifla_vf_info *ivi)
 {
        struct bnx2x *bp = netdev_priv(dev);
-       struct bnx2x_virtf *vf = BP_VF(bp, vfidx);
-       struct bnx2x_vlan_mac_obj *mac_obj = &bnx2x_vfq(vf, 0, mac_obj);
-       struct bnx2x_vlan_mac_obj *vlan_obj = &bnx2x_vfq(vf, 0, vlan_obj);
-       struct pf_vf_bulletin_content *bulletin = BP_VF_BULLETIN(bp, vfidx);
+       struct bnx2x_virtf *vf = NULL;
+       struct pf_vf_bulletin_content *bulletin = NULL;
+       struct bnx2x_vlan_mac_obj *mac_obj;
+       struct bnx2x_vlan_mac_obj *vlan_obj;
        int rc;
 
-       /* sanity */
-       rc = bnx2x_vf_ndo_sanity(bp, vfidx, vf);
+       /* sanity and init */
+       rc = bnx2x_vf_ndo_prep(bp, vfidx, &vf, &bulletin);
        if (rc)
                return rc;
-       if (!mac_obj || !vlan_obj || !bulletin) {
+       mac_obj = &bnx2x_vfq(vf, 0, mac_obj);
+       vlan_obj = &bnx2x_vfq(vf, 0, vlan_obj);
+       if (!mac_obj || !vlan_obj) {
                BNX2X_ERR("VF partially initialized\n");
                return -EINVAL;
        }
@@ -3183,11 +3193,11 @@ int bnx2x_set_vf_mac(struct net_device *dev, int vfidx, u8 *mac)
 {
        struct bnx2x *bp = netdev_priv(dev);
        int rc, q_logical_state;
-       struct bnx2x_virtf *vf = BP_VF(bp, vfidx);
-       struct pf_vf_bulletin_content *bulletin = BP_VF_BULLETIN(bp, vfidx);
+       struct bnx2x_virtf *vf = NULL;
+       struct pf_vf_bulletin_content *bulletin = NULL;
 
-       /* sanity */
-       rc = bnx2x_vf_ndo_sanity(bp, vfidx, vf);
+       /* sanity and init */
+       rc = bnx2x_vf_ndo_prep(bp, vfidx, &vf, &bulletin);
        if (rc)
                return rc;
        if (!is_valid_ether_addr(mac)) {
@@ -3249,11 +3259,11 @@ int bnx2x_set_vf_vlan(struct net_device *dev, int vfidx, u16 vlan, u8 qos)
 {
        struct bnx2x *bp = netdev_priv(dev);
        int rc, q_logical_state;
-       struct bnx2x_virtf *vf = BP_VF(bp, vfidx);
-       struct pf_vf_bulletin_content *bulletin = BP_VF_BULLETIN(bp, vfidx);
+       struct bnx2x_virtf *vf = NULL;
+       struct pf_vf_bulletin_content *bulletin = NULL;
 
-       /* sanity */
-       rc = bnx2x_vf_ndo_sanity(bp, vfidx, vf);
+       /* sanity and init */
+       rc = bnx2x_vf_ndo_prep(bp, vfidx, &vf, &bulletin);
        if (rc)
                return rc;
 
index 181edb5..4559c35 100644 (file)
@@ -2563,8 +2563,8 @@ static int be_close(struct net_device *netdev)
        /* Wait for all pending tx completions to arrive so that
         * all tx skbs are freed.
         */
-       be_tx_compl_clean(adapter);
        netif_tx_disable(netdev);
+       be_tx_compl_clean(adapter);
 
        be_rx_qs_destroy(adapter);
 
index b5eb419..85e5c97 100644 (file)
@@ -7088,7 +7088,7 @@ rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        RTL_W8(Cfg9346, Cfg9346_Unlock);
        RTL_W8(Config1, RTL_R8(Config1) | PMEnable);
-       RTL_W8(Config5, RTL_R8(Config5) & PMEStatus);
+       RTL_W8(Config5, RTL_R8(Config5) & (BWF | MWF | UWF | LanWake | PMEStatus));
        if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0)
                tp->features |= RTL_FEATURE_WOL;
        if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0)
index 2a469b2..30d7442 100644 (file)
@@ -675,7 +675,7 @@ s32 efx_filter_insert_filter(struct efx_nic *efx, struct efx_filter_spec *spec,
                BUILD_BUG_ON(EFX_FILTER_INDEX_UC_DEF != 0);
                BUILD_BUG_ON(EFX_FILTER_INDEX_MC_DEF !=
                             EFX_FILTER_MC_DEF - EFX_FILTER_UC_DEF);
-               rep_index = spec->type - EFX_FILTER_INDEX_UC_DEF;
+               rep_index = spec->type - EFX_FILTER_UC_DEF;
                ins_index = rep_index;
 
                spin_lock_bh(&state->lock);
index 51f2bc3..2dcc60f 100644 (file)
@@ -210,8 +210,7 @@ static int via_init_one(struct pci_dev *pcidev, const struct pci_device_id *id)
                        pci_write_config_byte(pcidev,0x42,(bTmp | 0xf0));
                        pci_write_config_byte(pcidev,0x5a,0xc0);
                        WriteLPCReg(0x28, 0x70 );
-                       if (via_ircc_open(pcidev, &info, 0x3076) == 0)
-                               rc=0;
+                       rc = via_ircc_open(pcidev, &info, 0x3076);
                } else
                        rc = -ENODEV; //IR not turn on   
        } else { //Not VT1211
@@ -249,8 +248,7 @@ static int via_init_one(struct pci_dev *pcidev, const struct pci_device_id *id)
                        info.irq=FirIRQ;
                        info.dma=FirDRQ1;
                        info.dma2=FirDRQ0;
-                       if (via_ircc_open(pcidev, &info, 0x3096) == 0)
-                               rc=0;
+                       rc = via_ircc_open(pcidev, &info, 0x3096);
                } else
                        rc = -ENODEV; //IR not turn on !!!!!
        }//Not VT1211
index b51db2a..ea53abb 100644 (file)
@@ -68,6 +68,8 @@ static const struct proto_ops macvtap_socket_ops;
 #define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \
                      NETIF_F_TSO6 | NETIF_F_UFO)
 #define RX_OFFLOADS (NETIF_F_GRO | NETIF_F_LRO)
+#define TAP_FEATURES (NETIF_F_GSO | NETIF_F_SG)
+
 /*
  * RCU usage:
  * The macvtap_queue and the macvlan_dev are loosely coupled, the
@@ -278,7 +280,8 @@ static int macvtap_forward(struct net_device *dev, struct sk_buff *skb)
 {
        struct macvlan_dev *vlan = netdev_priv(dev);
        struct macvtap_queue *q = macvtap_get_queue(dev, skb);
-       netdev_features_t features;
+       netdev_features_t features = TAP_FEATURES;
+
        if (!q)
                goto drop;
 
@@ -287,9 +290,11 @@ static int macvtap_forward(struct net_device *dev, struct sk_buff *skb)
 
        skb->dev = dev;
        /* Apply the forward feature mask so that we perform segmentation
-        * according to users wishes.
+        * according to users wishes.  This only works if VNET_HDR is
+        * enabled.
         */
-       features = netif_skb_features(skb) & vlan->tap_features;
+       if (q->flags & IFF_VNET_HDR)
+               features |= vlan->tap_features;
        if (netif_needs_gso(skb, features)) {
                struct sk_buff *segs = __skb_gso_segment(skb, features, false);
 
@@ -1064,8 +1069,7 @@ static int set_offload(struct macvtap_queue *q, unsigned long arg)
        /* tap_features are the same as features on tun/tap and
         * reflect user expectations.
         */
-       vlan->tap_features = vlan->dev->features &
-                           (feature_mask | ~TUN_OFFLOADS);
+       vlan->tap_features = feature_mask;
        vlan->set_features = features;
        netdev_update_features(vlan->dev);
 
@@ -1161,10 +1165,6 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd,
                            TUN_F_TSO_ECN | TUN_F_UFO))
                        return -EINVAL;
 
-               /* TODO: only accept frames with the features that
-                        got enabled for forwarded frames */
-               if (!(q->flags & IFF_VNET_HDR))
-                       return  -EINVAL;
                rtnl_lock();
                ret = set_offload(q, arg);
                rtnl_unlock();
index 8e7af83..138de83 100644 (file)
@@ -23,7 +23,7 @@
 #define RTL821x_INER_INIT      0x6400
 #define RTL821x_INSR           0x13
 
-#define        RTL8211E_INER_LINK_STAT 0x10
+#define        RTL8211E_INER_LINK_STATUS       0x400
 
 MODULE_DESCRIPTION("Realtek PHY driver");
 MODULE_AUTHOR("Johnson Leung");
@@ -57,7 +57,7 @@ static int rtl8211e_config_intr(struct phy_device *phydev)
 
        if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
                err = phy_write(phydev, RTL821x_INER,
-                               RTL8211E_INER_LINK_STAT);
+                               RTL8211E_INER_LINK_STATUS);
        else
                err = phy_write(phydev, RTL821x_INER, 0);
 
index cba1d46..86292e6 100644 (file)
@@ -2816,13 +2816,16 @@ exit:
 static int hso_get_config_data(struct usb_interface *interface)
 {
        struct usb_device *usbdev = interface_to_usbdev(interface);
-       u8 config_data[17];
+       u8 *config_data = kmalloc(17, GFP_KERNEL);
        u32 if_num = interface->altsetting->desc.bInterfaceNumber;
        s32 result;
 
+       if (!config_data)
+               return -ENOMEM;
        if (usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0),
                            0x86, 0xC0, 0, 0, config_data, 17,
                            USB_CTRL_SET_TIMEOUT) != 0x11) {
+               kfree(config_data);
                return -EIO;
        }
 
@@ -2873,6 +2876,7 @@ static int hso_get_config_data(struct usb_interface *interface)
        if (config_data[16] & 0x1)
                result |= HSO_INFO_CRC_BUG;
 
+       kfree(config_data);
        return result;
 }
 
@@ -2886,6 +2890,11 @@ static int hso_probe(struct usb_interface *interface,
        struct hso_shared_int *shared_int;
        struct hso_device *tmp_dev = NULL;
 
+       if (interface->cur_altsetting->desc.bInterfaceClass != 0xFF) {
+               dev_err(&interface->dev, "Not our interface\n");
+               return -ENODEV;
+       }
+
        if_num = interface->altsetting->desc.bInterfaceNumber;
 
        /* Get the interface/port specification from either driver_info or from
@@ -2895,10 +2904,6 @@ static int hso_probe(struct usb_interface *interface,
        else
                port_spec = hso_get_config_data(interface);
 
-       if (interface->cur_altsetting->desc.bInterfaceClass != 0xFF) {
-               dev_err(&interface->dev, "Not our interface\n");
-               return -ENODEV;
-       }
        /* Check if we need to switch to alt interfaces prior to port
         * configuration */
        if (interface->num_altsetting > 1)
index ac07473..e509030 100644 (file)
@@ -523,9 +523,9 @@ static int prism2_ioctl_giwaplist(struct net_device *dev,
 
        data->length = prism2_ap_get_sta_qual(local, addr, qual, IW_MAX_AP, 1);
 
-       memcpy(extra, &addr, sizeof(struct sockaddr) * data->length);
+       memcpy(extra, addr, sizeof(struct sockaddr) * data->length);
        data->flags = 1; /* has quality information */
-       memcpy(extra + sizeof(struct sockaddr) * data->length, &qual,
+       memcpy(extra + sizeof(struct sockaddr) * data->length, qual,
               sizeof(struct iw_quality) * data->length);
 
        kfree(addr);
index 822f1a0..3193872 100644 (file)
@@ -1068,7 +1068,10 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success)
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
 
-       if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
+       if (!test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
+               return;
+
+       if (ctx->vif)
                ieee80211_chswitch_done(ctx->vif, is_success);
 }
 
index a70c7b9..ff8cc75 100644 (file)
@@ -97,8 +97,6 @@
 
 #define APMG_PCIDEV_STT_VAL_L1_ACT_DIS         (0x00000800)
 
-#define APMG_RTC_INT_STT_RFKILL                (0x10000000)
-
 /* Device system time */
 #define DEVICE_SYSTEM_TIME_REG 0xA0206C
 
index ad9bbca..7fd6fbf 100644 (file)
@@ -138,6 +138,20 @@ static void iwl_mvm_roc_finished(struct iwl_mvm *mvm)
        schedule_work(&mvm->roc_done_wk);
 }
 
+static bool iwl_mvm_te_check_disconnect(struct iwl_mvm *mvm,
+                                       struct ieee80211_vif *vif,
+                                       const char *errmsg)
+{
+       if (vif->type != NL80211_IFTYPE_STATION)
+               return false;
+       if (vif->bss_conf.assoc && vif->bss_conf.dtim_period)
+               return false;
+       if (errmsg)
+               IWL_ERR(mvm, "%s\n", errmsg);
+       ieee80211_connection_loss(vif);
+       return true;
+}
+
 /*
  * Handles a FW notification for an event that is known to the driver.
  *
@@ -163,8 +177,13 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
         * P2P Device discoveribility, while there are other higher priority
         * events in the system).
         */
-       WARN_ONCE(!le32_to_cpu(notif->status),
-                 "Failed to schedule time event\n");
+       if (WARN_ONCE(!le32_to_cpu(notif->status),
+                     "Failed to schedule time event\n")) {
+               if (iwl_mvm_te_check_disconnect(mvm, te_data->vif, NULL)) {
+                       iwl_mvm_te_clear_data(mvm, te_data);
+                       return;
+               }
+       }
 
        if (le32_to_cpu(notif->action) & TE_NOTIF_HOST_EVENT_END) {
                IWL_DEBUG_TE(mvm,
@@ -180,14 +199,8 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
                 * By now, we should have finished association
                 * and know the dtim period.
                 */
-               if (te_data->vif->type == NL80211_IFTYPE_STATION &&
-                   (!te_data->vif->bss_conf.assoc ||
-                    !te_data->vif->bss_conf.dtim_period)) {
-                       IWL_ERR(mvm,
-                               "No assocation and the time event is over already...\n");
-                       ieee80211_connection_loss(te_data->vif);
-               }
-
+               iwl_mvm_te_check_disconnect(mvm, te_data->vif,
+                       "No assocation and the time event is over already...");
                iwl_mvm_te_clear_data(mvm, te_data);
        } else if (le32_to_cpu(notif->action) & TE_NOTIF_HOST_EVENT_START) {
                te_data->running = true;
index f600e68..fd848cd 100644 (file)
@@ -888,14 +888,6 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
 
                iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
                if (hw_rfkill) {
-                       /*
-                        * Clear the interrupt in APMG if the NIC is going down.
-                        * Note that when the NIC exits RFkill (else branch), we
-                        * can't access prph and the NIC will be reset in
-                        * start_hw anyway.
-                        */
-                       iwl_write_prph(trans, APMG_RTC_INT_STT_REG,
-                                      APMG_RTC_INT_STT_RFKILL);
                        set_bit(STATUS_RFKILL, &trans_pcie->status);
                        if (test_and_clear_bit(STATUS_HCMD_ACTIVE,
                                               &trans_pcie->status))
index 96cfcdd..390e2f0 100644 (file)
@@ -1502,16 +1502,16 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
        spin_lock_init(&trans_pcie->reg_lock);
        init_waitqueue_head(&trans_pcie->ucode_write_waitq);
 
-       /* W/A - seems to solve weird behavior. We need to remove this if we
-        * don't want to stay in L1 all the time. This wastes a lot of power */
-       pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
-                              PCIE_LINK_STATE_CLKPM);
-
        if (pci_enable_device(pdev)) {
                err = -ENODEV;
                goto out_no_pci;
        }
 
+       /* W/A - seems to solve weird behavior. We need to remove this if we
+        * don't want to stay in L1 all the time. This wastes a lot of power */
+       pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
+                              PCIE_LINK_STATE_CLKPM);
+
        pci_set_master(pdev);
 
        err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36));
index 4941f20..b8ba1f9 100644 (file)
@@ -98,10 +98,12 @@ static int zd1201_fw_upload(struct usb_device *dev, int apfw)
                goto exit;
 
        err = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 0x4,
-           USB_DIR_IN | 0x40, 0,0, &ret, sizeof(ret), ZD1201_FW_TIMEOUT);
+           USB_DIR_IN | 0x40, 0, 0, buf, sizeof(ret), ZD1201_FW_TIMEOUT);
        if (err < 0)
                goto exit;
 
+       memcpy(&ret, buf, sizeof(ret));
+
        if (ret & 0x80) {
                err = -EIO;
                goto exit;
index 6bb7cf2..b10ba00 100644 (file)
@@ -392,6 +392,8 @@ static void __unflatten_device_tree(struct boot_param_header *blob,
        mem = (unsigned long)
                dt_alloc(size + 4, __alignof__(struct device_node));
 
+       memset((void *)mem, 0, size);
+
        ((__be32 *)mem)[size / 4] = cpu_to_be32(0xdeadbeef);
 
        pr_debug("  unflattening %lx...\n", mem);
index 6fdd49c..f4e0289 100644 (file)
@@ -49,6 +49,7 @@
 #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
 #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
 
+struct acpiphp_context;
 struct acpiphp_bridge;
 struct acpiphp_slot;
 
@@ -59,6 +60,7 @@ struct slot {
        struct hotplug_slot     *hotplug_slot;
        struct acpiphp_slot     *acpi_slot;
        struct hotplug_slot_info info;
+       unsigned int sun;       /* ACPI _SUN (Slot User Number) value */
 };
 
 static inline const char *slot_name(struct slot *slot)
@@ -75,15 +77,11 @@ struct acpiphp_bridge {
        struct list_head list;
        struct list_head slots;
        struct kref ref;
-       acpi_handle handle;
 
-       /* Ejectable PCI-to-PCI bridge (PCI bridge and PCI function) */
-       struct acpiphp_func *func;
+       struct acpiphp_context *context;
 
        int nr_slots;
 
-       u32 flags;
-
        /* This bus (host bridge) or Secondary bus (PCI-to-PCI bridge) */
        struct pci_bus *pci_bus;
 
@@ -99,15 +97,13 @@ struct acpiphp_bridge {
  */
 struct acpiphp_slot {
        struct list_head node;
-       struct acpiphp_bridge *bridge;  /* parent */
+       struct pci_bus *bus;
        struct list_head funcs;         /* one slot may have different
                                           objects (i.e. for each function) */
        struct slot *slot;
        struct mutex crit_sect;
 
        u8              device;         /* pci device# */
-
-       unsigned long long sun;         /* ACPI _SUN (slot unique number) */
        u32             flags;          /* see below */
 };
 
@@ -119,16 +115,32 @@ struct acpiphp_slot {
  * typically 8 objects per slot (i.e. for each PCI function)
  */
 struct acpiphp_func {
-       struct acpiphp_slot *slot;      /* parent */
+       struct acpiphp_bridge *parent;
+       struct acpiphp_slot *slot;
 
        struct list_head sibling;
-       struct notifier_block nb;
-       acpi_handle     handle;
 
        u8              function;       /* pci function# */
        u32             flags;          /* see below */
 };
 
+struct acpiphp_context {
+       acpi_handle handle;
+       struct acpiphp_func func;
+       struct acpiphp_bridge *bridge;
+       unsigned int refcount;
+};
+
+static inline struct acpiphp_context *func_to_context(struct acpiphp_func *func)
+{
+       return container_of(func, struct acpiphp_context, func);
+}
+
+static inline acpi_handle func_to_handle(struct acpiphp_func *func)
+{
+       return func_to_context(func)->handle;
+}
+
 /*
  * struct acpiphp_attention_info - device specific attention registration
  *
@@ -142,45 +154,32 @@ struct acpiphp_attention_info
        struct module *owner;
 };
 
-/* PCI bus bridge HID */
-#define ACPI_PCI_HOST_HID              "PNP0A03"
-
 /* ACPI _STA method value (ignore bit 4; battery present) */
 #define ACPI_STA_ALL                   (0x0000000f)
 
-/* bridge flags */
-#define BRIDGE_HAS_EJ0         (0x00000001)
-
 /* slot flags */
 
-#define SLOT_POWEREDON         (0x00000001)
-#define SLOT_ENABLED           (0x00000002)
-#define SLOT_MULTIFUNCTION     (0x00000004)
+#define SLOT_ENABLED           (0x00000001)
 
 /* function flags */
 
 #define FUNC_HAS_STA           (0x00000001)
 #define FUNC_HAS_EJ0           (0x00000002)
-#define FUNC_HAS_PS0           (0x00000010)
-#define FUNC_HAS_PS1           (0x00000020)
-#define FUNC_HAS_PS2           (0x00000040)
-#define FUNC_HAS_PS3           (0x00000080)
-#define FUNC_HAS_DCK            (0x00000100)
+#define FUNC_HAS_DCK            (0x00000004)
 
 /* function prototypes */
 
 /* acpiphp_core.c */
 int acpiphp_register_attention(struct acpiphp_attention_info*info);
 int acpiphp_unregister_attention(struct acpiphp_attention_info *info);
-int acpiphp_register_hotplug_slot(struct acpiphp_slot *slot);
+int acpiphp_register_hotplug_slot(struct acpiphp_slot *slot, unsigned int sun);
 void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot);
 
 /* acpiphp_glue.c */
 typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data);
 
 int acpiphp_enable_slot(struct acpiphp_slot *slot);
-int acpiphp_disable_slot(struct acpiphp_slot *slot);
-int acpiphp_eject_slot(struct acpiphp_slot *slot);
+int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot);
 u8 acpiphp_get_power_status(struct acpiphp_slot *slot);
 u8 acpiphp_get_attention_status(struct acpiphp_slot *slot);
 u8 acpiphp_get_latch_status(struct acpiphp_slot *slot);
index ca81279..bf2203e 100644 (file)
@@ -155,15 +155,11 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
 static int disable_slot(struct hotplug_slot *hotplug_slot)
 {
        struct slot *slot = hotplug_slot->private;
-       int retval;
 
        dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
 
        /* disable the specified slot */
-       retval = acpiphp_disable_slot(slot->acpi_slot);
-       if (!retval)
-               retval = acpiphp_eject_slot(slot->acpi_slot);
-       return retval;
+       return acpiphp_disable_and_eject_slot(slot->acpi_slot);
 }
 
 
@@ -290,7 +286,8 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
 }
 
 /* callback routine to initialize 'struct slot' for each slot */
-int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot)
+int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot,
+                                 unsigned int sun)
 {
        struct slot *slot;
        int retval = -ENOMEM;
@@ -317,12 +314,11 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot)
        slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot);
 
        acpiphp_slot->slot = slot;
-       snprintf(name, SLOT_NAME_SIZE, "%llu", slot->acpi_slot->sun);
+       slot->sun = sun;
+       snprintf(name, SLOT_NAME_SIZE, "%u", sun);
 
-       retval = pci_hp_register(slot->hotplug_slot,
-                                       acpiphp_slot->bridge->pci_bus,
-                                       acpiphp_slot->device,
-                                       name);
+       retval = pci_hp_register(slot->hotplug_slot, acpiphp_slot->bus,
+                                acpiphp_slot->device, name);
        if (retval == -EBUSY)
                goto error_hpslot;
        if (retval) {
index 59df857..8054ddc 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/pci.h>
 #include <linux/pci_hotplug.h>
 #include <linux/pci-acpi.h>
+#include <linux/pm_runtime.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
 #include <linux/acpi.h>
 
 static LIST_HEAD(bridge_list);
 static DEFINE_MUTEX(bridge_mutex);
+static DEFINE_MUTEX(acpiphp_context_lock);
 
 #define MY_NAME "acpiphp_glue"
 
-static void handle_hotplug_event_bridge (acpi_handle, u32, void *);
+static void handle_hotplug_event(acpi_handle handle, u32 type, void *data);
 static void acpiphp_sanitize_bus(struct pci_bus *bus);
 static void acpiphp_set_hpp_values(struct pci_bus *bus);
-static void hotplug_event_func(acpi_handle handle, u32 type, void *context);
-static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context);
+static void hotplug_event(acpi_handle handle, u32 type, void *data);
 static void free_bridge(struct kref *kref);
 
-/* callback routine to check for the existence of a pci dock device */
-static acpi_status
-is_pci_dock_device(acpi_handle handle, u32 lvl, void *context, void **rv)
+static void acpiphp_context_handler(acpi_handle handle, void *context)
 {
-       int *count = (int *)context;
+       /* Intentionally empty. */
+}
 
-       if (is_dock_device(handle)) {
-               (*count)++;
-               return AE_CTRL_TERMINATE;
-       } else {
-               return AE_OK;
+/**
+ * acpiphp_init_context - Create hotplug context and grab a reference to it.
+ * @handle: ACPI object handle to create the context for.
+ *
+ * Call under acpiphp_context_lock.
+ */
+static struct acpiphp_context *acpiphp_init_context(acpi_handle handle)
+{
+       struct acpiphp_context *context;
+       acpi_status status;
+
+       context = kzalloc(sizeof(*context), GFP_KERNEL);
+       if (!context)
+               return NULL;
+
+       context->handle = handle;
+       context->refcount = 1;
+       status = acpi_attach_data(handle, acpiphp_context_handler, context);
+       if (ACPI_FAILURE(status)) {
+               kfree(context);
+               return NULL;
        }
+       return context;
+}
+
+/**
+ * acpiphp_get_context - Get hotplug context and grab a reference to it.
+ * @handle: ACPI object handle to get the context for.
+ *
+ * Call under acpiphp_context_lock.
+ */
+static struct acpiphp_context *acpiphp_get_context(acpi_handle handle)
+{
+       struct acpiphp_context *context = NULL;
+       acpi_status status;
+       void *data;
+
+       status = acpi_get_data(handle, acpiphp_context_handler, &data);
+       if (ACPI_SUCCESS(status)) {
+               context = data;
+               context->refcount++;
+       }
+       return context;
+}
+
+/**
+ * acpiphp_put_context - Drop a reference to ACPI hotplug context.
+ * @handle: ACPI object handle to put the context for.
+ *
+ * The context object is removed if there are no more references to it.
+ *
+ * Call under acpiphp_context_lock.
+ */
+static void acpiphp_put_context(struct acpiphp_context *context)
+{
+       if (--context->refcount)
+               return;
+
+       WARN_ON(context->bridge);
+       acpi_detach_data(context->handle, acpiphp_context_handler);
+       kfree(context);
 }
 
 static inline void get_bridge(struct acpiphp_bridge *bridge)
@@ -91,25 +146,36 @@ static inline void put_bridge(struct acpiphp_bridge *bridge)
 
 static void free_bridge(struct kref *kref)
 {
+       struct acpiphp_context *context;
        struct acpiphp_bridge *bridge;
        struct acpiphp_slot *slot, *next;
        struct acpiphp_func *func, *tmp;
 
+       mutex_lock(&acpiphp_context_lock);
+
        bridge = container_of(kref, struct acpiphp_bridge, ref);
 
        list_for_each_entry_safe(slot, next, &bridge->slots, node) {
-               list_for_each_entry_safe(func, tmp, &slot->funcs, sibling) {
-                       kfree(func);
-               }
+               list_for_each_entry_safe(func, tmp, &slot->funcs, sibling)
+                       acpiphp_put_context(func_to_context(func));
+
                kfree(slot);
        }
 
-       /* Release reference acquired by acpiphp_bridge_handle_to_function() */
-       if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func)
-               put_bridge(bridge->func->slot->bridge);
+       context = bridge->context;
+       /* Root bridges will not have hotplug context. */
+       if (context) {
+               /* Release the reference taken by acpiphp_enumerate_slots(). */
+               put_bridge(context->func.parent);
+               context->bridge = NULL;
+               acpiphp_put_context(context);
+       }
+
        put_device(&bridge->pci_bus->dev);
        pci_dev_put(bridge->pci_dev);
        kfree(bridge);
+
+       mutex_unlock(&acpiphp_context_lock);
 }
 
 /*
@@ -119,15 +185,14 @@ static void free_bridge(struct kref *kref)
  * TBD - figure out a way to only call fixups for
  * systems that require them.
  */
-static int post_dock_fixups(struct notifier_block *nb, unsigned long val,
-       void *v)
+static void post_dock_fixups(acpi_handle not_used, u32 event, void *data)
 {
-       struct acpiphp_func *func = container_of(nb, struct acpiphp_func, nb);
-       struct pci_bus *bus = func->slot->bridge->pci_bus;
+       struct acpiphp_context *context = data;
+       struct pci_bus *bus = context->func.slot->bus;
        u32 buses;
 
        if (!bus->self)
-               return  NOTIFY_OK;
+               return;
 
        /* fixup bad _DCK function that rewrites
         * secondary bridge on slot
@@ -143,12 +208,12 @@ static int post_dock_fixups(struct notifier_block *nb, unsigned long val,
                        | ((unsigned int)(bus->busn_res.end) << 16);
                pci_write_config_dword(bus->self, PCI_PRIMARY_BUS, buses);
        }
-       return NOTIFY_OK;
 }
 
 
 static const struct acpi_dock_ops acpiphp_dock_ops = {
-       .handler = hotplug_event_func,
+       .fixup = post_dock_fixups,
+       .handler = hotplug_event,
 };
 
 /* Check whether the PCI device is managed by native PCIe hotplug driver */
@@ -182,129 +247,118 @@ static bool device_is_managed_by_native_pciehp(struct pci_dev *pdev)
 
 static void acpiphp_dock_init(void *data)
 {
-       struct acpiphp_func *func = data;
+       struct acpiphp_context *context = data;
 
-       get_bridge(func->slot->bridge);
+       get_bridge(context->func.parent);
 }
 
 static void acpiphp_dock_release(void *data)
 {
-       struct acpiphp_func *func = data;
+       struct acpiphp_context *context = data;
 
-       put_bridge(func->slot->bridge);
+       put_bridge(context->func.parent);
 }
 
 /* callback routine to register each ACPI PCI slot object */
-static acpi_status
-register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
+static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data,
+                                void **rv)
 {
-       struct acpiphp_bridge *bridge = (struct acpiphp_bridge *)context;
+       struct acpiphp_bridge *bridge = data;
+       struct acpiphp_context *context;
        struct acpiphp_slot *slot;
        struct acpiphp_func *newfunc;
-       acpi_handle tmp;
        acpi_status status = AE_OK;
-       unsigned long long adr, sun;
-       int device, function, retval, found = 0;
+       unsigned long long adr;
+       int device, function;
        struct pci_bus *pbus = bridge->pci_bus;
-       struct pci_dev *pdev;
+       struct pci_dev *pdev = bridge->pci_dev;
        u32 val;
 
-       if (!acpi_pci_check_ejectable(pbus, handle) && !is_dock_device(handle))
+       if (pdev && device_is_managed_by_native_pciehp(pdev))
                return AE_OK;
 
        status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
        if (ACPI_FAILURE(status)) {
-               warn("can't evaluate _ADR (%#x)\n", status);
+               acpi_handle_warn(handle, "can't evaluate _ADR (%#x)\n", status);
                return AE_OK;
        }
 
        device = (adr >> 16) & 0xffff;
        function = adr & 0xffff;
 
-       pdev = bridge->pci_dev;
-       if (pdev && device_is_managed_by_native_pciehp(pdev))
-               return AE_OK;
-
-       newfunc = kzalloc(sizeof(struct acpiphp_func), GFP_KERNEL);
-       if (!newfunc)
-               return AE_NO_MEMORY;
-
-       newfunc->handle = handle;
+       mutex_lock(&acpiphp_context_lock);
+       context = acpiphp_init_context(handle);
+       if (!context) {
+               mutex_unlock(&acpiphp_context_lock);
+               acpi_handle_err(handle, "No hotplug context\n");
+               return AE_NOT_EXIST;
+       }
+       newfunc = &context->func;
        newfunc->function = function;
+       newfunc->parent = bridge;
+       mutex_unlock(&acpiphp_context_lock);
 
-       if (ACPI_SUCCESS(acpi_get_handle(handle, "_EJ0", &tmp)))
+       if (acpi_has_method(handle, "_EJ0"))
                newfunc->flags = FUNC_HAS_EJ0;
 
-       if (ACPI_SUCCESS(acpi_get_handle(handle, "_STA", &tmp)))
+       if (acpi_has_method(handle, "_STA"))
                newfunc->flags |= FUNC_HAS_STA;
 
-       if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS0", &tmp)))
-               newfunc->flags |= FUNC_HAS_PS0;
-
-       if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS3", &tmp)))
-               newfunc->flags |= FUNC_HAS_PS3;
-
-       if (ACPI_SUCCESS(acpi_get_handle(handle, "_DCK", &tmp)))
+       if (acpi_has_method(handle, "_DCK"))
                newfunc->flags |= FUNC_HAS_DCK;
 
-       status = acpi_evaluate_integer(handle, "_SUN", NULL, &sun);
-       if (ACPI_FAILURE(status)) {
-               /*
-                * use the count of the number of slots we've found
-                * for the number of the slot
-                */
-               sun = bridge->nr_slots+1;
-       }
-
        /* search for objects that share the same slot */
        list_for_each_entry(slot, &bridge->slots, node)
-               if (slot->device == device) {
-                       if (slot->sun != sun)
-                               warn("sibling found, but _SUN doesn't match!\n");
-                       found = 1;
-                       break;
-               }
+               if (slot->device == device)
+                       goto slot_found;
 
-       if (!found) {
-               slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL);
-               if (!slot) {
-                       kfree(newfunc);
-                       return AE_NO_MEMORY;
-               }
+       slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL);
+       if (!slot) {
+               status = AE_NO_MEMORY;
+               goto err;
+       }
 
-               slot->bridge = bridge;
-               slot->device = device;
-               slot->sun = sun;
-               INIT_LIST_HEAD(&slot->funcs);
-               mutex_init(&slot->crit_sect);
+       slot->bus = bridge->pci_bus;
+       slot->device = device;
+       INIT_LIST_HEAD(&slot->funcs);
+       mutex_init(&slot->crit_sect);
+
+       list_add_tail(&slot->node, &bridge->slots);
+
+       /* Register slots for ejectable funtions only. */
+       if (acpi_pci_check_ejectable(pbus, handle)  || is_dock_device(handle)) {
+               unsigned long long sun;
+               int retval;
 
-               mutex_lock(&bridge_mutex);
-               list_add_tail(&slot->node, &bridge->slots);
-               mutex_unlock(&bridge_mutex);
                bridge->nr_slots++;
+               status = acpi_evaluate_integer(handle, "_SUN", NULL, &sun);
+               if (ACPI_FAILURE(status))
+                       sun = bridge->nr_slots;
 
                dbg("found ACPI PCI Hotplug slot %llu at PCI %04x:%02x:%02x\n",
-                   slot->sun, pci_domain_nr(pbus), pbus->number, device);
-               retval = acpiphp_register_hotplug_slot(slot);
+                   sun, pci_domain_nr(pbus), pbus->number, device);
+
+               retval = acpiphp_register_hotplug_slot(slot, sun);
                if (retval) {
+                       slot->slot = NULL;
+                       bridge->nr_slots--;
                        if (retval == -EBUSY)
                                warn("Slot %llu already registered by another "
-                                       "hotplug driver\n", slot->sun);
+                                       "hotplug driver\n", sun);
                        else
                                warn("acpiphp_register_hotplug_slot failed "
                                        "(err code = 0x%x)\n", retval);
-                       goto err_exit;
                }
+               /* Even if the slot registration fails, we can still use it. */
        }
 
+ slot_found:
        newfunc->slot = slot;
-       mutex_lock(&bridge_mutex);
        list_add_tail(&newfunc->sibling, &slot->funcs);
-       mutex_unlock(&bridge_mutex);
 
        if (pci_bus_read_dev_vendor_id(pbus, PCI_DEVFN(device, function),
                                       &val, 60*1000))
-               slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON);
+               slot->flags |= SLOT_ENABLED;
 
        if (is_dock_device(handle)) {
                /* we don't want to call this device's _EJ0
@@ -313,136 +367,46 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
                 */
                newfunc->flags &= ~FUNC_HAS_EJ0;
                if (register_hotplug_dock_device(handle,
-                       &acpiphp_dock_ops, newfunc,
+                       &acpiphp_dock_ops, context,
                        acpiphp_dock_init, acpiphp_dock_release))
                        dbg("failed to register dock device\n");
-
-               /* we need to be notified when dock events happen
-                * outside of the hotplug operation, since we may
-                * need to do fixups before we can hotplug.
-                */
-               newfunc->nb.notifier_call = post_dock_fixups;
-               if (register_dock_notifier(&newfunc->nb))
-                       dbg("failed to register a dock notifier");
        }
 
        /* install notify handler */
        if (!(newfunc->flags & FUNC_HAS_DCK)) {
-               status = acpi_install_notify_handler(handle,
-                                            ACPI_SYSTEM_NOTIFY,
-                                            handle_hotplug_event_func,
-                                            newfunc);
-
+               status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+                                                    handle_hotplug_event,
+                                                    context);
                if (ACPI_FAILURE(status))
-                       err("failed to register interrupt notify handler\n");
-       } else
-               status = AE_OK;
-
-       return status;
-
- err_exit:
-       bridge->nr_slots--;
-       mutex_lock(&bridge_mutex);
-       list_del(&slot->node);
-       mutex_unlock(&bridge_mutex);
-       kfree(slot);
-       kfree(newfunc);
-
-       return AE_OK;
-}
-
-
-/* see if it's worth looking at this bridge */
-static int detect_ejectable_slots(acpi_handle handle)
-{
-       int found = acpi_pci_detect_ejectable(handle);
-       if (!found) {
-               acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
-                                   is_pci_dock_device, NULL, (void *)&found, NULL);
-       }
-       return found;
-}
-
-/* initialize miscellaneous stuff for both root and PCI-to-PCI bridge */
-static void init_bridge_misc(struct acpiphp_bridge *bridge)
-{
-       acpi_status status;
-
-       /* must be added to the list prior to calling register_slot */
-       mutex_lock(&bridge_mutex);
-       list_add(&bridge->list, &bridge_list);
-       mutex_unlock(&bridge_mutex);
-
-       /* register all slot objects under this bridge */
-       status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1,
-                                    register_slot, NULL, bridge, NULL);
-       if (ACPI_FAILURE(status)) {
-               mutex_lock(&bridge_mutex);
-               list_del(&bridge->list);
-               mutex_unlock(&bridge_mutex);
-               return;
+                       acpi_handle_err(handle,
+                                       "failed to install notify handler\n");
        }
 
-       /* install notify handler for P2P bridges */
-       if (!pci_is_root_bus(bridge->pci_bus)) {
-               if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) {
-                       status = acpi_remove_notify_handler(bridge->func->handle,
-                                               ACPI_SYSTEM_NOTIFY,
-                                               handle_hotplug_event_func);
-                       if (ACPI_FAILURE(status))
-                               err("failed to remove notify handler\n");
-               }
-               status = acpi_install_notify_handler(bridge->handle,
-                                            ACPI_SYSTEM_NOTIFY,
-                                            handle_hotplug_event_bridge,
-                                            bridge);
-
-               if (ACPI_FAILURE(status)) {
-                       err("failed to register interrupt notify handler\n");
-               }
-       }
-}
-
-
-/* find acpiphp_func from acpiphp_bridge */
-static struct acpiphp_func *acpiphp_bridge_handle_to_function(acpi_handle handle)
-{
-       struct acpiphp_bridge *bridge;
-       struct acpiphp_slot *slot;
-       struct acpiphp_func *func = NULL;
-
-       mutex_lock(&bridge_mutex);
-       list_for_each_entry(bridge, &bridge_list, list) {
-               list_for_each_entry(slot, &bridge->slots, node) {
-                       list_for_each_entry(func, &slot->funcs, sibling) {
-                               if (func->handle == handle) {
-                                       get_bridge(func->slot->bridge);
-                                       mutex_unlock(&bridge_mutex);
-                                       return func;
-                               }
-                       }
-               }
-       }
-       mutex_unlock(&bridge_mutex);
+       return AE_OK;
 
-       return NULL;
+ err:
+       mutex_lock(&acpiphp_context_lock);
+       acpiphp_put_context(context);
+       mutex_unlock(&acpiphp_context_lock);
+       return status;
 }
 
-
 static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle)
 {
-       struct acpiphp_bridge *bridge;
-
-       mutex_lock(&bridge_mutex);
-       list_for_each_entry(bridge, &bridge_list, list)
-               if (bridge->handle == handle) {
+       struct acpiphp_context *context;
+       struct acpiphp_bridge *bridge = NULL;
+
+       mutex_lock(&acpiphp_context_lock);
+       context = acpiphp_get_context(handle);
+       if (context) {
+               bridge = context->bridge;
+               if (bridge)
                        get_bridge(bridge);
-                       mutex_unlock(&bridge_mutex);
-                       return bridge;
-               }
-       mutex_unlock(&bridge_mutex);
 
-       return NULL;
+               acpiphp_put_context(context);
+       }
+       mutex_unlock(&acpiphp_context_lock);
+       return bridge;
 }
 
 static void cleanup_bridge(struct acpiphp_bridge *bridge)
@@ -450,40 +414,24 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
        struct acpiphp_slot *slot;
        struct acpiphp_func *func;
        acpi_status status;
-       acpi_handle handle = bridge->handle;
-
-       if (!pci_is_root_bus(bridge->pci_bus)) {
-               status = acpi_remove_notify_handler(handle,
-                                           ACPI_SYSTEM_NOTIFY,
-                                           handle_hotplug_event_bridge);
-               if (ACPI_FAILURE(status))
-                       err("failed to remove notify handler\n");
-       }
-
-       if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) {
-               status = acpi_install_notify_handler(bridge->func->handle,
-                                               ACPI_SYSTEM_NOTIFY,
-                                               handle_hotplug_event_func,
-                                               bridge->func);
-               if (ACPI_FAILURE(status))
-                       err("failed to install interrupt notify handler\n");
-       }
 
        list_for_each_entry(slot, &bridge->slots, node) {
                list_for_each_entry(func, &slot->funcs, sibling) {
-                       if (is_dock_device(func->handle)) {
-                               unregister_hotplug_dock_device(func->handle);
-                               unregister_dock_notifier(&func->nb);
-                       }
+                       acpi_handle handle = func_to_handle(func);
+
+                       if (is_dock_device(handle))
+                               unregister_hotplug_dock_device(handle);
+
                        if (!(func->flags & FUNC_HAS_DCK)) {
-                               status = acpi_remove_notify_handler(func->handle,
-                                               ACPI_SYSTEM_NOTIFY,
-                                               handle_hotplug_event_func);
+                               status = acpi_remove_notify_handler(handle,
+                                                       ACPI_SYSTEM_NOTIFY,
+                                                       handle_hotplug_event);
                                if (ACPI_FAILURE(status))
                                        err("failed to remove notify handler\n");
                        }
                }
-               acpiphp_unregister_hotplug_slot(slot);
+               if (slot->slot)
+                       acpiphp_unregister_hotplug_slot(slot);
        }
 
        mutex_lock(&bridge_mutex);
@@ -491,71 +439,6 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
        mutex_unlock(&bridge_mutex);
 }
 
-static int power_on_slot(struct acpiphp_slot *slot)
-{
-       acpi_status status;
-       struct acpiphp_func *func;
-       int retval = 0;
-
-       /* if already enabled, just skip */
-       if (slot->flags & SLOT_POWEREDON)
-               goto err_exit;
-
-       list_for_each_entry(func, &slot->funcs, sibling) {
-               if (func->flags & FUNC_HAS_PS0) {
-                       dbg("%s: executing _PS0\n", __func__);
-                       status = acpi_evaluate_object(func->handle, "_PS0", NULL, NULL);
-                       if (ACPI_FAILURE(status)) {
-                               warn("%s: _PS0 failed\n", __func__);
-                               retval = -1;
-                               goto err_exit;
-                       } else
-                               break;
-               }
-       }
-
-       /* TBD: evaluate _STA to check if the slot is enabled */
-
-       slot->flags |= SLOT_POWEREDON;
-
- err_exit:
-       return retval;
-}
-
-
-static int power_off_slot(struct acpiphp_slot *slot)
-{
-       acpi_status status;
-       struct acpiphp_func *func;
-
-       int retval = 0;
-
-       /* if already disabled, just skip */
-       if ((slot->flags & SLOT_POWEREDON) == 0)
-               goto err_exit;
-
-       list_for_each_entry(func, &slot->funcs, sibling) {
-               if (func->flags & FUNC_HAS_PS3) {
-                       status = acpi_evaluate_object(func->handle, "_PS3", NULL, NULL);
-                       if (ACPI_FAILURE(status)) {
-                               warn("%s: _PS3 failed\n", __func__);
-                               retval = -1;
-                               goto err_exit;
-                       } else
-                               break;
-               }
-       }
-
-       /* TBD: evaluate _STA to check if the slot is disabled */
-
-       slot->flags &= (~SLOT_POWEREDON);
-
- err_exit:
-       return retval;
-}
-
-
-
 /**
  * acpiphp_max_busnr - return the highest reserved bus number under the given bus.
  * @bus: bus to start search with
@@ -583,52 +466,32 @@ static unsigned char acpiphp_max_busnr(struct pci_bus *bus)
        return max;
 }
 
-
 /**
- * acpiphp_bus_add - add a new bus to acpi subsystem
- * @func: acpiphp_func of the bridge
+ * acpiphp_bus_trim - Trim device objects in an ACPI namespace subtree.
+ * @handle: ACPI device object handle to start from.
  */
-static int acpiphp_bus_add(struct acpiphp_func *func)
+static void acpiphp_bus_trim(acpi_handle handle)
 {
-       struct acpi_device *device;
-       int ret_val;
-
-       if (!acpi_bus_get_device(func->handle, &device)) {
-               dbg("bus exists... trim\n");
-               /* this shouldn't be in here, so remove
-                * the bus then re-add it...
-                */
-               acpi_bus_trim(device);
-       }
-
-       ret_val = acpi_bus_scan(func->handle);
-       if (!ret_val)
-               ret_val = acpi_bus_get_device(func->handle, &device);
-
-       if (ret_val)
-               dbg("error adding bus, %x\n", -ret_val);
+       struct acpi_device *adev = NULL;
 
-       return ret_val;
+       acpi_bus_get_device(handle, &adev);
+       if (adev)
+               acpi_bus_trim(adev);
 }
 
-
 /**
- * acpiphp_bus_trim - trim a bus from acpi subsystem
- * @handle: handle to acpi namespace
+ * acpiphp_bus_add - Scan ACPI namespace subtree.
+ * @handle: ACPI object handle to start the scan from.
  */
-static int acpiphp_bus_trim(acpi_handle handle)
+static void acpiphp_bus_add(acpi_handle handle)
 {
-       struct acpi_device *device;
-       int retval;
-
-       retval = acpi_bus_get_device(handle, &device);
-       if (retval) {
-               dbg("acpi_device not found\n");
-               return retval;
-       }
+       struct acpi_device *adev = NULL;
 
-       acpi_bus_trim(device);
-       return 0;
+       acpiphp_bus_trim(handle);
+       acpi_bus_scan(handle);
+       acpi_bus_get_device(handle, &adev);
+       if (adev)
+               acpi_device_set_power(adev, ACPI_STATE_D0);
 }
 
 static void acpiphp_set_acpi_region(struct acpiphp_slot *slot)
@@ -645,7 +508,8 @@ static void acpiphp_set_acpi_region(struct acpiphp_slot *slot)
                params[1].type = ACPI_TYPE_INTEGER;
                params[1].integer.value = 1;
                /* _REG is optional, we don't care about if there is failure */
-               acpi_evaluate_object(func->handle, "_REG", &arg_list, NULL);
+               acpi_evaluate_object(func_to_handle(func), "_REG", &arg_list,
+                                    NULL);
        }
 }
 
@@ -653,59 +517,44 @@ static void check_hotplug_bridge(struct acpiphp_slot *slot, struct pci_dev *dev)
 {
        struct acpiphp_func *func;
 
-       if (!dev->subordinate)
-               return;
-
        /* quirk, or pcie could set it already */
        if (dev->is_hotplug_bridge)
                return;
 
-       if (PCI_SLOT(dev->devfn) != slot->device)
-               return;
-
        list_for_each_entry(func, &slot->funcs, sibling) {
                if (PCI_FUNC(dev->devfn) == func->function) {
-                       /* check if this bridge has ejectable slots */
-                       if ((detect_ejectable_slots(func->handle) > 0))
-                               dev->is_hotplug_bridge = 1;
+                       dev->is_hotplug_bridge = 1;
                        break;
                }
        }
 }
 
 /**
- * enable_device - enable, configure a slot
+ * enable_slot - enable, configure a slot
  * @slot: slot to be enabled
  *
  * This function should be called per *physical slot*,
  * not per each slot object in ACPI namespace.
  */
-static int __ref enable_device(struct acpiphp_slot *slot)
+static void __ref enable_slot(struct acpiphp_slot *slot)
 {
        struct pci_dev *dev;
-       struct pci_bus *bus = slot->bridge->pci_bus;
+       struct pci_bus *bus = slot->bus;
        struct acpiphp_func *func;
-       int num, max, pass;
+       int max, pass;
        LIST_HEAD(add_list);
 
-       if (slot->flags & SLOT_ENABLED)
-               goto err_exit;
-
        list_for_each_entry(func, &slot->funcs, sibling)
-               acpiphp_bus_add(func);
+               acpiphp_bus_add(func_to_handle(func));
 
-       num = pci_scan_slot(bus, PCI_DEVFN(slot->device, 0));
-       if (num == 0) {
-               /* Maybe only part of funcs are added. */
-               dbg("No new device found\n");
-               goto err_exit;
-       }
+       pci_scan_slot(bus, PCI_DEVFN(slot->device, 0));
 
        max = acpiphp_max_busnr(bus);
        for (pass = 0; pass < 2; pass++) {
                list_for_each_entry(dev, &bus->devices, bus_list) {
                        if (PCI_SLOT(dev->devfn) != slot->device)
                                continue;
+
                        if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
                            dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
                                max = pci_scan_bridge(bus, dev, max, pass);
@@ -744,16 +593,12 @@ static int __ref enable_device(struct acpiphp_slot *slot)
                        continue;
                }
        }
-
-
- err_exit:
-       return 0;
 }
 
 /* return first device in slot, acquiring a reference on it */
 static struct pci_dev *dev_in_slot(struct acpiphp_slot *slot)
 {
-       struct pci_bus *bus = slot->bridge->pci_bus;
+       struct pci_bus *bus = slot->bus;
        struct pci_dev *dev;
        struct pci_dev *ret = NULL;
 
@@ -769,16 +614,16 @@ static struct pci_dev *dev_in_slot(struct acpiphp_slot *slot)
 }
 
 /**
- * disable_device - disable a slot
+ * disable_slot - disable a slot
  * @slot: ACPI PHP slot
  */
-static int disable_device(struct acpiphp_slot *slot)
+static void disable_slot(struct acpiphp_slot *slot)
 {
        struct acpiphp_func *func;
        struct pci_dev *pdev;
 
        /*
-        * enable_device() enumerates all functions in this device via
+        * enable_slot() enumerates all functions in this device via
         * pci_scan_slot(), whether they have associated ACPI hotplug
         * methods (_EJ0, etc.) or not.  Therefore, we remove all functions
         * here.
@@ -788,13 +633,10 @@ static int disable_device(struct acpiphp_slot *slot)
                pci_dev_put(pdev);
        }
 
-       list_for_each_entry(func, &slot->funcs, sibling) {
-               acpiphp_bus_trim(func->handle);
-       }
+       list_for_each_entry(func, &slot->funcs, sibling)
+               acpiphp_bus_trim(func_to_handle(func));
 
        slot->flags &= (~SLOT_ENABLED);
-
-       return 0;
 }
 
 
@@ -812,18 +654,21 @@ static int disable_device(struct acpiphp_slot *slot)
  */
 static unsigned int get_slot_status(struct acpiphp_slot *slot)
 {
-       acpi_status status;
        unsigned long long sta = 0;
-       u32 dvid;
        struct acpiphp_func *func;
 
        list_for_each_entry(func, &slot->funcs, sibling) {
                if (func->flags & FUNC_HAS_STA) {
-                       status = acpi_evaluate_integer(func->handle, "_STA", NULL, &sta);
+                       acpi_status status;
+
+                       status = acpi_evaluate_integer(func_to_handle(func),
+                                                      "_STA", NULL, &sta);
                        if (ACPI_SUCCESS(status) && sta)
                                break;
                } else {
-                       pci_bus_read_config_dword(slot->bridge->pci_bus,
+                       u32 dvid;
+
+                       pci_bus_read_config_dword(slot->bus,
                                                  PCI_DEVFN(slot->device,
                                                            func->function),
                                                  PCI_VENDOR_ID, &dvid);
@@ -838,34 +683,42 @@ static unsigned int get_slot_status(struct acpiphp_slot *slot)
 }
 
 /**
- * acpiphp_eject_slot - physically eject the slot
- * @slot: ACPI PHP slot
+ * trim_stale_devices - remove PCI devices that are not responding.
+ * @dev: PCI device to start walking the hierarchy from.
  */
-int acpiphp_eject_slot(struct acpiphp_slot *slot)
+static void trim_stale_devices(struct pci_dev *dev)
 {
-       acpi_status status;
-       struct acpiphp_func *func;
-       struct acpi_object_list arg_list;
-       union acpi_object arg;
+       acpi_handle handle = ACPI_HANDLE(&dev->dev);
+       struct pci_bus *bus = dev->subordinate;
+       bool alive = false;
 
-       list_for_each_entry(func, &slot->funcs, sibling) {
-               /* We don't want to call _EJ0 on non-existing functions. */
-               if ((func->flags & FUNC_HAS_EJ0)) {
-                       /* _EJ0 method take one argument */
-                       arg_list.count = 1;
-                       arg_list.pointer = &arg;
-                       arg.type = ACPI_TYPE_INTEGER;
-                       arg.integer.value = 1;
-
-                       status = acpi_evaluate_object(func->handle, "_EJ0", &arg_list, NULL);
-                       if (ACPI_FAILURE(status)) {
-                               warn("%s: _EJ0 failed\n", __func__);
-                               return -1;
-                       } else
-                               break;
-               }
+       if (handle) {
+               acpi_status status;
+               unsigned long long sta;
+
+               status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
+               alive = ACPI_SUCCESS(status) && sta == ACPI_STA_ALL;
+       }
+       if (!alive) {
+               u32 v;
+
+               /* Check if the device responds. */
+               alive = pci_bus_read_dev_vendor_id(dev->bus, dev->devfn, &v, 0);
+       }
+       if (!alive) {
+               pci_stop_and_remove_bus_device(dev);
+               if (handle)
+                       acpiphp_bus_trim(handle);
+       } else if (bus) {
+               struct pci_dev *child, *tmp;
+
+               /* The device is a bridge. so check the bus below it. */
+               pm_runtime_get_sync(&dev->dev);
+               list_for_each_entry_safe(child, tmp, &bus->devices, bus_list)
+                       trim_stale_devices(child);
+
+               pm_runtime_put(&dev->dev);
        }
-       return 0;
 }
 
 /**
@@ -875,43 +728,30 @@ int acpiphp_eject_slot(struct acpiphp_slot *slot)
  * Iterate over all slots under this bridge and make sure that if a
  * card is present they are enabled, and if not they are disabled.
  */
-static int acpiphp_check_bridge(struct acpiphp_bridge *bridge)
+static void acpiphp_check_bridge(struct acpiphp_bridge *bridge)
 {
        struct acpiphp_slot *slot;
-       int retval = 0;
-       int enabled, disabled;
-
-       enabled = disabled = 0;
 
        list_for_each_entry(slot, &bridge->slots, node) {
-               unsigned int status = get_slot_status(slot);
-               if (slot->flags & SLOT_ENABLED) {
-                       if (status == ACPI_STA_ALL)
-                               continue;
-                       retval = acpiphp_disable_slot(slot);
-                       if (retval) {
-                               err("Error occurred in disabling\n");
-                               goto err_exit;
-                       } else {
-                               acpiphp_eject_slot(slot);
-                       }
-                       disabled++;
+               struct pci_bus *bus = slot->bus;
+               struct pci_dev *dev, *tmp;
+
+               mutex_lock(&slot->crit_sect);
+               /* wake up all functions */
+               if (get_slot_status(slot) == ACPI_STA_ALL) {
+                       /* remove stale devices if any */
+                       list_for_each_entry_safe(dev, tmp, &bus->devices,
+                                                bus_list)
+                               if (PCI_SLOT(dev->devfn) == slot->device)
+                                       trim_stale_devices(dev);
+
+                       /* configure all functions */
+                       enable_slot(slot);
                } else {
-                       if (status != ACPI_STA_ALL)
-                               continue;
-                       retval = acpiphp_enable_slot(slot);
-                       if (retval) {
-                               err("Error occurred in enabling\n");
-                               goto err_exit;
-                       }
-                       enabled++;
+                       disable_slot(slot);
                }
+               mutex_unlock(&slot->crit_sect);
        }
-
-       dbg("%s: %d enabled, %d disabled\n", __func__, enabled, disabled);
-
- err_exit:
-       return retval;
 }
 
 static void acpiphp_set_hpp_values(struct pci_bus *bus)
@@ -950,25 +790,6 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus)
  * ACPI event handlers
  */
 
-static acpi_status
-check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
-{
-       struct acpiphp_bridge *bridge;
-       char objname[64];
-       struct acpi_buffer buffer = { .length = sizeof(objname),
-                                     .pointer = objname };
-
-       bridge = acpiphp_handle_to_bridge(handle);
-       if (bridge) {
-               acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
-               dbg("%s: re-enumerating slots under %s\n",
-                       __func__, objname);
-               acpiphp_check_bridge(bridge);
-               put_bridge(bridge);
-       }
-       return AE_OK ;
-}
-
 void acpiphp_check_host_bridge(acpi_handle handle)
 {
        struct acpiphp_bridge *bridge;
@@ -978,27 +799,23 @@ void acpiphp_check_host_bridge(acpi_handle handle)
                acpiphp_check_bridge(bridge);
                put_bridge(bridge);
        }
-
-       acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
-               ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL, NULL);
 }
 
-static void _handle_hotplug_event_bridge(struct work_struct *work)
+static void hotplug_event(acpi_handle handle, u32 type, void *data)
 {
+       struct acpiphp_context *context = data;
+       struct acpiphp_func *func = &context->func;
        struct acpiphp_bridge *bridge;
        char objname[64];
        struct acpi_buffer buffer = { .length = sizeof(objname),
                                      .pointer = objname };
-       struct acpi_hp_work *hp_work;
-       acpi_handle handle;
-       u32 type;
 
-       hp_work = container_of(work, struct acpi_hp_work, work);
-       handle = hp_work->handle;
-       type = hp_work->type;
-       bridge = (struct acpiphp_bridge *)hp_work->context;
+       mutex_lock(&acpiphp_context_lock);
+       bridge = context->bridge;
+       if (bridge)
+               get_bridge(bridge);
 
-       acpi_scan_lock_acquire();
+       mutex_unlock(&acpiphp_context_lock);
 
        acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
 
@@ -1007,188 +824,129 @@ static void _handle_hotplug_event_bridge(struct work_struct *work)
                /* bus re-enumerate */
                dbg("%s: Bus check notify on %s\n", __func__, objname);
                dbg("%s: re-enumerating slots under %s\n", __func__, objname);
-               acpiphp_check_bridge(bridge);
-               acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
-                       ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL, NULL);
+               if (bridge) {
+                       acpiphp_check_bridge(bridge);
+               } else {
+                       struct acpiphp_slot *slot = func->slot;
+
+                       mutex_lock(&slot->crit_sect);
+                       enable_slot(slot);
+                       mutex_unlock(&slot->crit_sect);
+               }
                break;
 
        case ACPI_NOTIFY_DEVICE_CHECK:
                /* device check */
                dbg("%s: Device check notify on %s\n", __func__, objname);
-               acpiphp_check_bridge(bridge);
-               break;
+               if (bridge)
+                       acpiphp_check_bridge(bridge);
+               else
+                       acpiphp_check_bridge(func->parent);
 
-       case ACPI_NOTIFY_DEVICE_WAKE:
-               /* wake event */
-               dbg("%s: Device wake notify on %s\n", __func__, objname);
                break;
 
        case ACPI_NOTIFY_EJECT_REQUEST:
                /* request device eject */
                dbg("%s: Device eject notify on %s\n", __func__, objname);
-               if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) {
-                       struct acpiphp_slot *slot;
-                       slot = bridge->func->slot;
-                       if (!acpiphp_disable_slot(slot))
-                               acpiphp_eject_slot(slot);
-               }
+               acpiphp_disable_and_eject_slot(func->slot);
                break;
+       }
 
-       case ACPI_NOTIFY_FREQUENCY_MISMATCH:
-               printk(KERN_ERR "Device %s cannot be configured due"
-                               " to a frequency mismatch\n", objname);
-               break;
+       if (bridge)
+               put_bridge(bridge);
+}
 
-       case ACPI_NOTIFY_BUS_MODE_MISMATCH:
-               printk(KERN_ERR "Device %s cannot be configured due"
-                               " to a bus mode mismatch\n", objname);
-               break;
+static void hotplug_event_work(struct work_struct *work)
+{
+       struct acpiphp_context *context;
+       struct acpi_hp_work *hp_work;
 
-       case ACPI_NOTIFY_POWER_FAULT:
-               printk(KERN_ERR "Device %s has suffered a power fault\n",
-                               objname);
-               break;
+       hp_work = container_of(work, struct acpi_hp_work, work);
+       context = hp_work->context;
+       acpi_scan_lock_acquire();
 
-       default:
-               warn("notify_handler: unknown event type 0x%x for %s\n", type, objname);
-               break;
-       }
+       hotplug_event(hp_work->handle, hp_work->type, context);
 
        acpi_scan_lock_release();
-       kfree(hp_work); /* allocated in handle_hotplug_event_bridge */
-       put_bridge(bridge);
+       kfree(hp_work); /* allocated in handle_hotplug_event() */
+       put_bridge(context->func.parent);
 }
 
 /**
- * handle_hotplug_event_bridge - handle ACPI event on bridges
+ * handle_hotplug_event - handle ACPI hotplug event
  * @handle: Notify()'ed acpi_handle
  * @type: Notify code
- * @context: pointer to acpiphp_bridge structure
+ * @data: pointer to acpiphp_context structure
  *
- * Handles ACPI event notification on {host,p2p} bridges.
+ * Handles ACPI event notification on slots.
  */
-static void handle_hotplug_event_bridge(acpi_handle handle, u32 type,
-                                       void *context)
+static void handle_hotplug_event(acpi_handle handle, u32 type, void *data)
 {
-       struct acpiphp_bridge *bridge = context;
-
-       /*
-        * Currently the code adds all hotplug events to the kacpid_wq
-        * queue when it should add hotplug events to the kacpi_hotplug_wq.
-        * The proper way to fix this is to reorganize the code so that
-        * drivers (dock, etc.) do not call acpi_os_execute(), etc.
-        * For now just re-add this work to the kacpi_hotplug_wq so we
-        * don't deadlock on hotplug actions.
-        */
-       get_bridge(bridge);
-       alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_bridge);
-}
-
-static void hotplug_event_func(acpi_handle handle, u32 type, void *context)
-{
-       struct acpiphp_func *func = context;
-       char objname[64];
-       struct acpi_buffer buffer = { .length = sizeof(objname),
-                                     .pointer = objname };
-
-       acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
+       struct acpiphp_context *context;
 
        switch (type) {
        case ACPI_NOTIFY_BUS_CHECK:
-               /* bus re-enumerate */
-               dbg("%s: Bus check notify on %s\n", __func__, objname);
-               acpiphp_enable_slot(func->slot);
-               break;
-
        case ACPI_NOTIFY_DEVICE_CHECK:
-               /* device check : re-enumerate from parent bus */
-               dbg("%s: Device check notify on %s\n", __func__, objname);
-               acpiphp_check_bridge(func->slot->bridge);
-               break;
-
-       case ACPI_NOTIFY_DEVICE_WAKE:
-               /* wake event */
-               dbg("%s: Device wake notify on %s\n", __func__, objname);
-               break;
-
        case ACPI_NOTIFY_EJECT_REQUEST:
-               /* request device eject */
-               dbg("%s: Device eject notify on %s\n", __func__, objname);
-               if (!(acpiphp_disable_slot(func->slot)))
-                       acpiphp_eject_slot(func->slot);
                break;
 
-       default:
-               warn("notify_handler: unknown event type 0x%x for %s\n", type, objname);
-               break;
-       }
-}
-
-static void _handle_hotplug_event_func(struct work_struct *work)
-{
-       struct acpi_hp_work *hp_work;
-       struct acpiphp_func *func;
+       case ACPI_NOTIFY_DEVICE_WAKE:
+               return;
 
-       hp_work = container_of(work, struct acpi_hp_work, work);
-       func = hp_work->context;
-       acpi_scan_lock_acquire();
+       case ACPI_NOTIFY_FREQUENCY_MISMATCH:
+               acpi_handle_err(handle, "Device cannot be configured due "
+                               "to a frequency mismatch\n");
+               return;
 
-       hotplug_event_func(hp_work->handle, hp_work->type, func);
+       case ACPI_NOTIFY_BUS_MODE_MISMATCH:
+               acpi_handle_err(handle, "Device cannot be configured due "
+                               "to a bus mode mismatch\n");
+               return;
 
-       acpi_scan_lock_release();
-       kfree(hp_work); /* allocated in handle_hotplug_event_func */
-       put_bridge(func->slot->bridge);
-}
+       case ACPI_NOTIFY_POWER_FAULT:
+               acpi_handle_err(handle, "Device has suffered a power fault\n");
+               return;
 
-/**
- * handle_hotplug_event_func - handle ACPI event on functions (i.e. slots)
- * @handle: Notify()'ed acpi_handle
- * @type: Notify code
- * @context: pointer to acpiphp_func structure
- *
- * Handles ACPI event notification on slots.
- */
-static void handle_hotplug_event_func(acpi_handle handle, u32 type,
-                                     void *context)
-{
-       struct acpiphp_func *func = context;
+       default:
+               acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type);
+               return;
+       }
 
-       /*
-        * Currently the code adds all hotplug events to the kacpid_wq
-        * queue when it should add hotplug events to the kacpi_hotplug_wq.
-        * The proper way to fix this is to reorganize the code so that
-        * drivers (dock, etc.) do not call acpi_os_execute(), etc.
-        * For now just re-add this work to the kacpi_hotplug_wq so we
-        * don't deadlock on hotplug actions.
-        */
-       get_bridge(func->slot->bridge);
-       alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_func);
+       mutex_lock(&acpiphp_context_lock);
+       context = acpiphp_get_context(handle);
+       if (context) {
+               get_bridge(context->func.parent);
+               acpiphp_put_context(context);
+               alloc_acpi_hp_work(handle, type, context, hotplug_event_work);
+       }
+       mutex_unlock(&acpiphp_context_lock);
 }
 
 /*
  * Create hotplug slots for the PCI bus.
  * It should always return 0 to avoid skipping following notifiers.
  */
-void acpiphp_enumerate_slots(struct pci_bus *bus, acpi_handle handle)
+void acpiphp_enumerate_slots(struct pci_bus *bus)
 {
-       acpi_handle dummy_handle;
        struct acpiphp_bridge *bridge;
+       acpi_handle handle;
+       acpi_status status;
 
        if (acpiphp_disabled)
                return;
 
-       if (detect_ejectable_slots(handle) <= 0)
+       handle = ACPI_HANDLE(bus->bridge);
+       if (!handle)
                return;
 
        bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
-       if (bridge == NULL) {
-               err("out of memory\n");
+       if (!bridge) {
+               acpi_handle_err(handle, "No memory for bridge object\n");
                return;
        }
 
        INIT_LIST_HEAD(&bridge->slots);
        kref_init(&bridge->ref);
-       bridge->handle = handle;
        bridge->pci_dev = pci_dev_get(bus->self);
        bridge->pci_bus = bus;
 
@@ -1199,31 +957,62 @@ void acpiphp_enumerate_slots(struct pci_bus *bus, acpi_handle handle)
         */
        get_device(&bus->dev);
 
-       if (!pci_is_root_bus(bridge->pci_bus) &&
-           ACPI_SUCCESS(acpi_get_handle(bridge->handle,
-                                       "_EJ0", &dummy_handle))) {
-               dbg("found ejectable p2p bridge\n");
-               bridge->flags |= BRIDGE_HAS_EJ0;
-               bridge->func = acpiphp_bridge_handle_to_function(handle);
+       if (!pci_is_root_bus(bridge->pci_bus)) {
+               struct acpiphp_context *context;
+
+               /*
+                * This bridge should have been registered as a hotplug function
+                * under its parent, so the context has to be there.  If not, we
+                * are in deep goo.
+                */
+               mutex_lock(&acpiphp_context_lock);
+               context = acpiphp_get_context(handle);
+               if (WARN_ON(!context)) {
+                       mutex_unlock(&acpiphp_context_lock);
+                       put_device(&bus->dev);
+                       kfree(bridge);
+                       return;
+               }
+               bridge->context = context;
+               context->bridge = bridge;
+               /* Get a reference to the parent bridge. */
+               get_bridge(context->func.parent);
+               mutex_unlock(&acpiphp_context_lock);
        }
 
-       init_bridge_misc(bridge);
+       /* must be added to the list prior to calling register_slot */
+       mutex_lock(&bridge_mutex);
+       list_add(&bridge->list, &bridge_list);
+       mutex_unlock(&bridge_mutex);
+
+       /* register all slot objects under this bridge */
+       status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
+                                    register_slot, NULL, bridge, NULL);
+       if (ACPI_FAILURE(status)) {
+               acpi_handle_err(handle, "failed to register slots\n");
+               cleanup_bridge(bridge);
+               put_bridge(bridge);
+       }
 }
 
 /* Destroy hotplug slots associated with the PCI bus */
 void acpiphp_remove_slots(struct pci_bus *bus)
 {
-       struct acpiphp_bridge *bridge, *tmp;
+       struct acpiphp_bridge *bridge;
 
        if (acpiphp_disabled)
                return;
 
-       list_for_each_entry_safe(bridge, tmp, &bridge_list, list)
+       mutex_lock(&bridge_mutex);
+       list_for_each_entry(bridge, &bridge_list, list)
                if (bridge->pci_bus == bus) {
+                       mutex_unlock(&bridge_mutex);
                        cleanup_bridge(bridge);
                        put_bridge(bridge);
-                       break;
+                       return;
                }
+
+       mutex_unlock(&bridge_mutex);
 }
 
 /**
@@ -1232,51 +1021,39 @@ void acpiphp_remove_slots(struct pci_bus *bus)
  */
 int acpiphp_enable_slot(struct acpiphp_slot *slot)
 {
-       int retval;
-
        mutex_lock(&slot->crit_sect);
+       /* configure all functions */
+       if (!(slot->flags & SLOT_ENABLED))
+               enable_slot(slot);
 
-       /* wake up all functions */
-       retval = power_on_slot(slot);
-       if (retval)
-               goto err_exit;
-
-       if (get_slot_status(slot) == ACPI_STA_ALL) {
-               /* configure all functions */
-               retval = enable_device(slot);
-               if (retval)
-                       power_off_slot(slot);
-       } else {
-               dbg("%s: Slot status is not ACPI_STA_ALL\n", __func__);
-               power_off_slot(slot);
-       }
-
- err_exit:
        mutex_unlock(&slot->crit_sect);
-       return retval;
+       return 0;
 }
 
 /**
- * acpiphp_disable_slot - power off slot
+ * acpiphp_disable_and_eject_slot - power off and eject slot
  * @slot: ACPI PHP slot
  */
-int acpiphp_disable_slot(struct acpiphp_slot *slot)
+int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot)
 {
+       struct acpiphp_func *func;
        int retval = 0;
 
        mutex_lock(&slot->crit_sect);
 
        /* unconfigure all functions */
-       retval = disable_device(slot);
-       if (retval)
-               goto err_exit;
+       disable_slot(slot);
+
+       list_for_each_entry(func, &slot->funcs, sibling)
+               if (func->flags & FUNC_HAS_EJ0) {
+                       acpi_handle handle = func_to_handle(func);
 
-       /* power off all functions */
-       retval = power_off_slot(slot);
-       if (retval)
-               goto err_exit;
+                       if (ACPI_FAILURE(acpi_evaluate_ej0(handle)))
+                               acpi_handle_err(handle, "_EJ0 failed\n");
+
+                       break;
+               }
 
- err_exit:
        mutex_unlock(&slot->crit_sect);
        return retval;
 }
@@ -1288,7 +1065,7 @@ int acpiphp_disable_slot(struct acpiphp_slot *slot)
  */
 u8 acpiphp_get_power_status(struct acpiphp_slot *slot)
 {
-       return (slot->flags & SLOT_POWEREDON);
+       return (slot->flags & SLOT_ENABLED);
 }
 
 
@@ -1298,11 +1075,7 @@ u8 acpiphp_get_power_status(struct acpiphp_slot *slot)
  */
 u8 acpiphp_get_latch_status(struct acpiphp_slot *slot)
 {
-       unsigned int sta;
-
-       sta = get_slot_status(slot);
-
-       return (sta & ACPI_STA_DEVICE_UI) ? 0 : 1;
+       return !(get_slot_status(slot) & ACPI_STA_DEVICE_UI);
 }
 
 
@@ -1312,9 +1085,5 @@ u8 acpiphp_get_latch_status(struct acpiphp_slot *slot)
  */
 u8 acpiphp_get_adapter_status(struct acpiphp_slot *slot)
 {
-       unsigned int sta;
-
-       sta = get_slot_status(slot);
-
-       return (sta == 0) ? 0 : 1;
+       return !!get_slot_status(slot);
 }
index c35e8ad..2f5786c 100644 (file)
@@ -66,7 +66,7 @@ do {                                                  \
 #define IBM_HARDWARE_ID1 "IBM37D0"
 #define IBM_HARDWARE_ID2 "IBM37D4"
 
-#define hpslot_to_sun(A) (((struct slot *)((A)->private))->acpi_slot->sun)
+#define hpslot_to_sun(A) (((struct slot *)((A)->private))->sun)
 
 /* union apci_descriptor - allows access to the
  * various device descriptors that are embedded in the
@@ -270,7 +270,6 @@ static void ibm_handle_events(acpi_handle handle, u32 event, void *context)
 
        if (subevent == 0x80) {
                dbg("%s: generationg bus event\n", __func__);
-               acpi_bus_generate_proc_event(note->device, note->event, detail);
                acpi_bus_generate_netlink_event(note->device->pnp.device_class,
                                                  dev_name(&note->device->dev),
                                                  note->event, detail);
index 01e264f..7c29ee4 100644 (file)
@@ -210,7 +210,7 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
        }
 
        if (!error)
-               dev_info(&dev->dev, "power state changed by ACPI to %s\n",
+               dev_dbg(&dev->dev, "power state changed by ACPI to %s\n",
                         acpi_power_state_string(state_conv[state]));
 
        return error;
@@ -290,24 +290,16 @@ static struct pci_platform_pm_ops acpi_pci_platform_pm = {
 
 void acpi_pci_add_bus(struct pci_bus *bus)
 {
-       acpi_handle handle = NULL;
-
-       if (bus->bridge)
-               handle = ACPI_HANDLE(bus->bridge);
-       if (acpi_pci_disabled || handle == NULL)
+       if (acpi_pci_disabled || !bus->bridge)
                return;
 
-       acpi_pci_slot_enumerate(bus, handle);
-       acpiphp_enumerate_slots(bus, handle);
+       acpi_pci_slot_enumerate(bus);
+       acpiphp_enumerate_slots(bus);
 }
 
 void acpi_pci_remove_bus(struct pci_bus *bus)
 {
-       /*
-        * bus->bridge->acpi_node.handle has already been reset to NULL
-        * when acpi_pci_remove_bus() is called, so don't check ACPI handle.
-        */
-       if (acpi_pci_disabled)
+       if (acpi_pci_disabled || !bus->bridge)
                return;
 
        acpiphp_remove_slots(bus);
index c47fd1e..94716c7 100644 (file)
@@ -278,6 +278,7 @@ static int sunxi_pconf_group_set(struct pinctrl_dev *pctldev,
 {
        struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
        struct sunxi_pinctrl_group *g = &pctl->groups[group];
+       unsigned long flags;
        u32 val, mask;
        u16 strength;
        u8 dlevel;
@@ -295,22 +296,35 @@ static int sunxi_pconf_group_set(struct pinctrl_dev *pctldev,
                 *   3: 40mA
                 */
                dlevel = strength / 10 - 1;
+
+               spin_lock_irqsave(&pctl->lock, flags);
+
                val = readl(pctl->membase + sunxi_dlevel_reg(g->pin));
                mask = DLEVEL_PINS_MASK << sunxi_dlevel_offset(g->pin);
                writel((val & ~mask) | dlevel << sunxi_dlevel_offset(g->pin),
                        pctl->membase + sunxi_dlevel_reg(g->pin));
+
+               spin_unlock_irqrestore(&pctl->lock, flags);
                break;
        case PIN_CONFIG_BIAS_PULL_UP:
+               spin_lock_irqsave(&pctl->lock, flags);
+
                val = readl(pctl->membase + sunxi_pull_reg(g->pin));
                mask = PULL_PINS_MASK << sunxi_pull_offset(g->pin);
                writel((val & ~mask) | 1 << sunxi_pull_offset(g->pin),
                        pctl->membase + sunxi_pull_reg(g->pin));
+
+               spin_unlock_irqrestore(&pctl->lock, flags);
                break;
        case PIN_CONFIG_BIAS_PULL_DOWN:
+               spin_lock_irqsave(&pctl->lock, flags);
+
                val = readl(pctl->membase + sunxi_pull_reg(g->pin));
                mask = PULL_PINS_MASK << sunxi_pull_offset(g->pin);
                writel((val & ~mask) | 2 << sunxi_pull_offset(g->pin),
                        pctl->membase + sunxi_pull_reg(g->pin));
+
+               spin_unlock_irqrestore(&pctl->lock, flags);
                break;
        default:
                break;
@@ -360,11 +374,17 @@ static void sunxi_pmx_set(struct pinctrl_dev *pctldev,
                                 u8 config)
 {
        struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+       unsigned long flags;
+       u32 val, mask;
+
+       spin_lock_irqsave(&pctl->lock, flags);
 
-       u32 val = readl(pctl->membase + sunxi_mux_reg(pin));
-       u32 mask = MUX_PINS_MASK << sunxi_mux_offset(pin);
+       val = readl(pctl->membase + sunxi_mux_reg(pin));
+       mask = MUX_PINS_MASK << sunxi_mux_offset(pin);
        writel((val & ~mask) | config << sunxi_mux_offset(pin),
                pctl->membase + sunxi_mux_reg(pin));
+
+       spin_unlock_irqrestore(&pctl->lock, flags);
 }
 
 static int sunxi_pmx_enable(struct pinctrl_dev *pctldev,
@@ -464,8 +484,21 @@ static void sunxi_pinctrl_gpio_set(struct gpio_chip *chip,
        struct sunxi_pinctrl *pctl = dev_get_drvdata(chip->dev);
        u32 reg = sunxi_data_reg(offset);
        u8 index = sunxi_data_offset(offset);
+       unsigned long flags;
+       u32 regval;
+
+       spin_lock_irqsave(&pctl->lock, flags);
+
+       regval = readl(pctl->membase + reg);
 
-       writel((value & DATA_PINS_MASK) << index, pctl->membase + reg);
+       if (value)
+               regval |= BIT(index);
+       else
+               regval &= ~(BIT(index));
+
+       writel(regval, pctl->membase + reg);
+
+       spin_unlock_irqrestore(&pctl->lock, flags);
 }
 
 static int sunxi_pinctrl_gpio_of_xlate(struct gpio_chip *gc,
@@ -526,6 +559,8 @@ static int sunxi_pinctrl_irq_set_type(struct irq_data *d,
        struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
        u32 reg = sunxi_irq_cfg_reg(d->hwirq);
        u8 index = sunxi_irq_cfg_offset(d->hwirq);
+       unsigned long flags;
+       u32 regval;
        u8 mode;
 
        switch (type) {
@@ -548,7 +583,13 @@ static int sunxi_pinctrl_irq_set_type(struct irq_data *d,
                return -EINVAL;
        }
 
-       writel((mode & IRQ_CFG_IRQ_MASK) << index, pctl->membase + reg);
+       spin_lock_irqsave(&pctl->lock, flags);
+
+       regval = readl(pctl->membase + reg);
+       regval &= ~IRQ_CFG_IRQ_MASK;
+       writel(regval | (mode << index), pctl->membase + reg);
+
+       spin_unlock_irqrestore(&pctl->lock, flags);
 
        return 0;
 }
@@ -560,14 +601,19 @@ static void sunxi_pinctrl_irq_mask_ack(struct irq_data *d)
        u8 ctrl_idx = sunxi_irq_ctrl_offset(d->hwirq);
        u32 status_reg = sunxi_irq_status_reg(d->hwirq);
        u8 status_idx = sunxi_irq_status_offset(d->hwirq);
+       unsigned long flags;
        u32 val;
 
+       spin_lock_irqsave(&pctl->lock, flags);
+
        /* Mask the IRQ */
        val = readl(pctl->membase + ctrl_reg);
        writel(val & ~(1 << ctrl_idx), pctl->membase + ctrl_reg);
 
        /* Clear the IRQ */
        writel(1 << status_idx, pctl->membase + status_reg);
+
+       spin_unlock_irqrestore(&pctl->lock, flags);
 }
 
 static void sunxi_pinctrl_irq_mask(struct irq_data *d)
@@ -575,11 +621,16 @@ static void sunxi_pinctrl_irq_mask(struct irq_data *d)
        struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
        u32 reg = sunxi_irq_ctrl_reg(d->hwirq);
        u8 idx = sunxi_irq_ctrl_offset(d->hwirq);
+       unsigned long flags;
        u32 val;
 
+       spin_lock_irqsave(&pctl->lock, flags);
+
        /* Mask the IRQ */
        val = readl(pctl->membase + reg);
        writel(val & ~(1 << idx), pctl->membase + reg);
+
+       spin_unlock_irqrestore(&pctl->lock, flags);
 }
 
 static void sunxi_pinctrl_irq_unmask(struct irq_data *d)
@@ -588,6 +639,7 @@ static void sunxi_pinctrl_irq_unmask(struct irq_data *d)
        struct sunxi_desc_function *func;
        u32 reg = sunxi_irq_ctrl_reg(d->hwirq);
        u8 idx = sunxi_irq_ctrl_offset(d->hwirq);
+       unsigned long flags;
        u32 val;
 
        func = sunxi_pinctrl_desc_find_function_by_pin(pctl,
@@ -597,9 +649,13 @@ static void sunxi_pinctrl_irq_unmask(struct irq_data *d)
        /* Change muxing to INT mode */
        sunxi_pmx_set(pctl->pctl_dev, pctl->irq_array[d->hwirq], func->muxval);
 
+       spin_lock_irqsave(&pctl->lock, flags);
+
        /* Unmask the IRQ */
        val = readl(pctl->membase + reg);
        writel(val | (1 << idx), pctl->membase + reg);
+
+       spin_unlock_irqrestore(&pctl->lock, flags);
 }
 
 static struct irq_chip sunxi_pinctrl_irq_chip = {
@@ -752,6 +808,8 @@ static int sunxi_pinctrl_probe(struct platform_device *pdev)
                return -ENOMEM;
        platform_set_drvdata(pdev, pctl);
 
+       spin_lock_init(&pctl->lock);
+
        pctl->membase = of_iomap(node, 0);
        if (!pctl->membase)
                return -ENOMEM;
index d68047d..01c494f 100644 (file)
@@ -14,6 +14,7 @@
 #define __PINCTRL_SUNXI_H
 
 #include <linux/kernel.h>
+#include <linux/spinlock.h>
 
 #define PA_BASE        0
 #define PB_BASE        32
@@ -407,6 +408,7 @@ struct sunxi_pinctrl {
        unsigned                        ngroups;
        int                             irq;
        int                             irq_array[SUNXI_IRQ_NUMBER];
+       spinlock_t                      lock;
        struct pinctrl_dev              *pctl_dev;
 };
 
index 0f9f859..f911952 100644 (file)
@@ -330,7 +330,7 @@ static int __init olpc_ec_init_module(void)
        return platform_driver_register(&olpc_ec_plat_driver);
 }
 
-module_init(olpc_ec_init_module);
+arch_initcall(olpc_ec_init_module);
 
 MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>");
 MODULE_LICENSE("GPL");
index 8e268da..0e9c169 100644 (file)
@@ -1543,7 +1543,6 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event)
 
        /* TODO Find a better way to handle events count. */
        count = asus->event_count[event % 128]++;
-       acpi_bus_generate_proc_event(asus->device, event, count);
        acpi_bus_generate_netlink_event(asus->device->pnp.device_class,
                                        dev_name(&asus->device->dev), event,
                                        count);
index 5d26e70..a6afd41 100644 (file)
@@ -1269,7 +1269,6 @@ static void eeepc_acpi_notify(struct acpi_device *device, u32 event)
        if (event > ACPI_MAX_SYS_NOTIFY)
                return;
        count = eeepc->event_count[event % 128]++;
-       acpi_bus_generate_proc_event(device, event, count);
        acpi_bus_generate_netlink_event(device->pnp.device_class,
                                        dev_name(&device->dev), event,
                                        count);
index 1c9386e..52b8a97 100644 (file)
@@ -773,8 +773,6 @@ static void acpi_fujitsu_notify(struct acpi_device *device, u32 event)
                                else
                                        set_lcd_level(newb);
                        }
-                       acpi_bus_generate_proc_event(fujitsu->dev,
-                               ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS, 0);
                        keycode = KEY_BRIGHTNESSUP;
                } else if (oldb > newb) {
                        if (disable_brightness_adjust != 1) {
@@ -783,8 +781,6 @@ static void acpi_fujitsu_notify(struct acpi_device *device, u32 event)
                                else
                                        set_lcd_level(newb);
                        }
-                       acpi_bus_generate_proc_event(fujitsu->dev,
-                               ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS, 0);
                        keycode = KEY_BRIGHTNESSDOWN;
                }
                break;
index 97bb05e..d6970f4 100644 (file)
@@ -53,7 +53,6 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4");
 #define HPWMI_ALS_QUERY 0x3
 #define HPWMI_HARDWARE_QUERY 0x4
 #define HPWMI_WIRELESS_QUERY 0x5
-#define HPWMI_BIOS_QUERY 0x9
 #define HPWMI_HOTKEY_QUERY 0xc
 #define HPWMI_WIRELESS2_QUERY 0x1b
 #define HPWMI_POSTCODEERROR_QUERY 0x2a
@@ -293,19 +292,6 @@ static int hp_wmi_tablet_state(void)
        return (state & 0x4) ? 1 : 0;
 }
 
-static int hp_wmi_enable_hotkeys(void)
-{
-       int ret;
-       int query = 0x6e;
-
-       ret = hp_wmi_perform_query(HPWMI_BIOS_QUERY, 1, &query, sizeof(query),
-                                  0);
-
-       if (ret)
-               return -EINVAL;
-       return 0;
-}
-
 static int hp_wmi_set_block(void *data, bool blocked)
 {
        enum hp_wmi_radio r = (enum hp_wmi_radio) data;
@@ -1009,8 +995,6 @@ static int __init hp_wmi_init(void)
                err = hp_wmi_input_setup();
                if (err)
                        return err;
-
-               hp_wmi_enable_hotkeys();
        }
 
        if (bios_capable) {
index 4add9a3..984253d 100644 (file)
@@ -464,9 +464,6 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
                                 "error getting hotkey status\n"));
                return;
        }
-
-       acpi_bus_generate_proc_event(pcc->device, HKEY_NOTIFY, result);
-
        if (!sparse_keymap_report_event(hotk_input_dev,
                                        result & 0xf, result & 0x80, false))
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
index 2ac045f..d3fd520 100644 (file)
@@ -1275,9 +1275,6 @@ static void sony_nc_notify(struct acpi_device *device, u32 event)
                ev_type = HOTKEY;
                sony_laptop_report_input_event(real_ev);
        }
-
-       acpi_bus_generate_proc_event(sony_nc_acpi_device, ev_type, real_ev);
-
        acpi_bus_generate_netlink_event(sony_nc_acpi_device->pnp.device_class,
                        dev_name(&sony_nc_acpi_device->dev), ev_type, real_ev);
 }
@@ -2440,7 +2437,10 @@ static ssize_t sony_nc_gfx_switch_status_show(struct device *dev,
        if (pos < 0)
                return pos;
 
-       return snprintf(buffer, PAGE_SIZE, "%s\n", pos ? "speed" : "stamina");
+       return snprintf(buffer, PAGE_SIZE, "%s\n",
+                                       pos == SPEED ? "speed" :
+                                       pos == STAMINA ? "stamina" :
+                                       pos == AUTO ? "auto" : "unknown");
 }
 
 static int sony_nc_gfx_switch_setup(struct platform_device *pd,
@@ -4243,7 +4243,6 @@ static irqreturn_t sony_pic_irq(int irq, void *dev_id)
 
 found:
        sony_laptop_report_input_event(device_event);
-       acpi_bus_generate_proc_event(dev->acpi_dev, 1, device_event);
        sonypi_compat_report_event(device_event);
        return IRQ_HANDLED;
 }
@@ -4320,7 +4319,8 @@ static int sony_pic_add(struct acpi_device *device)
                goto err_free_resources;
        }
 
-       if (sonypi_compat_init())
+       result = sonypi_compat_init();
+       if (result)
                goto err_remove_input;
 
        /* request io port */
index 54d31c0..be67e5e 100644 (file)
@@ -2022,8 +2022,6 @@ static u32 hotkey_driver_mask;            /* events needed by the driver */
 static u32 hotkey_user_mask;           /* events visible to userspace */
 static u32 hotkey_acpi_mask;           /* events enabled in firmware */
 
-static unsigned int hotkey_report_mode;
-
 static u16 *hotkey_keycode_map;
 
 static struct attribute_set *hotkey_dev_attributes;
@@ -2282,10 +2280,6 @@ static struct tp_acpi_drv_struct ibm_hotkey_acpidriver;
 static void tpacpi_hotkey_send_key(unsigned int scancode)
 {
        tpacpi_input_send_key_masked(scancode);
-       if (hotkey_report_mode < 2) {
-               acpi_bus_generate_proc_event(ibm_hotkey_acpidriver.device,
-                               0x80, TP_HKEY_EV_HOTKEY_BASE + scancode);
-       }
 }
 
 static void hotkey_read_nvram(struct tp_nvram_state *n, const u32 m)
@@ -2882,18 +2876,6 @@ static void hotkey_tablet_mode_notify_change(void)
                             "hotkey_tablet_mode");
 }
 
-/* sysfs hotkey report_mode -------------------------------------------- */
-static ssize_t hotkey_report_mode_show(struct device *dev,
-                          struct device_attribute *attr,
-                          char *buf)
-{
-       return snprintf(buf, PAGE_SIZE, "%d\n",
-               (hotkey_report_mode != 0) ? hotkey_report_mode : 1);
-}
-
-static struct device_attribute dev_attr_hotkey_report_mode =
-       __ATTR(hotkey_report_mode, S_IRUGO, hotkey_report_mode_show, NULL);
-
 /* sysfs wakeup reason (pollable) -------------------------------------- */
 static ssize_t hotkey_wakeup_reason_show(struct device *dev,
                           struct device_attribute *attr,
@@ -2935,7 +2917,6 @@ static struct attribute *hotkey_attributes[] __initdata = {
        &dev_attr_hotkey_enable.attr,
        &dev_attr_hotkey_bios_enabled.attr,
        &dev_attr_hotkey_bios_mask.attr,
-       &dev_attr_hotkey_report_mode.attr,
        &dev_attr_hotkey_wakeup_reason.attr,
        &dev_attr_hotkey_wakeup_hotunplug_complete.attr,
        &dev_attr_hotkey_mask.attr,
@@ -3439,11 +3420,6 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
                "initial masks: user=0x%08x, fw=0x%08x, poll=0x%08x\n",
                hotkey_user_mask, hotkey_acpi_mask, hotkey_source_mask);
 
-       dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
-                       "legacy ibm/hotkey event reporting over procfs %s\n",
-                       (hotkey_report_mode < 2) ?
-                               "enabled" : "disabled");
-
        tpacpi_inputdev->open = &hotkey_inputdev_open;
        tpacpi_inputdev->close = &hotkey_inputdev_close;
 
@@ -3737,13 +3713,6 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
                                  "event happened to %s\n", TPACPI_MAIL);
                }
 
-               /* Legacy events */
-               if (!ignore_acpi_ev &&
-                   (send_acpi_ev || hotkey_report_mode < 2)) {
-                       acpi_bus_generate_proc_event(ibm->acpi->device,
-                                                    event, hkey);
-               }
-
                /* netlink events */
                if (!ignore_acpi_ev && send_acpi_ev) {
                        acpi_bus_generate_netlink_event(
@@ -8840,11 +8809,6 @@ module_param(brightness_enable, uint, 0444);
 MODULE_PARM_DESC(brightness_enable,
                 "Enables backlight control when 1, disables when 0");
 
-module_param(hotkey_report_mode, uint, 0444);
-MODULE_PARM_DESC(hotkey_report_mode,
-                "used for backwards compatibility with userspace, "
-                "see documentation");
-
 #ifdef CONFIG_THINKPAD_ACPI_ALSA_SUPPORT
 module_param_named(volume_mode, volume_mode, uint, 0444);
 MODULE_PARM_DESC(volume_mode,
@@ -8975,10 +8939,6 @@ static int __init thinkpad_acpi_module_init(void)
 
        tpacpi_lifecycle = TPACPI_LIFE_INIT;
 
-       /* Parameter checking */
-       if (hotkey_report_mode > 2)
-               return -EINVAL;
-
        /* Driver-level probe */
 
        ret = get_thinkpad_model_data(&thinkpad_id);
index 00e9403..12adb43 100644 (file)
@@ -154,7 +154,7 @@ static int pnp_bus_match(struct device *dev, struct device_driver *drv)
        return 1;
 }
 
-static int pnp_bus_suspend(struct device *dev, pm_message_t state)
+static int __pnp_bus_suspend(struct device *dev, pm_message_t state)
 {
        struct pnp_dev *pnp_dev = to_pnp_dev(dev);
        struct pnp_driver *pnp_drv = pnp_dev->driver;
@@ -180,6 +180,16 @@ static int pnp_bus_suspend(struct device *dev, pm_message_t state)
        return 0;
 }
 
+static int pnp_bus_suspend(struct device *dev)
+{
+       return __pnp_bus_suspend(dev, PMSG_SUSPEND);
+}
+
+static int pnp_bus_freeze(struct device *dev)
+{
+       return __pnp_bus_suspend(dev, PMSG_FREEZE);
+}
+
 static int pnp_bus_resume(struct device *dev)
 {
        struct pnp_dev *pnp_dev = to_pnp_dev(dev);
@@ -210,14 +220,19 @@ static int pnp_bus_resume(struct device *dev)
        return 0;
 }
 
+static const struct dev_pm_ops pnp_bus_dev_pm_ops = {
+       .suspend = pnp_bus_suspend,
+       .freeze = pnp_bus_freeze,
+       .resume = pnp_bus_resume,
+};
+
 struct bus_type pnp_bus_type = {
        .name    = "pnp",
        .match   = pnp_bus_match,
        .probe   = pnp_device_probe,
        .remove  = pnp_device_remove,
        .shutdown = pnp_device_shutdown,
-       .suspend = pnp_bus_suspend,
-       .resume  = pnp_bus_resume,
+       .pm      = &pnp_bus_dev_pm_ops,
        .dev_attrs = pnp_interface_attrs,
 };
 
index 55cd459..34049b0 100644 (file)
@@ -131,7 +131,7 @@ static int pnpacpi_disable_resources(struct pnp_dev *dev)
        /* acpi_unregister_gsi(pnp_irq(dev, 0)); */
        ret = 0;
        if (acpi_bus_power_manageable(handle))
-               acpi_bus_set_power(handle, ACPI_STATE_D3);
+               acpi_bus_set_power(handle, ACPI_STATE_D3_COLD);
                /* continue even if acpi_bus_set_power() fails */
        if (ACPI_FAILURE(acpi_evaluate_object(handle, "_DIS", NULL, NULL)))
                ret = -ENODEV;
@@ -174,10 +174,10 @@ static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state)
 
        if (acpi_bus_power_manageable(handle)) {
                int power_state = acpi_pm_device_sleep_state(&dev->dev, NULL,
-                                                            ACPI_STATE_D3);
+                                                       ACPI_STATE_D3_COLD);
                if (power_state < 0)
                        power_state = (state.event == PM_EVENT_ON) ?
-                                       ACPI_STATE_D0 : ACPI_STATE_D3;
+                                       ACPI_STATE_D0 : ACPI_STATE_D3_COLD;
 
                /*
                 * acpi_bus_set_power() often fails (keyboard port can't be
index 1d4c8fe..c82fe65 100644 (file)
@@ -102,10 +102,13 @@ static void zfcp_erp_action_dismiss_port(struct zfcp_port *port)
 
        if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_INUSE)
                zfcp_erp_action_dismiss(&port->erp_action);
-       else
-               shost_for_each_device(sdev, port->adapter->scsi_host)
+       else {
+               spin_lock(port->adapter->scsi_host->host_lock);
+               __shost_for_each_device(sdev, port->adapter->scsi_host)
                        if (sdev_to_zfcp(sdev)->port == port)
                                zfcp_erp_action_dismiss_lun(sdev);
+               spin_unlock(port->adapter->scsi_host->host_lock);
+       }
 }
 
 static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
@@ -592,9 +595,11 @@ static void _zfcp_erp_lun_reopen_all(struct zfcp_port *port, int clear,
 {
        struct scsi_device *sdev;
 
-       shost_for_each_device(sdev, port->adapter->scsi_host)
+       spin_lock(port->adapter->scsi_host->host_lock);
+       __shost_for_each_device(sdev, port->adapter->scsi_host)
                if (sdev_to_zfcp(sdev)->port == port)
                        _zfcp_erp_lun_reopen(sdev, clear, id, 0);
+       spin_unlock(port->adapter->scsi_host->host_lock);
 }
 
 static void zfcp_erp_strategy_followup_failed(struct zfcp_erp_action *act)
@@ -1434,8 +1439,10 @@ void zfcp_erp_set_adapter_status(struct zfcp_adapter *adapter, u32 mask)
                atomic_set_mask(common_mask, &port->status);
        read_unlock_irqrestore(&adapter->port_list_lock, flags);
 
-       shost_for_each_device(sdev, adapter->scsi_host)
+       spin_lock_irqsave(adapter->scsi_host->host_lock, flags);
+       __shost_for_each_device(sdev, adapter->scsi_host)
                atomic_set_mask(common_mask, &sdev_to_zfcp(sdev)->status);
+       spin_unlock_irqrestore(adapter->scsi_host->host_lock, flags);
 }
 
 /**
@@ -1469,11 +1476,13 @@ void zfcp_erp_clear_adapter_status(struct zfcp_adapter *adapter, u32 mask)
        }
        read_unlock_irqrestore(&adapter->port_list_lock, flags);
 
-       shost_for_each_device(sdev, adapter->scsi_host) {
+       spin_lock_irqsave(adapter->scsi_host->host_lock, flags);
+       __shost_for_each_device(sdev, adapter->scsi_host) {
                atomic_clear_mask(common_mask, &sdev_to_zfcp(sdev)->status);
                if (clear_counter)
                        atomic_set(&sdev_to_zfcp(sdev)->erp_counter, 0);
        }
+       spin_unlock_irqrestore(adapter->scsi_host->host_lock, flags);
 }
 
 /**
@@ -1487,16 +1496,19 @@ void zfcp_erp_set_port_status(struct zfcp_port *port, u32 mask)
 {
        struct scsi_device *sdev;
        u32 common_mask = mask & ZFCP_COMMON_FLAGS;
+       unsigned long flags;
 
        atomic_set_mask(mask, &port->status);
 
        if (!common_mask)
                return;
 
-       shost_for_each_device(sdev, port->adapter->scsi_host)
+       spin_lock_irqsave(port->adapter->scsi_host->host_lock, flags);
+       __shost_for_each_device(sdev, port->adapter->scsi_host)
                if (sdev_to_zfcp(sdev)->port == port)
                        atomic_set_mask(common_mask,
                                        &sdev_to_zfcp(sdev)->status);
+       spin_unlock_irqrestore(port->adapter->scsi_host->host_lock, flags);
 }
 
 /**
@@ -1511,6 +1523,7 @@ void zfcp_erp_clear_port_status(struct zfcp_port *port, u32 mask)
        struct scsi_device *sdev;
        u32 common_mask = mask & ZFCP_COMMON_FLAGS;
        u32 clear_counter = mask & ZFCP_STATUS_COMMON_ERP_FAILED;
+       unsigned long flags;
 
        atomic_clear_mask(mask, &port->status);
 
@@ -1520,13 +1533,15 @@ void zfcp_erp_clear_port_status(struct zfcp_port *port, u32 mask)
        if (clear_counter)
                atomic_set(&port->erp_counter, 0);
 
-       shost_for_each_device(sdev, port->adapter->scsi_host)
+       spin_lock_irqsave(port->adapter->scsi_host->host_lock, flags);
+       __shost_for_each_device(sdev, port->adapter->scsi_host)
                if (sdev_to_zfcp(sdev)->port == port) {
                        atomic_clear_mask(common_mask,
                                          &sdev_to_zfcp(sdev)->status);
                        if (clear_counter)
                                atomic_set(&sdev_to_zfcp(sdev)->erp_counter, 0);
                }
+       spin_unlock_irqrestore(port->adapter->scsi_host->host_lock, flags);
 }
 
 /**
index 665e3cf..de0598e 100644 (file)
@@ -224,11 +224,9 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
 
 static int zfcp_qdio_sbal_check(struct zfcp_qdio *qdio)
 {
-       spin_lock_irq(&qdio->req_q_lock);
        if (atomic_read(&qdio->req_q_free) ||
            !(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))
                return 1;
-       spin_unlock_irq(&qdio->req_q_lock);
        return 0;
 }
 
@@ -246,9 +244,8 @@ int zfcp_qdio_sbal_get(struct zfcp_qdio *qdio)
 {
        long ret;
 
-       spin_unlock_irq(&qdio->req_q_lock);
-       ret = wait_event_interruptible_timeout(qdio->req_q_wq,
-                              zfcp_qdio_sbal_check(qdio), 5 * HZ);
+       ret = wait_event_interruptible_lock_irq_timeout(qdio->req_q_wq,
+                      zfcp_qdio_sbal_check(qdio), qdio->req_q_lock, 5 * HZ);
 
        if (!(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))
                return -EIO;
@@ -262,7 +259,6 @@ int zfcp_qdio_sbal_get(struct zfcp_qdio *qdio)
                zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdsbg_1");
        }
 
-       spin_lock_irq(&qdio->req_q_lock);
        return -EIO;
 }
 
index 3f01bbf..8906392 100644 (file)
@@ -27,6 +27,16 @@ static ssize_t zfcp_sysfs_##_feat##_##_name##_show(struct device *dev,              \
 static ZFCP_DEV_ATTR(_feat, _name, S_IRUGO,                                   \
                     zfcp_sysfs_##_feat##_##_name##_show, NULL);
 
+#define ZFCP_DEFINE_ATTR_CONST(_feat, _name, _format, _value)                 \
+static ssize_t zfcp_sysfs_##_feat##_##_name##_show(struct device *dev,        \
+                                                  struct device_attribute *at,\
+                                                  char *buf)                  \
+{                                                                             \
+       return sprintf(buf, _format, _value);                                  \
+}                                                                             \
+static ZFCP_DEV_ATTR(_feat, _name, S_IRUGO,                                   \
+                    zfcp_sysfs_##_feat##_##_name##_show, NULL);
+
 #define ZFCP_DEFINE_A_ATTR(_name, _format, _value)                          \
 static ssize_t zfcp_sysfs_adapter_##_name##_show(struct device *dev,        \
                                                 struct device_attribute *at,\
@@ -75,6 +85,8 @@ ZFCP_DEFINE_ATTR(zfcp_unit, unit, in_recovery, "%d\n",
 ZFCP_DEFINE_ATTR(zfcp_unit, unit, access_denied, "%d\n",
                 (zfcp_unit_sdev_status(unit) &
                  ZFCP_STATUS_COMMON_ACCESS_DENIED) != 0);
+ZFCP_DEFINE_ATTR_CONST(unit, access_shared, "%d\n", 0);
+ZFCP_DEFINE_ATTR_CONST(unit, access_readonly, "%d\n", 0);
 
 static ssize_t zfcp_sysfs_port_failed_show(struct device *dev,
                                           struct device_attribute *attr,
@@ -347,6 +359,8 @@ static struct attribute *zfcp_unit_attrs[] = {
        &dev_attr_unit_in_recovery.attr,
        &dev_attr_unit_status.attr,
        &dev_attr_unit_access_denied.attr,
+       &dev_attr_unit_access_shared.attr,
+       &dev_attr_unit_access_readonly.attr,
        NULL
 };
 static struct attribute_group zfcp_unit_attr_group = {
index 48b2918..92ff027 100644 (file)
@@ -1353,7 +1353,6 @@ config SCSI_LPFC
        tristate "Emulex LightPulse Fibre Channel Support"
        depends on PCI && SCSI
        select SCSI_FC_ATTRS
-       select GENERIC_CSUM
        select CRC_T10DIF
        help
           This lpfc driver supports the Emulex LightPulse
index e25eba5..b3b5125 100644 (file)
@@ -482,7 +482,7 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it)
                ret = comedi_device_postconfig(dev);
        if (ret < 0) {
                comedi_device_detach(dev);
-               module_put(dev->driver->module);
+               module_put(driv->module);
        }
        /* On success, the driver module count has been incremented. */
        return ret;
index 08613e2..0f1d193 100644 (file)
@@ -304,6 +304,11 @@ static int __init ohci_pci_init(void)
        pr_info("%s: " DRIVER_DESC "\n", hcd_name);
 
        ohci_init_driver(&ohci_pci_hc_driver, &pci_overrides);
+
+       /* Entries for the PCI suspend/resume callbacks are special */
+       ohci_pci_hc_driver.pci_suspend = ohci_suspend;
+       ohci_pci_hc_driver.pci_resume = ohci_resume;
+
        return pci_register_driver(&ohci_pci_driver);
 }
 module_init(ohci_pci_init);
index ca26628..e1859b8 100644 (file)
@@ -15,7 +15,7 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include "otg_fsm.h"
+#include "phy-fsm-usb.h"
 #include <linux/usb/otg.h>
 #include <linux/ioctl.h>
 
index c520b35..7f45966 100644 (file)
@@ -29,7 +29,7 @@
 #include <linux/usb/gadget.h>
 #include <linux/usb/otg.h>
 
-#include "phy-otg-fsm.h"
+#include "phy-fsm-usb.h"
 
 /* Change USB protocol when there is a protocol change */
 static int otg_set_protocol(struct otg_fsm *fsm, int protocol)
index 119d42a..90307c0 100644 (file)
 #include <asm/xen/hypercall.h>
 #include <asm/xen/hypervisor.h>
 
-int xen_acpi_notify_hypervisor_state(u8 sleep_state,
-                                    u32 pm1a_cnt, u32 pm1b_cnt)
+static int xen_acpi_notify_hypervisor_state(u8 sleep_state,
+                                           u32 val_a, u32 val_b,
+                                           bool extended)
 {
+       unsigned int bits = extended ? 8 : 16;
+
        struct xen_platform_op op = {
                .cmd = XENPF_enter_acpi_sleep,
                .interface_version = XENPF_INTERFACE_VERSION,
-               .u = {
-                       .enter_acpi_sleep = {
-                               .pm1a_cnt_val = (u16)pm1a_cnt,
-                               .pm1b_cnt_val = (u16)pm1b_cnt,
-                               .sleep_state = sleep_state,
-                       },
+               .u.enter_acpi_sleep = {
+                       .val_a = (u16)val_a,
+                       .val_b = (u16)val_b,
+                       .sleep_state = sleep_state,
+                       .flags = extended ? XENPF_ACPI_SLEEP_EXTENDED : 0,
                },
        };
 
-       if ((pm1a_cnt & 0xffff0000) || (pm1b_cnt & 0xffff0000)) {
-               WARN(1, "Using more than 16bits of PM1A/B 0x%x/0x%x!"
-                    "Email xen-devel@lists.xensource.com  Thank you.\n", \
-                    pm1a_cnt, pm1b_cnt);
+       if (WARN((val_a & (~0 << bits)) || (val_b & (~0 << bits)),
+                "Using more than %u bits of sleep control values %#x/%#x!"
+                "Email xen-devel@lists.xen.org - Thank you.\n", \
+                bits, val_a, val_b))
                return -1;
-       }
 
        HYPERVISOR_dom0_op(&op);
        return 1;
 }
+
+int xen_acpi_notify_hypervisor_sleep(u8 sleep_state,
+                                    u32 pm1a_cnt, u32 pm1b_cnt)
+{
+       return xen_acpi_notify_hypervisor_state(sleep_state, pm1a_cnt,
+                                               pm1b_cnt, false);
+}
+
+int xen_acpi_notify_hypervisor_extended_sleep(u8 sleep_state,
+                                    u32 val_a, u32 val_b)
+{
+       return xen_acpi_notify_hypervisor_state(sleep_state, val_a,
+                                               val_b, true);
+}
index a58ac43..5e8be46 100644 (file)
@@ -348,7 +348,7 @@ static void init_evtchn_cpu_bindings(void)
 
        for_each_possible_cpu(i)
                memset(per_cpu(cpu_evtchn_mask, i),
-                      (i == 0) ? ~0 : 0, sizeof(*per_cpu(cpu_evtchn_mask, i)));
+                      (i == 0) ? ~0 : 0, NR_EVENT_CHANNELS/8);
 }
 
 static inline void clear_evtchn(int port)
@@ -1493,8 +1493,10 @@ void rebind_evtchn_irq(int evtchn, int irq)
 /* Rebind an evtchn so that it gets delivered to a specific cpu */
 static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
 {
+       struct shared_info *s = HYPERVISOR_shared_info;
        struct evtchn_bind_vcpu bind_vcpu;
        int evtchn = evtchn_from_irq(irq);
+       int masked;
 
        if (!VALID_EVTCHN(evtchn))
                return -1;
@@ -1510,6 +1512,12 @@ static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
        bind_vcpu.port = evtchn;
        bind_vcpu.vcpu = tcpu;
 
+       /*
+        * Mask the event while changing the VCPU binding to prevent
+        * it being delivered on an unexpected VCPU.
+        */
+       masked = sync_test_and_set_bit(evtchn, BM(s->evtchn_mask));
+
        /*
         * If this fails, it usually just indicates that we're dealing with a
         * virq or IPI channel, which don't actually need to be rebound. Ignore
@@ -1518,6 +1526,9 @@ static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
        if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_vcpu, &bind_vcpu) >= 0)
                bind_evtchn_to_cpu(evtchn, tcpu);
 
+       if (!masked)
+               unmask_evtchn(evtchn);
+
        return 0;
 }
 
index 5e376bb..8defc6b 100644 (file)
@@ -40,7 +40,7 @@ struct inode *bfs_iget(struct super_block *sb, unsigned long ino)
        int block, off;
 
        inode = iget_locked(sb, ino);
-       if (IS_ERR(inode))
+       if (!inode)
                return ERR_PTR(-ENOMEM);
        if (!(inode->i_state & I_NEW))
                return inode;
index 94bbc04..c5eae72 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -1045,12 +1045,22 @@ static int __bio_copy_iov(struct bio *bio, struct bio_vec *iovecs,
 int bio_uncopy_user(struct bio *bio)
 {
        struct bio_map_data *bmd = bio->bi_private;
-       int ret = 0;
+       struct bio_vec *bvec;
+       int ret = 0, i;
 
-       if (!bio_flagged(bio, BIO_NULL_MAPPED))
-               ret = __bio_copy_iov(bio, bmd->iovecs, bmd->sgvecs,
-                                    bmd->nr_sgvecs, bio_data_dir(bio) == READ,
-                                    0, bmd->is_our_pages);
+       if (!bio_flagged(bio, BIO_NULL_MAPPED)) {
+               /*
+                * if we're in a workqueue, the request is orphaned, so
+                * don't copy into a random user address space, just free.
+                */
+               if (current->mm)
+                       ret = __bio_copy_iov(bio, bmd->iovecs, bmd->sgvecs,
+                                            bmd->nr_sgvecs, bio_data_dir(bio) == READ,
+                                            0, bmd->is_our_pages);
+               else if (bmd->is_our_pages)
+                       bio_for_each_segment_all(bvec, bio, i)
+                               __free_page(bvec->bv_page);
+       }
        bio_free_map_data(bmd);
        bio_put(bio);
        return ret;
index 87bdb53..83cfb83 100644 (file)
@@ -2724,6 +2724,17 @@ char *dynamic_dname(struct dentry *dentry, char *buffer, int buflen,
        return memcpy(buffer, temp, sz);
 }
 
+char *simple_dname(struct dentry *dentry, char *buffer, int buflen)
+{
+       char *end = buffer + buflen;
+       /* these dentries are never renamed, so d_lock is not needed */
+       if (prepend(&end, &buflen, " (deleted)", 11) ||
+           prepend_name(&end, &buflen, &dentry->d_name) ||
+           prepend(&end, &buflen, "/", 1))  
+               end = ERR_PTR(-ENAMETOOLONG);
+       return end;  
+}
+
 /*
  * Write full pathname from the root of the filesystem into the buffer.
  */
index f3913eb..d15ccf2 100644 (file)
@@ -57,7 +57,7 @@ struct inode *efs_iget(struct super_block *super, unsigned long ino)
        struct inode *inode;
 
        inode = iget_locked(super, ino);
-       if (IS_ERR(inode))
+       if (!inode)
                return ERR_PTR(-ENOMEM);
        if (!(inode->i_state & I_NEW))
                return inode;
index 9435384..544a809 100644 (file)
@@ -1838,14 +1838,14 @@ int __init gfs2_glock_init(void)
 
        glock_workqueue = alloc_workqueue("glock_workqueue", WQ_MEM_RECLAIM |
                                          WQ_HIGHPRI | WQ_FREEZABLE, 0);
-       if (IS_ERR(glock_workqueue))
-               return PTR_ERR(glock_workqueue);
+       if (!glock_workqueue)
+               return -ENOMEM;
        gfs2_delete_workqueue = alloc_workqueue("delete_workqueue",
                                                WQ_MEM_RECLAIM | WQ_FREEZABLE,
                                                0);
-       if (IS_ERR(gfs2_delete_workqueue)) {
+       if (!gfs2_delete_workqueue) {
                destroy_workqueue(glock_workqueue);
-               return PTR_ERR(gfs2_delete_workqueue);
+               return -ENOMEM;
        }
 
        register_shrinker(&glock_shrinker);
index 5f2e522..e2e0a90 100644 (file)
@@ -47,7 +47,8 @@ static void gfs2_ail_error(struct gfs2_glock *gl, const struct buffer_head *bh)
  * None of the buffers should be dirty, locked, or pinned.
  */
 
-static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
+static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync,
+                            unsigned int nr_revokes)
 {
        struct gfs2_sbd *sdp = gl->gl_sbd;
        struct list_head *head = &gl->gl_ail_list;
@@ -57,7 +58,9 @@ static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
 
        gfs2_log_lock(sdp);
        spin_lock(&sdp->sd_ail_lock);
-       list_for_each_entry_safe(bd, tmp, head, bd_ail_gl_list) {
+       list_for_each_entry_safe_reverse(bd, tmp, head, bd_ail_gl_list) {
+               if (nr_revokes == 0)
+                       break;
                bh = bd->bd_bh;
                if (bh->b_state & b_state) {
                        if (fsync)
@@ -65,6 +68,7 @@ static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
                        gfs2_ail_error(gl, bh);
                }
                gfs2_trans_add_revoke(sdp, bd);
+               nr_revokes--;
        }
        GLOCK_BUG_ON(gl, !fsync && atomic_read(&gl->gl_ail_count));
        spin_unlock(&sdp->sd_ail_lock);
@@ -91,7 +95,7 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl)
        WARN_ON_ONCE(current->journal_info);
        current->journal_info = &tr;
 
-       __gfs2_ail_flush(gl, 0);
+       __gfs2_ail_flush(gl, 0, tr.tr_revokes);
 
        gfs2_trans_end(sdp);
        gfs2_log_flush(sdp, NULL);
@@ -101,15 +105,19 @@ void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
 {
        struct gfs2_sbd *sdp = gl->gl_sbd;
        unsigned int revokes = atomic_read(&gl->gl_ail_count);
+       unsigned int max_revokes = (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_log_descriptor)) / sizeof(u64);
        int ret;
 
        if (!revokes)
                return;
 
-       ret = gfs2_trans_begin(sdp, 0, revokes);
+       while (revokes > max_revokes)
+               max_revokes += (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_meta_header)) / sizeof(u64);
+
+       ret = gfs2_trans_begin(sdp, 0, max_revokes);
        if (ret)
                return;
-       __gfs2_ail_flush(gl, fsync);
+       __gfs2_ail_flush(gl, fsync, max_revokes);
        gfs2_trans_end(sdp);
        gfs2_log_flush(sdp, NULL);
 }
index bbb2715..64915ee 100644 (file)
@@ -594,7 +594,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
                }
                gfs2_glock_dq_uninit(ghs);
                if (IS_ERR(d))
-                       return PTR_RET(d);
+                       return PTR_ERR(d);
                return error;
        } else if (error != -ENOENT) {
                goto fail_gunlock;
@@ -1750,6 +1750,10 @@ static ssize_t gfs2_getxattr(struct dentry *dentry, const char *name,
        struct gfs2_holder gh;
        int ret;
 
+       /* For selinux during lookup */
+       if (gfs2_glock_is_locked_by_me(ip->i_gl))
+               return generic_getxattr(dentry, name, data, size);
+
        gfs2_holder_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh);
        ret = gfs2_glock_nq(&gh);
        if (ret == 0) {
index e04d0e0..7b0f504 100644 (file)
@@ -155,7 +155,7 @@ static int __init init_gfs2_fs(void)
                goto fail_wq;
 
        gfs2_control_wq = alloc_workqueue("gfs2_control",
-                              WQ_NON_REENTRANT | WQ_UNBOUND | WQ_FREEZABLE, 0);
+                                         WQ_UNBOUND | WQ_FREEZABLE, 0);
        if (!gfs2_control_wq)
                goto fail_recovery;
 
index 3442397..d19b30a 100644 (file)
@@ -926,14 +926,8 @@ static int get_hstate_idx(int page_size_log)
        return h - hstates;
 }
 
-static char *hugetlb_dname(struct dentry *dentry, char *buffer, int buflen)
-{
-       return dynamic_dname(dentry, buffer, buflen, "/%s (deleted)",
-                               dentry->d_name.name);
-}
-
 static struct dentry_operations anon_ops = {
-       .d_dname = hugetlb_dname
+       .d_dname = simple_dname
 };
 
 /*
index 7b1ca9b..a45ba4f 100644 (file)
@@ -1429,7 +1429,7 @@ struct vfsmount *collect_mounts(struct path *path)
                         CL_COPY_ALL | CL_PRIVATE);
        namespace_unlock();
        if (IS_ERR(tree))
-               return NULL;
+               return ERR_CAST(tree);
        return &tree->mnt;
 }
 
index dc9a913..2d8be51 100644 (file)
@@ -345,8 +345,7 @@ static void nilfs_end_bio_write(struct bio *bio, int err)
 
        if (err == -EOPNOTSUPP) {
                set_bit(BIO_EOPNOTSUPP, &bio->bi_flags);
-               bio_put(bio);
-               /* to be detected by submit_seg_bio() */
+               /* to be detected by nilfs_segbuf_submit_bio() */
        }
 
        if (!uptodate)
@@ -377,12 +376,12 @@ static int nilfs_segbuf_submit_bio(struct nilfs_segment_buffer *segbuf,
        bio->bi_private = segbuf;
        bio_get(bio);
        submit_bio(mode, bio);
+       segbuf->sb_nbio++;
        if (bio_flagged(bio, BIO_EOPNOTSUPP)) {
                bio_put(bio);
                err = -EOPNOTSUPP;
                goto failed;
        }
-       segbuf->sb_nbio++;
        bio_put(bio);
 
        wi->bio = NULL;
index 75f2890..0ff80f9 100644 (file)
@@ -228,8 +228,6 @@ static int proc_readfd_common(struct file *file, struct dir_context *ctx,
        if (!p)
                return -ENOENT;
 
-       if (!dir_emit_dots(file, ctx))
-               goto out;
        if (!dir_emit_dots(file, ctx))
                goto out;
        files = get_files_struct(p);
index 94441a4..737e156 100644 (file)
@@ -271,7 +271,7 @@ int proc_readdir_de(struct proc_dir_entry *de, struct file *file,
                de = next;
        } while (de);
        spin_unlock(&proc_subdir_lock);
-       return 0;
+       return 1;
 }
 
 int proc_readdir(struct file *file, struct dir_context *ctx)
index 229e366..e0a790d 100644 (file)
@@ -205,7 +205,9 @@ static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentr
 static int proc_root_readdir(struct file *file, struct dir_context *ctx)
 {
        if (ctx->pos < FIRST_PROCESS_ENTRY) {
-               proc_readdir(file, ctx);
+               int error = proc_readdir(file, ctx);
+               if (unlikely(error <= 0))
+                       return error;
                ctx->pos = FIRST_PROCESS_ENTRY;
        }
 
index 94383a7..22650cd 100644 (file)
@@ -56,6 +56,16 @@ acpi_evaluate_hotplug_ost(acpi_handle handle, u32 source_event,
 
 acpi_status
 acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld_info **pld);
+
+bool acpi_has_method(acpi_handle handle, char *name);
+acpi_status acpi_execute_simple_method(acpi_handle handle, char *method,
+                                      u64 arg);
+acpi_status acpi_evaluate_ej0(acpi_handle handle);
+acpi_status acpi_evaluate_lck(acpi_handle handle, int lock);
+bool acpi_ata_match(acpi_handle handle);
+bool acpi_bay_match(acpi_handle handle);
+bool acpi_dock_match(acpi_handle handle);
+
 #ifdef CONFIG_ACPI
 
 #include <linux/proc_fs.h>
@@ -352,14 +362,11 @@ extern int acpi_notifier_call_chain(struct acpi_device *, u32, u32);
 extern int register_acpi_notifier(struct notifier_block *);
 extern int unregister_acpi_notifier(struct notifier_block *);
 
-extern int register_acpi_bus_notifier(struct notifier_block *nb);
-extern void unregister_acpi_bus_notifier(struct notifier_block *nb);
 /*
  * External Functions
  */
 
 int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device);
-void acpi_bus_data_handler(acpi_handle handle, void *context);
 acpi_status acpi_bus_get_status_handle(acpi_handle handle,
                                       unsigned long long *sta);
 int acpi_bus_get_status(struct acpi_device *device);
@@ -379,15 +386,6 @@ bool acpi_bus_can_wakeup(acpi_handle handle);
 static inline bool acpi_bus_can_wakeup(acpi_handle handle) { return false; }
 #endif
 
-#ifdef CONFIG_ACPI_PROC_EVENT
-int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data);
-int acpi_bus_generate_proc_event4(const char *class, const char *bid, u8 type, int data);
-int acpi_bus_receive_event(struct acpi_bus_event *event);
-#else
-static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
-       { return 0; }
-#endif
-
 void acpi_scan_lock_acquire(void);
 void acpi_scan_lock_release(void);
 int acpi_scan_add_handler(struct acpi_scan_handler *handler);
@@ -478,7 +476,8 @@ static inline int acpi_pm_device_sleep_state(struct device *d, int *p, int m)
        if (p)
                *p = ACPI_STATE_D0;
 
-       return (m >= ACPI_STATE_D0 && m <= ACPI_STATE_D3) ? m : ACPI_STATE_D0;
+       return (m >= ACPI_STATE_D0 && m <= ACPI_STATE_D3_COLD) ?
+               m : ACPI_STATE_D0;
 }
 static inline void acpi_dev_pm_add_dependent(acpi_handle handle,
                                             struct device *depdev) {}
index b420939..1cedfcb 100644 (file)
@@ -113,14 +113,13 @@ void pci_acpi_crs_quirks(void);
                                   Dock Station
   -------------------------------------------------------------------------- */
 struct acpi_dock_ops {
+       acpi_notify_handler fixup;
        acpi_notify_handler handler;
        acpi_notify_handler uevent;
 };
 
-#if defined(CONFIG_ACPI_DOCK) || defined(CONFIG_ACPI_DOCK_MODULE)
+#ifdef CONFIG_ACPI_DOCK
 extern int is_dock_device(acpi_handle handle);
-extern int register_dock_notifier(struct notifier_block *nb);
-extern void unregister_dock_notifier(struct notifier_block *nb);
 extern int register_hotplug_dock_device(acpi_handle handle,
                                        const struct acpi_dock_ops *ops,
                                        void *context,
@@ -132,13 +131,6 @@ static inline int is_dock_device(acpi_handle handle)
 {
        return 0;
 }
-static inline int register_dock_notifier(struct notifier_block *nb)
-{
-       return -ENODEV;
-}
-static inline void unregister_dock_notifier(struct notifier_block *nb)
-{
-}
 static inline int register_hotplug_dock_device(acpi_handle handle,
                                               const struct acpi_dock_ops *ops,
                                               void *context,
@@ -150,6 +142,6 @@ static inline int register_hotplug_dock_device(acpi_handle handle,
 static inline void unregister_hotplug_dock_device(acpi_handle handle)
 {
 }
-#endif
+#endif /* CONFIG_ACPI_DOCK */
 
 #endif /*__ACPI_DRIVERS_H__*/
index 22d497e..85bfdbe 100644 (file)
@@ -46,7 +46,7 @@
 
 /* Current ACPICA subsystem version in YYYYMMDD format */
 
-#define ACPI_CA_VERSION                 0x20130517
+#define ACPI_CA_VERSION                 0x20130725
 
 #include <acpi/acconfig.h>
 #include <acpi/actypes.h>
@@ -147,6 +147,8 @@ acpi_status acpi_install_interface(acpi_string interface_name);
 
 acpi_status acpi_remove_interface(acpi_string interface_name);
 
+acpi_status acpi_update_interfaces(u8 action);
+
 u32
 acpi_check_address_range(acpi_adr_space_type space_id,
                         acpi_physical_address address,
@@ -210,8 +212,8 @@ acpi_status
 acpi_walk_namespace(acpi_object_type type,
                    acpi_handle start_object,
                    u32 max_depth,
-                   acpi_walk_callback pre_order_visit,
-                   acpi_walk_callback post_order_visit,
+                   acpi_walk_callback descending_callback,
+                   acpi_walk_callback ascending_callback,
                    void *context, void **return_value);
 
 acpi_status
index 22b03c9..b748aef 100644 (file)
@@ -668,13 +668,6 @@ typedef u32 acpi_event_status;
 #define ACPI_EVENT_FLAG_SET             (acpi_event_status) 0x04
 #define ACPI_EVENT_FLAG_HANDLE         (acpi_event_status) 0x08
 
-/*
- * General Purpose Events (GPE)
- */
-#define ACPI_GPE_INVALID                0xFF
-#define ACPI_GPE_MAX                    0xFF
-#define ACPI_NUM_GPE                    256
-
 /* Actions for acpi_set_gpe, acpi_gpe_wakeup, acpi_hw_low_set_gpe */
 
 #define ACPI_GPE_ENABLE                 0
@@ -1144,7 +1137,19 @@ struct acpi_memory_list {
 #endif
 };
 
-/* Definitions for _OSI support */
+/* Definitions of _OSI support */
+
+#define ACPI_VENDOR_STRINGS                 0x01
+#define ACPI_FEATURE_STRINGS                0x02
+#define ACPI_ENABLE_INTERFACES              0x00
+#define ACPI_DISABLE_INTERFACES             0x04
+
+#define ACPI_DISABLE_ALL_VENDOR_STRINGS     (ACPI_DISABLE_INTERFACES | ACPI_VENDOR_STRINGS)
+#define ACPI_DISABLE_ALL_FEATURE_STRINGS    (ACPI_DISABLE_INTERFACES | ACPI_FEATURE_STRINGS)
+#define ACPI_DISABLE_ALL_STRINGS            (ACPI_DISABLE_INTERFACES | ACPI_VENDOR_STRINGS | ACPI_FEATURE_STRINGS)
+#define ACPI_ENABLE_ALL_VENDOR_STRINGS      (ACPI_ENABLE_INTERFACES | ACPI_VENDOR_STRINGS)
+#define ACPI_ENABLE_ALL_FEATURE_STRINGS     (ACPI_ENABLE_INTERFACES | ACPI_FEATURE_STRINGS)
+#define ACPI_ENABLE_ALL_STRINGS             (ACPI_ENABLE_INTERFACES | ACPI_VENDOR_STRINGS | ACPI_FEATURE_STRINGS)
 
 #define ACPI_OSI_WIN_2000               0x01
 #define ACPI_OSI_WIN_XP                 0x02
index 353ba25..a5db4ae 100644 (file)
@@ -481,6 +481,13 @@ void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state,
 
 acpi_status acpi_os_prepare_sleep(u8 sleep_state,
                                  u32 pm1a_control, u32 pm1b_control);
+
+void acpi_os_set_prepare_extended_sleep(int (*func)(u8 sleep_state,
+                                       u32 val_a,  u32 val_b));
+
+acpi_status acpi_os_prepare_extended_sleep(u8 sleep_state,
+                                          u32 val_a, u32 val_b);
+
 #ifdef CONFIG_X86
 void arch_reserve_mem_area(acpi_physical_address addr, size_t size);
 #else
index 3dfed2b..801ff9e 100644 (file)
@@ -173,6 +173,8 @@ extern struct bus_type cpu_subsys;
 #ifdef CONFIG_HOTPLUG_CPU
 /* Stop CPUs going up and down. */
 
+extern void cpu_hotplug_begin(void);
+extern void cpu_hotplug_done(void);
 extern void get_online_cpus(void);
 extern void put_online_cpus(void);
 extern void cpu_hotplug_disable(void);
@@ -198,6 +200,8 @@ static inline void cpu_hotplug_driver_unlock(void)
 
 #else          /* CONFIG_HOTPLUG_CPU */
 
+static inline void cpu_hotplug_begin(void) {}
+static inline void cpu_hotplug_done(void) {}
 #define get_online_cpus()      do { } while (0)
 #define put_online_cpus()      do { } while (0)
 #define cpu_hotplug_disable()  do { } while (0)
index 0bc4b74..781addc 100644 (file)
@@ -13,8 +13,6 @@
 
 #include <linux/percpu.h>
 #include <linux/list.h>
-#include <linux/kobject.h>
-#include <linux/completion.h>
 #include <linux/hrtimer.h>
 
 #define CPUIDLE_STATE_MAX      10
@@ -61,6 +59,10 @@ struct cpuidle_state {
 
 #define CPUIDLE_DRIVER_FLAGS_MASK (0xFFFF0000)
 
+struct cpuidle_device_kobj;
+struct cpuidle_state_kobj;
+struct cpuidle_driver_kobj;
+
 struct cpuidle_device {
        unsigned int            registered:1;
        unsigned int            enabled:1;
@@ -71,9 +73,8 @@ struct cpuidle_device {
        struct cpuidle_state_usage      states_usage[CPUIDLE_STATE_MAX];
        struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX];
        struct cpuidle_driver_kobj *kobj_driver;
+       struct cpuidle_device_kobj *kobj_dev;
        struct list_head        device_list;
-       struct kobject          kobj;
-       struct completion       kobj_unregister;
 
 #ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED
        int                     safe_state_index;
index b90337c..4a12532 100644 (file)
@@ -336,6 +336,7 @@ extern int d_validate(struct dentry *, struct dentry *);
  * helper function for dentry_operations.d_dname() members
  */
 extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
+extern char *simple_dname(struct dentry *, char *, int);
 
 extern char *__d_path(const struct path *, const struct path *, char *, int);
 extern char *d_absolute_path(const struct path *, char *, int);
index b99cd23..79640e0 100644 (file)
@@ -5,45 +5,13 @@
 
 #include <linux/bitmap.h>
 #include <linux/if.h>
+#include <linux/ip.h>
 #include <linux/netdevice.h>
 #include <linux/rcupdate.h>
 #include <linux/timer.h>
 #include <linux/sysctl.h>
 #include <linux/rtnetlink.h>
 
-enum
-{
-       IPV4_DEVCONF_FORWARDING=1,
-       IPV4_DEVCONF_MC_FORWARDING,
-       IPV4_DEVCONF_PROXY_ARP,
-       IPV4_DEVCONF_ACCEPT_REDIRECTS,
-       IPV4_DEVCONF_SECURE_REDIRECTS,
-       IPV4_DEVCONF_SEND_REDIRECTS,
-       IPV4_DEVCONF_SHARED_MEDIA,
-       IPV4_DEVCONF_RP_FILTER,
-       IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE,
-       IPV4_DEVCONF_BOOTP_RELAY,
-       IPV4_DEVCONF_LOG_MARTIANS,
-       IPV4_DEVCONF_TAG,
-       IPV4_DEVCONF_ARPFILTER,
-       IPV4_DEVCONF_MEDIUM_ID,
-       IPV4_DEVCONF_NOXFRM,
-       IPV4_DEVCONF_NOPOLICY,
-       IPV4_DEVCONF_FORCE_IGMP_VERSION,
-       IPV4_DEVCONF_ARP_ANNOUNCE,
-       IPV4_DEVCONF_ARP_IGNORE,
-       IPV4_DEVCONF_PROMOTE_SECONDARIES,
-       IPV4_DEVCONF_ARP_ACCEPT,
-       IPV4_DEVCONF_ARP_NOTIFY,
-       IPV4_DEVCONF_ACCEPT_LOCAL,
-       IPV4_DEVCONF_SRC_VMARK,
-       IPV4_DEVCONF_PROXY_ARP_PVLAN,
-       IPV4_DEVCONF_ROUTE_LOCALNET,
-       __IPV4_DEVCONF_MAX
-};
-
-#define IPV4_DEVCONF_MAX (__IPV4_DEVCONF_MAX - 1)
-
 struct ipv4_devconf {
        void    *sysctl;
        int     data[IPV4_DEVCONF_MAX];
index 850e95b..b8b7dc7 100644 (file)
@@ -101,6 +101,7 @@ struct inet6_skb_parm {
 #define IP6SKB_FORWARDED       2
 #define IP6SKB_REROUTED                4
 #define IP6SKB_ROUTERALERT     8
+#define IP6SKB_FRAGMENTED      16
 };
 
 #define IP6CB(skb)     ((struct inet6_skb_parm*)((skb)->cb))
index fb425aa..faf4b7c 100644 (file)
@@ -332,6 +332,7 @@ struct mm_struct {
                                unsigned long pgoff, unsigned long flags);
 #endif
        unsigned long mmap_base;                /* base of mmap area */
+       unsigned long mmap_legacy_base;         /* base of mmap area in bottom-up allocations */
        unsigned long task_size;                /* size of task vm space */
        unsigned long highest_vm_end;           /* highest vma end address */
        pgd_t * pgd;
index 1704479..d006f0c 100644 (file)
@@ -47,24 +47,22 @@ void acpi_pci_remove_bus(struct pci_bus *bus);
 
 #ifdef CONFIG_ACPI_PCI_SLOT
 void acpi_pci_slot_init(void);
-void acpi_pci_slot_enumerate(struct pci_bus *bus, acpi_handle handle);
+void acpi_pci_slot_enumerate(struct pci_bus *bus);
 void acpi_pci_slot_remove(struct pci_bus *bus);
 #else
 static inline void acpi_pci_slot_init(void) { }
-static inline void acpi_pci_slot_enumerate(struct pci_bus *bus,
-                                          acpi_handle handle) { }
+static inline void acpi_pci_slot_enumerate(struct pci_bus *bus) { }
 static inline void acpi_pci_slot_remove(struct pci_bus *bus) { }
 #endif
 
 #ifdef CONFIG_HOTPLUG_PCI_ACPI
 void acpiphp_init(void);
-void acpiphp_enumerate_slots(struct pci_bus *bus, acpi_handle handle);
+void acpiphp_enumerate_slots(struct pci_bus *bus);
 void acpiphp_remove_slots(struct pci_bus *bus);
 void acpiphp_check_host_bridge(acpi_handle handle);
 #else
 static inline void acpiphp_init(void) { }
-static inline void acpiphp_enumerate_slots(struct pci_bus *bus,
-                                          acpi_handle handle) { }
+static inline void acpiphp_enumerate_slots(struct pci_bus *bus) { }
 static inline void acpiphp_remove_slots(struct pci_bus *bus) { }
 static inline void acpiphp_check_host_bridge(acpi_handle handle) { }
 #endif
index e9995eb..078066d 100644 (file)
@@ -314,7 +314,6 @@ struct nsproxy;
 struct user_namespace;
 
 #ifdef CONFIG_MMU
-extern unsigned long mmap_legacy_base(void);
 extern void arch_pick_mmap_layout(struct mm_struct *mm);
 extern unsigned long
 arch_get_unmapped_area(struct file *, unsigned long, unsigned long,
index f487a47..a67fc16 100644 (file)
@@ -811,6 +811,63 @@ do {                                                                       \
        __ret;                                                          \
 })
 
+#define __wait_event_interruptible_lock_irq_timeout(wq, condition,     \
+                                                   lock, ret)          \
+do {                                                                   \
+       DEFINE_WAIT(__wait);                                            \
+                                                                       \
+       for (;;) {                                                      \
+               prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE);      \
+               if (condition)                                          \
+                       break;                                          \
+               if (signal_pending(current)) {                          \
+                       ret = -ERESTARTSYS;                             \
+                       break;                                          \
+               }                                                       \
+               spin_unlock_irq(&lock);                                 \
+               ret = schedule_timeout(ret);                            \
+               spin_lock_irq(&lock);                                   \
+               if (!ret)                                               \
+                       break;                                          \
+       }                                                               \
+       finish_wait(&wq, &__wait);                                      \
+} while (0)
+
+/**
+ * wait_event_interruptible_lock_irq_timeout - sleep until a condition gets true or a timeout elapses.
+ *             The condition is checked under the lock. This is expected
+ *             to be called with the lock taken.
+ * @wq: the waitqueue to wait on
+ * @condition: a C expression for the event to wait for
+ * @lock: a locked spinlock_t, which will be released before schedule()
+ *       and reacquired afterwards.
+ * @timeout: timeout, in jiffies
+ *
+ * The process is put to sleep (TASK_INTERRUPTIBLE) until the
+ * @condition evaluates to true or signal is received. The @condition is
+ * checked each time the waitqueue @wq is woken up.
+ *
+ * wake_up() has to be called after changing any variable that could
+ * change the result of the wait condition.
+ *
+ * This is supposed to be called while holding the lock. The lock is
+ * dropped before going to sleep and is reacquired afterwards.
+ *
+ * The function returns 0 if the @timeout elapsed, -ERESTARTSYS if it
+ * was interrupted by a signal, and the remaining jiffies otherwise
+ * if the condition evaluated to true before the timeout elapsed.
+ */
+#define wait_event_interruptible_lock_irq_timeout(wq, condition, lock, \
+                                                 timeout)              \
+({                                                                     \
+       int __ret = timeout;                                            \
+                                                                       \
+       if (!(condition))                                               \
+               __wait_event_interruptible_lock_irq_timeout(            \
+                                       wq, condition, lock, __ret);    \
+       __ret;                                                          \
+})
+
 
 /*
  * These are the old interfaces to sleep waiting for an event.
index 260f83f..f667248 100644 (file)
@@ -135,6 +135,8 @@ extern void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu,
 extern void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk,
                               __be32 mtu);
 extern void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark);
+extern void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif,
+                                  u32 mark);
 extern void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk);
 
 struct netlink_callback;
index 8e42410..cda100d 100644 (file)
@@ -66,6 +66,43 @@ TRACE_EVENT(machine_suspend,
        TP_printk("state=%lu", (unsigned long)__entry->state)
 );
 
+TRACE_EVENT(device_pm_report_time,
+
+       TP_PROTO(struct device *dev, const char *pm_ops, s64 ops_time,
+                char *pm_event_str, int error),
+
+       TP_ARGS(dev, pm_ops, ops_time, pm_event_str, error),
+
+       TP_STRUCT__entry(
+               __string(device, dev_name(dev))
+               __string(driver, dev_driver_string(dev))
+               __string(parent, dev->parent ? dev_name(dev->parent) : "none")
+               __string(pm_ops, pm_ops ? pm_ops : "none ")
+               __string(pm_event_str, pm_event_str)
+               __field(s64, ops_time)
+               __field(int, error)
+       ),
+
+       TP_fast_assign(
+               const char *tmp = dev->parent ? dev_name(dev->parent) : "none";
+               const char *tmp_i = pm_ops ? pm_ops : "none ";
+
+               __assign_str(device, dev_name(dev));
+               __assign_str(driver, dev_driver_string(dev));
+               __assign_str(parent, tmp);
+               __assign_str(pm_ops, tmp_i);
+               __assign_str(pm_event_str, pm_event_str);
+               __entry->ops_time = ops_time;
+               __entry->error = error;
+       ),
+
+       /* ops_str has an extra space at the end */
+       TP_printk("%s %s parent=%s state=%s ops=%snsecs=%lld err=%d",
+               __get_str(driver), __get_str(device), __get_str(parent),
+               __get_str(pm_event_str), __get_str(pm_ops),
+               __entry->ops_time, __entry->error)
+);
+
 DECLARE_EVENT_CLASS(wakeup_source,
 
        TP_PROTO(const char *name, unsigned int state),
index 6cf06bf..2fee45b 100644 (file)
@@ -133,4 +133,38 @@ struct ip_beet_phdr {
        __u8 reserved;
 };
 
+/* index values for the variables in ipv4_devconf */
+enum
+{
+       IPV4_DEVCONF_FORWARDING=1,
+       IPV4_DEVCONF_MC_FORWARDING,
+       IPV4_DEVCONF_PROXY_ARP,
+       IPV4_DEVCONF_ACCEPT_REDIRECTS,
+       IPV4_DEVCONF_SECURE_REDIRECTS,
+       IPV4_DEVCONF_SEND_REDIRECTS,
+       IPV4_DEVCONF_SHARED_MEDIA,
+       IPV4_DEVCONF_RP_FILTER,
+       IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE,
+       IPV4_DEVCONF_BOOTP_RELAY,
+       IPV4_DEVCONF_LOG_MARTIANS,
+       IPV4_DEVCONF_TAG,
+       IPV4_DEVCONF_ARPFILTER,
+       IPV4_DEVCONF_MEDIUM_ID,
+       IPV4_DEVCONF_NOXFRM,
+       IPV4_DEVCONF_NOPOLICY,
+       IPV4_DEVCONF_FORCE_IGMP_VERSION,
+       IPV4_DEVCONF_ARP_ANNOUNCE,
+       IPV4_DEVCONF_ARP_IGNORE,
+       IPV4_DEVCONF_PROMOTE_SECONDARIES,
+       IPV4_DEVCONF_ARP_ACCEPT,
+       IPV4_DEVCONF_ARP_NOTIFY,
+       IPV4_DEVCONF_ACCEPT_LOCAL,
+       IPV4_DEVCONF_SRC_VMARK,
+       IPV4_DEVCONF_PROXY_ARP_PVLAN,
+       IPV4_DEVCONF_ROUTE_LOCALNET,
+       __IPV4_DEVCONF_MAX
+};
+
+#define IPV4_DEVCONF_MAX (__IPV4_DEVCONF_MAX - 1)
+
 #endif /* _UAPI_LINUX_IP_H */
index 46aa3d1..4ddd7dc 100644 (file)
@@ -75,8 +75,10 @@ static inline int xen_acpi_get_pxm(acpi_handle h)
        return -ENXIO;
 }
 
-int xen_acpi_notify_hypervisor_state(u8 sleep_state,
+int xen_acpi_notify_hypervisor_sleep(u8 sleep_state,
                                     u32 pm1a_cnt, u32 pm1b_cnd);
+int xen_acpi_notify_hypervisor_extended_sleep(u8 sleep_state,
+                                    u32 val_a, u32 val_b);
 
 static inline int xen_acpi_suspend_lowlevel(void)
 {
@@ -93,7 +95,9 @@ static inline void xen_acpi_sleep_register(void)
 {
        if (xen_initial_domain()) {
                acpi_os_set_prepare_sleep(
-                       &xen_acpi_notify_hypervisor_state);
+                       &xen_acpi_notify_hypervisor_sleep);
+               acpi_os_set_prepare_extended_sleep(
+                       &xen_acpi_notify_hypervisor_extended_sleep);
 
                acpi_suspend_lowlevel = xen_acpi_suspend_lowlevel;
        }
index c57d5f6..f1331e3 100644 (file)
@@ -152,10 +152,11 @@ DEFINE_GUEST_HANDLE_STRUCT(xenpf_firmware_info_t);
 #define XENPF_enter_acpi_sleep    51
 struct xenpf_enter_acpi_sleep {
        /* IN variables */
-       uint16_t pm1a_cnt_val;      /* PM1a control value. */
-       uint16_t pm1b_cnt_val;      /* PM1b control value. */
+       uint16_t val_a;             /* PM1a control / sleep type A. */
+       uint16_t val_b;             /* PM1b control / sleep type B. */
        uint32_t sleep_state;       /* Which state to enter (Sn). */
-       uint32_t flags;             /* Must be zero. */
+#define XENPF_ACPI_SLEEP_EXTENDED 0x00000001
+       uint32_t flags;             /* XENPF_ACPI_SLEEP_*. */
 };
 DEFINE_GUEST_HANDLE_STRUCT(xenpf_enter_acpi_sleep_t);
 
index 247084b..fed81b5 100644 (file)
@@ -955,7 +955,7 @@ config MEMCG_SWAP_ENABLED
          Memory Resource Controller Swap Extension comes with its price in
          a bigger memory consumption. General purpose distribution kernels
          which want to enable the feature but keep it disabled by default
-         and let the user enable it by swapaccount boot command line
+         and let the user enable it by swapaccount=1 boot command line
          parameter should have this option unselected.
          For those who want to have the feature enabled by default should
          select this option (if, for some reason, they need to disable it
index b2b227b..d7f07a2 100644 (file)
@@ -113,7 +113,7 @@ EXPORT_SYMBOL_GPL(put_online_cpus);
  * get_online_cpus() not an api which is called all that often.
  *
  */
-static void cpu_hotplug_begin(void)
+void cpu_hotplug_begin(void)
 {
        cpu_hotplug.active_writer = current;
 
@@ -127,7 +127,7 @@ static void cpu_hotplug_begin(void)
        }
 }
 
-static void cpu_hotplug_done(void)
+void cpu_hotplug_done(void)
 {
        cpu_hotplug.active_writer = NULL;
        mutex_unlock(&cpu_hotplug.lock);
@@ -154,10 +154,7 @@ void cpu_hotplug_enable(void)
        cpu_maps_update_done();
 }
 
-#else /* #if CONFIG_HOTPLUG_CPU */
-static void cpu_hotplug_begin(void) {}
-static void cpu_hotplug_done(void) {}
-#endif /* #else #if CONFIG_HOTPLUG_CPU */
+#endif /* CONFIG_HOTPLUG_CPU */
 
 /* Need to know about CPUs going up/down? */
 int __ref register_cpu_notifier(struct notifier_block *nb)
index 010a008..ea1966d 100644 (file)
@@ -475,13 +475,17 @@ static int validate_change(const struct cpuset *cur, const struct cpuset *trial)
 
        /*
         * Cpusets with tasks - existing or newly being attached - can't
-        * have empty cpus_allowed or mems_allowed.
+        * be changed to have empty cpus_allowed or mems_allowed.
         */
        ret = -ENOSPC;
-       if ((cgroup_task_count(cur->css.cgroup) || cur->attach_in_progress) &&
-           (cpumask_empty(trial->cpus_allowed) &&
-            nodes_empty(trial->mems_allowed)))
-               goto out;
+       if ((cgroup_task_count(cur->css.cgroup) || cur->attach_in_progress)) {
+               if (!cpumask_empty(cur->cpus_allowed) &&
+                   cpumask_empty(trial->cpus_allowed))
+                       goto out;
+               if (!nodes_empty(cur->mems_allowed) &&
+                   nodes_empty(trial->mems_allowed))
+                       goto out;
+       }
 
        ret = 0;
 out:
index ece0422..62ee437 100644 (file)
@@ -210,6 +210,7 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
                goto Platform_wake;
        }
 
+       ftrace_stop();
        error = disable_nonboot_cpus();
        if (error || suspend_test(TEST_CPUS))
                goto Enable_cpus;
@@ -232,6 +233,7 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
 
  Enable_cpus:
        enable_nonboot_cpus();
+       ftrace_start();
 
  Platform_wake:
        if (need_suspend_ops(state) && suspend_ops->wake)
@@ -265,7 +267,6 @@ int suspend_devices_and_enter(suspend_state_t state)
                        goto Close;
        }
        suspend_console();
-       ftrace_stop();
        suspend_test_start();
        error = dpm_suspend_start(PMSG_SUSPEND);
        if (error) {
@@ -285,7 +286,6 @@ int suspend_devices_and_enter(suspend_state_t state)
        suspend_test_start();
        dpm_resume_end(PMSG_RESUME);
        suspend_test_finish("resume devices");
-       ftrace_start();
        resume_console();
  Close:
        if (need_suspend_ops(state) && suspend_ops->end)
index a326f27..0b479a6 100644 (file)
@@ -121,7 +121,7 @@ void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)
        BUG_ON(bits > 32);
        WARN_ON(!irqs_disabled());
        read_sched_clock = read;
-       sched_clock_mask = (1 << bits) - 1;
+       sched_clock_mask = (1ULL << bits) - 1;
        cd.rate = rate;
 
        /* calculate the mult/shift to convert counter ticks to ns. */
index e77edc9..e8a1516 100644 (file)
@@ -182,7 +182,8 @@ static bool can_stop_full_tick(void)
                 * Don't allow the user to think they can get
                 * full NO_HZ with this machine.
                 */
-               WARN_ONCE(1, "NO_HZ FULL will not work with unstable sched clock");
+               WARN_ONCE(have_nohz_full_mask,
+                         "NO_HZ FULL will not work with unstable sched clock");
                return false;
        }
 #endif
@@ -343,8 +344,6 @@ static int tick_nohz_init_all(void)
 
 void __init tick_nohz_init(void)
 {
-       int cpu;
-
        if (!have_nohz_full_mask) {
                if (tick_nohz_init_all() < 0)
                        return;
index dec68bd..d550920 100644 (file)
@@ -363,8 +363,7 @@ EXPORT_SYMBOL(out_of_line_wait_on_atomic_t);
 
 /**
  * wake_up_atomic_t - Wake up a waiter on a atomic_t
- * @word: The word being waited on, a kernel virtual address
- * @bit: The bit of the word being waited on
+ * @p: The atomic_t being waited on, a kernel virtual address
  *
  * Wake up anyone waiting for the atomic_t to go to zero.
  *
index 7aa7ce2..3eb3e47 100644 (file)
@@ -49,22 +49,23 @@ enum cpio_fields {
 
 /**
  * cpio_data find_cpio_data - Search for files in an uncompressed cpio
- * @path:   The directory to search for, including a slash at the end
- * @data:   Pointer to the the cpio archive or a header inside
- * @len:    Remaining length of the cpio based on data pointer
- * @offset: When a matching file is found, this is the offset to the
- *          beginning of the cpio. It can be used to iterate through
- *          the cpio to find all files inside of a directory path
+ * @path:       The directory to search for, including a slash at the end
+ * @data:       Pointer to the the cpio archive or a header inside
+ * @len:        Remaining length of the cpio based on data pointer
+ * @nextoff:    When a matching file is found, this is the offset from the
+ *              beginning of the cpio to the beginning of the next file, not the
+ *              matching file itself. It can be used to iterate through the cpio
+ *              to find all files inside of a directory path.
  *
- * @return: struct cpio_data containing the address, length and
- *          filename (with the directory path cut off) of the found file.
- *          If you search for a filename and not for files in a directory,
- *          pass the absolute path of the filename in the cpio and make sure
- *          the match returned an empty filename string.
+ * @return:     struct cpio_data containing the address, length and
+ *              filename (with the directory path cut off) of the found file.
+ *              If you search for a filename and not for files in a directory,
+ *              pass the absolute path of the filename in the cpio and make sure
+ *              the match returned an empty filename string.
  */
 
 struct cpio_data find_cpio_data(const char *path, void *data,
-                                         size_t len,  long *offset)
+                               size_t len,  long *nextoff)
 {
        const size_t cpio_header_len = 8*C_NFIELDS - 2;
        struct cpio_data cd = { NULL, 0, "" };
@@ -124,7 +125,7 @@ struct cpio_data find_cpio_data(const char *path, void *data,
                if ((ch[C_MODE] & 0170000) == 0100000 &&
                    ch[C_NAMESIZE] >= mypathsize &&
                    !memcmp(p, path, mypathsize)) {
-                       *offset = (long)nptr - (long)data;
+                       *nextoff = (long)nptr - (long)data;
                        if (ch[C_NAMESIZE] - mypathsize >= MAX_CPIO_FILE_NAME) {
                                pr_warn(
                                "File %s exceeding MAX_CPIO_FILE_NAME [%d]\n",
index fd94058..28321d8 100644 (file)
@@ -437,7 +437,7 @@ int lz4_compress(const unsigned char *src, size_t src_len,
 exit:
        return ret;
 }
-EXPORT_SYMBOL_GPL(lz4_compress);
+EXPORT_SYMBOL(lz4_compress);
 
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("Dual BSD/GPL");
 MODULE_DESCRIPTION("LZ4 compressor");
index d3414ea..411be80 100644 (file)
@@ -299,7 +299,7 @@ exit_0:
        return ret;
 }
 #ifndef STATIC
-EXPORT_SYMBOL_GPL(lz4_decompress);
+EXPORT_SYMBOL(lz4_decompress);
 #endif
 
 int lz4_decompress_unknownoutputsize(const char *src, size_t src_len,
@@ -319,8 +319,8 @@ exit_0:
        return ret;
 }
 #ifndef STATIC
-EXPORT_SYMBOL_GPL(lz4_decompress_unknownoutputsize);
+EXPORT_SYMBOL(lz4_decompress_unknownoutputsize);
 
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("Dual BSD/GPL");
 MODULE_DESCRIPTION("LZ4 Decompressor");
 #endif
index eb1a74f..f344f76 100644 (file)
@@ -533,7 +533,7 @@ int lz4hc_compress(const unsigned char *src, size_t src_len,
 exit:
        return ret;
 }
-EXPORT_SYMBOL_GPL(lz4hc_compress);
+EXPORT_SYMBOL(lz4hc_compress);
 
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("Dual BSD/GPL");
 MODULE_DESCRIPTION("LZ4HC compressor");
index c5792a5..0878ff7 100644 (file)
@@ -6969,7 +6969,6 @@ struct cgroup_subsys mem_cgroup_subsys = {
 #ifdef CONFIG_MEMCG_SWAP
 static int __init enable_swap_account(char *s)
 {
-       /* consider enabled if no parameter or 1 is given */
        if (!strcmp(s, "1"))
                really_do_swap_account = 1;
        else if (!strcmp(s, "0"))
index 8335dbd..e43dc55 100644 (file)
@@ -2909,14 +2909,8 @@ EXPORT_SYMBOL_GPL(shmem_truncate_range);
 
 /* common code */
 
-static char *shmem_dname(struct dentry *dentry, char *buffer, int buflen)
-{
-       return dynamic_dname(dentry, buffer, buflen, "/%s (deleted)",
-                               dentry->d_name.name);
-}
-
 static struct dentry_operations anon_ops = {
-       .d_dname = shmem_dname
+       .d_dname = simple_dname
 };
 
 /**
index 688a041..857e1b8 100644 (file)
@@ -432,12 +432,16 @@ find_router:
 
        switch (packet_type) {
        case BATADV_UNICAST:
-               batadv_unicast_prepare_skb(skb, orig_node);
+               if (!batadv_unicast_prepare_skb(skb, orig_node))
+                       goto out;
+
                header_len = sizeof(struct batadv_unicast_packet);
                break;
        case BATADV_UNICAST_4ADDR:
-               batadv_unicast_4addr_prepare_skb(bat_priv, skb, orig_node,
-                                                packet_subtype);
+               if (!batadv_unicast_4addr_prepare_skb(bat_priv, skb, orig_node,
+                                                     packet_subtype))
+                       goto out;
+
                header_len = sizeof(struct batadv_unicast_4addr_packet);
                break;
        default:
index 60aca91..ffd5874 100644 (file)
@@ -161,7 +161,7 @@ void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr)
        if (!pv)
                return;
 
-       for_each_set_bit_from(vid, pv->vlan_bitmap, BR_VLAN_BITMAP_LEN) {
+       for_each_set_bit_from(vid, pv->vlan_bitmap, VLAN_N_VID) {
                f = __br_fdb_get(br, br->dev->dev_addr, vid);
                if (f && f->is_local && !f->dst)
                        fdb_delete(br, f);
@@ -730,7 +730,7 @@ int br_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
                /* VID was specified, so use it. */
                err = __br_fdb_add(ndm, p, addr, nlh_flags, vid);
        } else {
-               if (!pv || bitmap_empty(pv->vlan_bitmap, BR_VLAN_BITMAP_LEN)) {
+               if (!pv || bitmap_empty(pv->vlan_bitmap, VLAN_N_VID)) {
                        err = __br_fdb_add(ndm, p, addr, nlh_flags, 0);
                        goto out;
                }
@@ -739,7 +739,7 @@ int br_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
                 * specify a VLAN.  To be nice, add/update entry for every
                 * vlan on this port.
                 */
-               for_each_set_bit(vid, pv->vlan_bitmap, BR_VLAN_BITMAP_LEN) {
+               for_each_set_bit(vid, pv->vlan_bitmap, VLAN_N_VID) {
                        err = __br_fdb_add(ndm, p, addr, nlh_flags, vid);
                        if (err)
                                goto out;
@@ -817,7 +817,7 @@ int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
 
                err = __br_fdb_delete(p, addr, vid);
        } else {
-               if (!pv || bitmap_empty(pv->vlan_bitmap, BR_VLAN_BITMAP_LEN)) {
+               if (!pv || bitmap_empty(pv->vlan_bitmap, VLAN_N_VID)) {
                        err = __br_fdb_delete(p, addr, 0);
                        goto out;
                }
@@ -827,7 +827,7 @@ int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
                 * vlan on this port.
                 */
                err = -ENOENT;
-               for_each_set_bit(vid, pv->vlan_bitmap, BR_VLAN_BITMAP_LEN) {
+               for_each_set_bit(vid, pv->vlan_bitmap, VLAN_N_VID) {
                        err &= __br_fdb_delete(p, addr, vid);
                }
        }
index 1fc30ab..b9259ef 100644 (file)
@@ -132,7 +132,7 @@ static int br_fill_ifinfo(struct sk_buff *skb,
                else
                        pv = br_get_vlan_info(br);
 
-               if (!pv || bitmap_empty(pv->vlan_bitmap, BR_VLAN_BITMAP_LEN))
+               if (!pv || bitmap_empty(pv->vlan_bitmap, VLAN_N_VID))
                        goto done;
 
                af = nla_nest_start(skb, IFLA_AF_SPEC);
@@ -140,7 +140,7 @@ static int br_fill_ifinfo(struct sk_buff *skb,
                        goto nla_put_failure;
 
                pvid = br_get_pvid(pv);
-               for_each_set_bit(vid, pv->vlan_bitmap, BR_VLAN_BITMAP_LEN) {
+               for_each_set_bit(vid, pv->vlan_bitmap, VLAN_N_VID) {
                        vinfo.vid = vid;
                        vinfo.flags = 0;
                        if (vid == pvid)
index bd58b45..9a9ffe7 100644 (file)
@@ -108,7 +108,7 @@ static int __vlan_del(struct net_port_vlans *v, u16 vid)
 
        clear_bit(vid, v->vlan_bitmap);
        v->num_vlans--;
-       if (bitmap_empty(v->vlan_bitmap, BR_VLAN_BITMAP_LEN)) {
+       if (bitmap_empty(v->vlan_bitmap, VLAN_N_VID)) {
                if (v->port_idx)
                        rcu_assign_pointer(v->parent.port->vlan_info, NULL);
                else
@@ -122,7 +122,7 @@ static void __vlan_flush(struct net_port_vlans *v)
 {
        smp_wmb();
        v->pvid = 0;
-       bitmap_zero(v->vlan_bitmap, BR_VLAN_BITMAP_LEN);
+       bitmap_zero(v->vlan_bitmap, VLAN_N_VID);
        if (v->port_idx)
                rcu_assign_pointer(v->parent.port->vlan_info, NULL);
        else
index 5423223..b2f6c74 100644 (file)
@@ -1120,6 +1120,13 @@ new_segment:
                                if (!skb)
                                        goto wait_for_memory;
 
+                               /*
+                                * All packets are restored as if they have
+                                * already been sent.
+                                */
+                               if (tp->repair)
+                                       TCP_SKB_CB(skb)->when = tcp_time_stamp;
+
                                /*
                                 * Check whether we can use HW checksum.
                                 */
index da4241c..498ea99 100644 (file)
@@ -1126,12 +1126,10 @@ retry:
        if (ifp->flags & IFA_F_OPTIMISTIC)
                addr_flags |= IFA_F_OPTIMISTIC;
 
-       ift = !max_addresses ||
-             ipv6_count_addresses(idev) < max_addresses ?
-               ipv6_add_addr(idev, &addr, NULL, tmp_plen,
-                             ipv6_addr_scope(&addr), addr_flags,
-                             tmp_valid_lft, tmp_prefered_lft) : NULL;
-       if (IS_ERR_OR_NULL(ift)) {
+       ift = ipv6_add_addr(idev, &addr, NULL, tmp_plen,
+                           ipv6_addr_scope(&addr), addr_flags,
+                           tmp_valid_lft, tmp_prefered_lft);
+       if (IS_ERR(ift)) {
                in6_ifa_put(ifp);
                in6_dev_put(idev);
                pr_info("%s: retry temporary address regeneration\n", __func__);
index 79aa965..04d31c2 100644 (file)
@@ -1369,8 +1369,10 @@ static void ndisc_redirect_rcv(struct sk_buff *skb)
        if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts))
                return;
 
-       if (!ndopts.nd_opts_rh)
+       if (!ndopts.nd_opts_rh) {
+               ip6_redirect_no_header(skb, dev_net(skb->dev), 0, 0);
                return;
+       }
 
        hdr = (u8 *)ndopts.nd_opts_rh;
        hdr += 8;
index 790d9f4..1aeb473 100644 (file)
@@ -490,6 +490,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev,
        ipv6_hdr(head)->payload_len = htons(payload_len);
        ipv6_change_dsfield(ipv6_hdr(head), 0xff, ecn);
        IP6CB(head)->nhoff = nhoff;
+       IP6CB(head)->flags |= IP6SKB_FRAGMENTED;
 
        /* Yes, and fold redundant checksum back. 8) */
        if (head->ip_summed == CHECKSUM_COMPLETE)
@@ -524,6 +525,9 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
        struct net *net = dev_net(skb_dst(skb)->dev);
        int evicted;
 
+       if (IP6CB(skb)->flags & IP6SKB_FRAGMENTED)
+               goto fail_hdr;
+
        IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_REASMREQDS);
 
        /* Jumbo payload inhibits frag. header */
@@ -544,6 +548,7 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
                                 ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_REASMOKS);
 
                IP6CB(skb)->nhoff = (u8 *)fhdr - skb_network_header(skb);
+               IP6CB(skb)->flags |= IP6SKB_FRAGMENTED;
                return 1;
        }
 
index b70f897..8d9a93e 100644 (file)
@@ -1178,6 +1178,27 @@ void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark)
 }
 EXPORT_SYMBOL_GPL(ip6_redirect);
 
+void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif,
+                           u32 mark)
+{
+       const struct ipv6hdr *iph = ipv6_hdr(skb);
+       const struct rd_msg *msg = (struct rd_msg *)icmp6_hdr(skb);
+       struct dst_entry *dst;
+       struct flowi6 fl6;
+
+       memset(&fl6, 0, sizeof(fl6));
+       fl6.flowi6_oif = oif;
+       fl6.flowi6_mark = mark;
+       fl6.flowi6_flags = 0;
+       fl6.daddr = msg->dest;
+       fl6.saddr = iph->daddr;
+
+       dst = ip6_route_output(net, NULL, &fl6);
+       if (!dst->error)
+               rt6_do_redirect(dst, NULL, skb);
+       dst_release(dst);
+}
+
 void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk)
 {
        ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if, sk->sk_mark);
index f85f8a2..512718a 100644 (file)
@@ -789,10 +789,6 @@ static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb)
        struct net *net = sock_net(skb->sk);
        int chains_to_skip = cb->args[0];
        int fams_to_skip = cb->args[1];
-       bool need_locking = chains_to_skip || fams_to_skip;
-
-       if (need_locking)
-               genl_lock();
 
        for (i = chains_to_skip; i < GENL_FAM_TAB_SIZE; i++) {
                n = 0;
@@ -814,9 +810,6 @@ errout:
        cb->args[0] = i;
        cb->args[1] = n;
 
-       if (need_locking)
-               genl_unlock();
-
        return skb->len;
 }
 
index 4b66c75..75c8bbf 100644 (file)
@@ -3259,9 +3259,11 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
 
                if (po->tp_version == TPACKET_V3) {
                        lv = sizeof(struct tpacket_stats_v3);
+                       st.stats3.tp_packets += st.stats3.tp_drops;
                        data = &st.stats3;
                } else {
                        lv = sizeof(struct tpacket_stats);
+                       st.stats1.tp_packets += st.stats1.tp_drops;
                        data = &st.stats1;
                }
 
index 3fcba69..5f6e982 100644 (file)
@@ -2622,8 +2622,8 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
 
        hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
                             NL80211_CMD_NEW_KEY);
-       if (IS_ERR(hdr))
-               return PTR_ERR(hdr);
+       if (!hdr)
+               return -ENOBUFS;
 
        cookie.msg = msg;
        cookie.idx = key_idx;
@@ -6507,6 +6507,9 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
                                           NL80211_CMD_TESTMODE);
                struct nlattr *tmdata;
 
+               if (!hdr)
+                       break;
+
                if (nla_put_u32(skb, NL80211_ATTR_WIPHY, phy_idx)) {
                        genlmsg_cancel(skb, hdr);
                        break;
@@ -6951,9 +6954,8 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
 
        hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
                             NL80211_CMD_REMAIN_ON_CHANNEL);
-
-       if (IS_ERR(hdr)) {
-               err = PTR_ERR(hdr);
+       if (!hdr) {
+               err = -ENOBUFS;
                goto free_msg;
        }
 
@@ -7251,9 +7253,8 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
 
                hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
                                     NL80211_CMD_FRAME);
-
-               if (IS_ERR(hdr)) {
-                       err = PTR_ERR(hdr);
+               if (!hdr) {
+                       err = -ENOBUFS;
                        goto free_msg;
                }
        }
@@ -8132,9 +8133,8 @@ static int nl80211_probe_client(struct sk_buff *skb,
 
        hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
                             NL80211_CMD_PROBE_CLIENT);
-
-       if (IS_ERR(hdr)) {
-               err = PTR_ERR(hdr);
+       if (!hdr) {
+               err = -ENOBUFS;
                goto free_msg;
        }
 
index 81c8a10..20e86a9 100644 (file)
@@ -976,21 +976,19 @@ int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
                        struct net_device *dev, u16 reason, bool wextev)
 {
        struct wireless_dev *wdev = dev->ieee80211_ptr;
-       int err;
+       int err = 0;
 
        ASSERT_WDEV_LOCK(wdev);
 
        kfree(wdev->connect_keys);
        wdev->connect_keys = NULL;
 
-       if (wdev->conn) {
+       if (wdev->conn)
                err = cfg80211_sme_disconnect(wdev, reason);
-       } else if (!rdev->ops->disconnect) {
+       else if (!rdev->ops->disconnect)
                cfg80211_mlme_down(rdev, dev);
-               err = 0;
-       } else {
+       else if (wdev->current_bss)
                err = rdev_disconnect(rdev, dev, reason);
-       }
 
        return err;
 }