]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
Merge tag 'mac80211-next-for-davem-2016-02-26' into next2
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Sat, 27 Feb 2016 19:59:03 +0000 (21:59 +0200)
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Sat, 27 Feb 2016 19:59:03 +0000 (21:59 +0200)
Here's another round of updates for -next:
 * big A-MSDU RX performance improvement (avoid linearize of paged RX)
 * rfkill changes: cleanups, documentation, platform properties
 * basic PBSS support in cfg80211
 * MU-MIMO action frame processing support
 * BlockAck reordering & duplicate detection offload support
 * various cleanups & little fixes

397 files changed:
Documentation/ABI/obsolete/sysfs-class-rfkill [deleted file]
Documentation/ABI/removed/sysfs-class-rfkill [new file with mode: 0644]
Documentation/ABI/stable/sysfs-class-rfkill
Documentation/cgroup-v1/00-INDEX [new file with mode: 0644]
Documentation/cgroup-v1/blkio-controller.txt [new file with mode: 0644]
Documentation/cgroup-v1/cgroups.txt [new file with mode: 0644]
Documentation/cgroup-v1/cpuacct.txt [new file with mode: 0644]
Documentation/cgroup-v1/cpusets.txt [new file with mode: 0644]
Documentation/cgroup-v1/devices.txt [new file with mode: 0644]
Documentation/cgroup-v1/freezer-subsystem.txt [new file with mode: 0644]
Documentation/cgroup-v1/hugetlb.txt [new file with mode: 0644]
Documentation/cgroup-v1/memcg_test.txt [new file with mode: 0644]
Documentation/cgroup-v1/memory.txt [new file with mode: 0644]
Documentation/cgroup-v1/net_cls.txt [new file with mode: 0644]
Documentation/cgroup-v1/net_prio.txt [new file with mode: 0644]
Documentation/cgroup-v1/pids.txt [new file with mode: 0644]
Documentation/cgroup-v2.txt [new file with mode: 0644]
Documentation/cgroups/00-INDEX [deleted file]
Documentation/cgroups/blkio-controller.txt [deleted file]
Documentation/cgroups/cgroups.txt [deleted file]
Documentation/cgroups/cpuacct.txt [deleted file]
Documentation/cgroups/cpusets.txt [deleted file]
Documentation/cgroups/devices.txt [deleted file]
Documentation/cgroups/freezer-subsystem.txt [deleted file]
Documentation/cgroups/hugetlb.txt [deleted file]
Documentation/cgroups/memcg_test.txt [deleted file]
Documentation/cgroups/memory.txt [deleted file]
Documentation/cgroups/net_cls.txt [deleted file]
Documentation/cgroups/net_prio.txt [deleted file]
Documentation/cgroups/pids.txt [deleted file]
Documentation/cgroups/unified-hierarchy.txt [deleted file]
Documentation/cpu-freq/intel-pstate.txt
Documentation/cpu-freq/pcc-cpufreq.txt
Documentation/devicetree/bindings/arm/cpus.txt
Documentation/devicetree/bindings/cpufreq/cpufreq-st.txt [new file with mode: 0644]
Documentation/devicetree/bindings/opp/opp.txt
Documentation/networking/mac80211-injection.txt
Documentation/power/pci.txt
Documentation/power/runtime_pm.txt
Documentation/rfkill.txt
MAINTAINERS
arch/arm/boot/dts/exynos4412.dtsi
arch/arm/mach-tegra/board-paz00.c
arch/ia64/kernel/ftrace.c
arch/metag/kernel/ftrace.c
arch/sh/kernel/ftrace.c
arch/x86/Kconfig
arch/x86/include/asm/iosf_mbi.h
arch/x86/kernel/ftrace.c
arch/x86/platform/atom/punit_atom_debug.c
arch/x86/platform/intel-quark/imr.c
drivers/acpi/Kconfig
drivers/acpi/Makefile
drivers/acpi/acpi_apd.c
drivers/acpi/acpi_dbg.c [new file with mode: 0644]
drivers/acpi/acpi_lpss.c
drivers/acpi/acpi_pnp.c
drivers/acpi/acpi_video.c
drivers/acpi/acpica/Makefile
drivers/acpi/acpica/acapps.h
drivers/acpi/acpica/acdebug.h
drivers/acpi/acpica/acevents.h
drivers/acpi/acpica/acglobal.h
drivers/acpi/acpica/aclocal.h
drivers/acpi/acpica/acmacros.h
drivers/acpi/acpica/acnamesp.h
drivers/acpi/acpica/acobject.h
drivers/acpi/acpica/acopcode.h
drivers/acpi/acpica/acparser.h
drivers/acpi/acpica/acutils.h
drivers/acpi/acpica/amlcode.h
drivers/acpi/acpica/dbcmds.c
drivers/acpi/acpica/dbdisply.c
drivers/acpi/acpica/dbfileio.c
drivers/acpi/acpica/dbinput.c
drivers/acpi/acpica/dbnames.c
drivers/acpi/acpica/dbstats.c
drivers/acpi/acpica/dbtest.c
drivers/acpi/acpica/dbutils.c
drivers/acpi/acpica/dbxface.c
drivers/acpi/acpica/dsargs.c
drivers/acpi/acpica/dscontrol.c
drivers/acpi/acpica/dsdebug.c
drivers/acpi/acpica/dsfield.c
drivers/acpi/acpica/dsinit.c
drivers/acpi/acpica/dsmethod.c
drivers/acpi/acpica/dsmthdat.c
drivers/acpi/acpica/dsobject.c
drivers/acpi/acpica/dsopcode.c
drivers/acpi/acpica/dsutils.c
drivers/acpi/acpica/dswexec.c
drivers/acpi/acpica/dswload.c
drivers/acpi/acpica/dswload2.c
drivers/acpi/acpica/dswscope.c
drivers/acpi/acpica/evgpe.c
drivers/acpi/acpica/evgpeblk.c
drivers/acpi/acpica/evgpeutil.c
drivers/acpi/acpica/evhandler.c
drivers/acpi/acpica/evmisc.c
drivers/acpi/acpica/evregion.c
drivers/acpi/acpica/evrgnini.c
drivers/acpi/acpica/evxface.c
drivers/acpi/acpica/evxfregn.c
drivers/acpi/acpica/exconfig.c
drivers/acpi/acpica/exconvrt.c
drivers/acpi/acpica/excreate.c
drivers/acpi/acpica/exdebug.c
drivers/acpi/acpica/exdump.c
drivers/acpi/acpica/exfield.c
drivers/acpi/acpica/exfldio.c
drivers/acpi/acpica/exmisc.c
drivers/acpi/acpica/exmutex.c
drivers/acpi/acpica/exnames.c
drivers/acpi/acpica/exoparg1.c
drivers/acpi/acpica/exoparg2.c
drivers/acpi/acpica/exoparg3.c
drivers/acpi/acpica/exoparg6.c
drivers/acpi/acpica/exprep.c
drivers/acpi/acpica/exregion.c
drivers/acpi/acpica/exresnte.c
drivers/acpi/acpica/exresolv.c
drivers/acpi/acpica/exresop.c
drivers/acpi/acpica/exstore.c
drivers/acpi/acpica/exstorob.c
drivers/acpi/acpica/exsystem.c
drivers/acpi/acpica/extrace.c [new file with mode: 0644]
drivers/acpi/acpica/exutils.c
drivers/acpi/acpica/hwesleep.c
drivers/acpi/acpica/hwgpe.c
drivers/acpi/acpica/hwsleep.c
drivers/acpi/acpica/hwxface.c
drivers/acpi/acpica/hwxfsleep.c
drivers/acpi/acpica/nsconvert.c
drivers/acpi/acpica/nsdump.c
drivers/acpi/acpica/nseval.c
drivers/acpi/acpica/nsinit.c
drivers/acpi/acpica/nsload.c
drivers/acpi/acpica/nsnames.c
drivers/acpi/acpica/nsparse.c
drivers/acpi/acpica/nsprepkg.c
drivers/acpi/acpica/nsrepair.c
drivers/acpi/acpica/nsrepair2.c
drivers/acpi/acpica/nssearch.c
drivers/acpi/acpica/nsutils.c
drivers/acpi/acpica/nsxfeval.c
drivers/acpi/acpica/nsxfname.c
drivers/acpi/acpica/nsxfobj.c
drivers/acpi/acpica/psargs.c
drivers/acpi/acpica/psloop.c
drivers/acpi/acpica/psopcode.c
drivers/acpi/acpica/psparse.c
drivers/acpi/acpica/psutils.c
drivers/acpi/acpica/pswalk.c
drivers/acpi/acpica/rsaddr.c
drivers/acpi/acpica/rscalc.c
drivers/acpi/acpica/rscreate.c
drivers/acpi/acpica/rsdump.c
drivers/acpi/acpica/rslist.c
drivers/acpi/acpica/rsmisc.c
drivers/acpi/acpica/rsutils.c
drivers/acpi/acpica/rsxface.c
drivers/acpi/acpica/tbdata.c
drivers/acpi/acpica/tbinstal.c
drivers/acpi/acpica/tbprint.c
drivers/acpi/acpica/tbutils.c
drivers/acpi/acpica/tbxfload.c
drivers/acpi/acpica/utaddress.c
drivers/acpi/acpica/utcopy.c
drivers/acpi/acpica/utdecode.c
drivers/acpi/acpica/utdelete.c
drivers/acpi/acpica/uterror.c
drivers/acpi/acpica/utfileio.c [deleted file]
drivers/acpi/acpica/uthex.c
drivers/acpi/acpica/utids.c
drivers/acpi/acpica/utinit.c
drivers/acpi/acpica/utmath.c
drivers/acpi/acpica/utmisc.c
drivers/acpi/acpica/utmutex.c
drivers/acpi/acpica/utnonansi.c
drivers/acpi/acpica/utobject.c
drivers/acpi/acpica/utosi.c
drivers/acpi/acpica/utownerid.c
drivers/acpi/acpica/utpredef.c
drivers/acpi/acpica/utprint.c
drivers/acpi/acpica/utresrc.c
drivers/acpi/acpica/utstate.c
drivers/acpi/acpica/utstring.c
drivers/acpi/acpica/uttrack.c
drivers/acpi/acpica/utxface.c
drivers/acpi/acpica/utxferror.c
drivers/acpi/acpica/utxfinit.c
drivers/acpi/acpica/utxfmutex.c
drivers/acpi/bus.c
drivers/acpi/gsi.c
drivers/acpi/internal.h
drivers/acpi/osl.c
drivers/acpi/pci_irq.c
drivers/acpi/pci_link.c
drivers/acpi/property.c
drivers/acpi/resource.c
drivers/acpi/sbs.c
drivers/acpi/scan.c
drivers/acpi/sleep.c
drivers/acpi/sleep.h
drivers/acpi/utils.c
drivers/acpi/video_detect.c
drivers/base/base.h
drivers/base/core.c
drivers/base/dd.c
drivers/base/platform.c
drivers/base/power/clock_ops.c
drivers/base/power/common.c
drivers/base/power/domain.c
drivers/base/power/main.c
drivers/base/power/opp/Makefile
drivers/base/power/opp/core.c
drivers/base/power/opp/cpu.c
drivers/base/power/opp/debugfs.c [new file with mode: 0644]
drivers/base/power/opp/opp.h
drivers/base/power/power.h
drivers/base/power/runtime.c
drivers/base/property.c
drivers/cpufreq/Kconfig.arm
drivers/cpufreq/Makefile
drivers/cpufreq/acpi-cpufreq.c
drivers/cpufreq/arm_big_little.c
drivers/cpufreq/blackfin-cpufreq.c
drivers/cpufreq/cpufreq-dt.c
drivers/cpufreq/cpufreq.c
drivers/cpufreq/cpufreq_conservative.c
drivers/cpufreq/cpufreq_governor.c
drivers/cpufreq/cpufreq_governor.h
drivers/cpufreq/cpufreq_ondemand.c
drivers/cpufreq/intel_pstate.c
drivers/cpufreq/mt8173-cpufreq.c
drivers/cpufreq/pcc-cpufreq.c
drivers/cpufreq/qoriq-cpufreq.c
drivers/cpufreq/sti-cpufreq.c [new file with mode: 0644]
drivers/cpuidle/cpuidle-clps711x.c
drivers/cpuidle/cpuidle-exynos.c
drivers/cpuidle/cpuidle-ux500.c
drivers/cpuidle/governors/menu.c
drivers/dma/dw/core.c
drivers/dma/dw/platform.c
drivers/gpio/gpiolib-acpi.c
drivers/gpio/gpiolib.c
drivers/gpio/gpiolib.h
drivers/i2c/busses/i2c-designware-baytrail.c
drivers/i2c/busses/i2c-designware-platdrv.c
drivers/mfd/intel-lpss-acpi.c
drivers/mfd/intel-lpss-pci.c
drivers/mfd/intel-lpss.c
drivers/mfd/intel-lpss.h
drivers/mfd/mfd-core.c
drivers/net/wireless/ath/ath10k/mac.c
drivers/net/wireless/ath/ath9k/htc_drv_main.c
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/carl9170/main.c
drivers/net/wireless/ath/wcn36xx/main.c
drivers/net/wireless/ath/wil6210/cfg80211.c
drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c
drivers/net/wireless/intel/iwlegacy/4965-mac.c
drivers/net/wireless/intel/iwlegacy/4965.h
drivers/net/wireless/intel/iwlwifi/dvm/lib.c
drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/d3.c
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/tx.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/marvell/mwl8k.c
drivers/net/wireless/mediatek/mt7601u/main.c
drivers/net/wireless/ralink/rt2x00/rt2800lib.c
drivers/net/wireless/ralink/rt2x00/rt2800lib.h
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c
drivers/net/wireless/realtek/rtlwifi/core.c
drivers/net/wireless/rsi/rsi_91x_mac80211.c
drivers/net/wireless/st/cw1200/sta.c
drivers/net/wireless/st/cw1200/sta.h
drivers/net/wireless/ti/wlcore/main.c
drivers/pci/pci-acpi.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/platform/x86/dell-wmi.c
drivers/platform/x86/thinkpad_acpi.c
drivers/pnp/driver.c
drivers/pnp/quirks.c
drivers/powercap/intel_rapl.c
drivers/powercap/powercap_sys.c
drivers/spi/spi.c
drivers/staging/vt6655/rxtx.c
drivers/staging/vt6656/rxtx.c
drivers/thermal/intel_quark_dts_thermal.c
drivers/thermal/intel_soc_dts_iosf.c
include/acpi/acexcep.h
include/acpi/acpi_bus.h
include/acpi/acpiosxf.h
include/acpi/acpixf.h
include/acpi/actypes.h
include/acpi/platform/aclinux.h
include/acpi/platform/aclinuxex.h
include/acpi/video.h
include/linux/acpi.h
include/linux/cgroup-defs.h
include/linux/cgroup.h
include/linux/cgroup_subsys.h
include/linux/cpufreq.h
include/linux/device.h
include/linux/ftrace.h
include/linux/ieee80211.h
include/linux/mfd/core.h
include/linux/platform_device.h
include/linux/pm_opp.h
include/linux/pm_runtime.h
include/linux/powercap.h
include/linux/property.h
include/linux/rfkill-gpio.h [deleted file]
include/linux/rfkill.h
include/linux/tracepoint.h
include/net/cfg80211.h
include/net/mac80211.h
include/trace/define_trace.h
include/trace/trace_events.h
include/uapi/linux/magic.h
include/uapi/linux/nl80211.h
include/uapi/linux/rfkill.h
init/Kconfig
kernel/cgroup.c
kernel/cgroup_freezer.c
kernel/cgroup_pids.c
kernel/cpuset.c
kernel/fork.c
kernel/power/main.c
kernel/power/power.h
kernel/sched/core.c
kernel/trace/bpf_trace.c
kernel/trace/ftrace.c
kernel/trace/ring_buffer.c
kernel/trace/trace.h
kernel/trace/trace_event_perf.c
kernel/trace/trace_events_trigger.c
lib/seq_buf.c
mm/memcontrol.c
net/mac80211/agg-rx.c
net/mac80211/agg-tx.c
net/mac80211/cfg.c
net/mac80211/chan.c
net/mac80211/debugfs.c
net/mac80211/debugfs_key.c
net/mac80211/driver-ops.c
net/mac80211/driver-ops.h
net/mac80211/ht.c
net/mac80211/ibss.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/key.c
net/mac80211/key.h
net/mac80211/mesh.c
net/mac80211/mesh.h
net/mac80211/mesh_pathtbl.c
net/mac80211/mesh_plink.c
net/mac80211/mlme.c
net/mac80211/rx.c
net/mac80211/sta_info.c
net/mac80211/sta_info.h
net/mac80211/tkip.c
net/mac80211/tkip.h
net/mac80211/trace.h
net/mac80211/tx.c
net/mac80211/util.c
net/mac80211/vht.c
net/mac80211/wpa.c
net/netlink/genetlink.c
net/rfkill/Kconfig
net/rfkill/core.c
net/rfkill/rfkill-gpio.c
net/wireless/Kconfig
net/wireless/core.c
net/wireless/mlme.c
net/wireless/nl80211.c
net/wireless/radiotap.c
net/wireless/reg.c
net/wireless/sme.c
net/wireless/util.c
tools/power/acpi/Makefile
tools/power/acpi/common/getopt.c
tools/power/acpi/os_specific/service_layers/oslibcfs.c
tools/power/acpi/tools/acpidbg/Makefile [new file with mode: 0644]
tools/power/acpi/tools/acpidbg/acpidbg.c [new file with mode: 0644]
tools/power/acpi/tools/acpidump/apfiles.c
tools/power/cpupower/Makefile
tools/power/cpupower/bench/Makefile
tools/power/cpupower/utils/cpufreq-info.c
tools/power/cpupower/utils/cpuidle-info.c
tools/power/cpupower/utils/cpupower-info.c
tools/power/cpupower/utils/cpupower-set.c
tools/power/cpupower/utils/helpers/topology.c
tools/testing/selftests/ftrace/test.d/instances/instance.tc [new file with mode: 0644]

diff --git a/Documentation/ABI/obsolete/sysfs-class-rfkill b/Documentation/ABI/obsolete/sysfs-class-rfkill
deleted file mode 100644 (file)
index ff60ad9..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-rfkill - radio frequency (RF) connector kill switch support
-
-For details to this subsystem look at Documentation/rfkill.txt.
-
-What:          /sys/class/rfkill/rfkill[0-9]+/state
-Date:          09-Jul-2007
-KernelVersion  v2.6.22
-Contact:       linux-wireless@vger.kernel.org
-Description:   Current state of the transmitter.
-               This file is deprecated and scheduled to be removed in 2014,
-               because its not possible to express the 'soft and hard block'
-               state of the rfkill driver.
-Values:        A numeric value.
-               0: RFKILL_STATE_SOFT_BLOCKED
-                       transmitter is turned off by software
-               1: RFKILL_STATE_UNBLOCKED
-                       transmitter is (potentially) active
-               2: RFKILL_STATE_HARD_BLOCKED
-                       transmitter is forced off by something outside of
-                       the driver's control.
-
-What:          /sys/class/rfkill/rfkill[0-9]+/claim
-Date:          09-Jul-2007
-KernelVersion  v2.6.22
-Contact:       linux-wireless@vger.kernel.org
-Description:   This file is deprecated because there no longer is a way to
-               claim just control over a single rfkill instance.
-               This file is scheduled to be removed in 2012.
-Values:        0: Kernel handles events
diff --git a/Documentation/ABI/removed/sysfs-class-rfkill b/Documentation/ABI/removed/sysfs-class-rfkill
new file mode 100644 (file)
index 0000000..3ce6231
--- /dev/null
@@ -0,0 +1,13 @@
+rfkill - radio frequency (RF) connector kill switch support
+
+For details to this subsystem look at Documentation/rfkill.txt.
+
+What:          /sys/class/rfkill/rfkill[0-9]+/claim
+Date:          09-Jul-2007
+KernelVersion  v2.6.22
+Contact:       linux-wireless@vger.kernel.org
+Description:   This file was deprecated because there no longer was a way to
+               claim just control over a single rfkill instance.
+               This file was scheduled to be removed in 2012, and was removed
+               in 2016.
+Values:        0: Kernel handles events
index 097f522c33bb7b5c3632a9ca200e099fea32b2cf..e1ba4a10475364cd8fcf201b323c26de5ee8b62b 100644 (file)
@@ -2,9 +2,8 @@ rfkill - radio frequency (RF) connector kill switch support
 
 For details to this subsystem look at Documentation/rfkill.txt.
 
-For the deprecated /sys/class/rfkill/*/state and
-/sys/class/rfkill/*/claim knobs of this interface look in
-Documentation/ABI/obsolete/sysfs-class-rfkill.
+For the deprecated /sys/class/rfkill/*/claim knobs of this interface look in
+Documentation/ABI/removed/sysfs-class-rfkill.
 
 What:          /sys/class/rfkill
 Date:          09-Jul-2007
@@ -42,6 +41,28 @@ Values:      A numeric value.
                1: true
 
 
+What:          /sys/class/rfkill/rfkill[0-9]+/state
+Date:          09-Jul-2007
+KernelVersion  v2.6.22
+Contact:       linux-wireless@vger.kernel.org
+Description:   Current state of the transmitter.
+               This file was scheduled to be removed in 2014, but due to its
+               large number of users it will be sticking around for a bit
+               longer. Despite it being marked as stabe, the newer "hard" and
+               "soft" interfaces should be preffered, since it is not possible
+               to express the 'soft and hard block' state of the rfkill driver
+               through this interface. There will likely be another attempt to
+               remove it in the future.
+Values:        A numeric value.
+               0: RFKILL_STATE_SOFT_BLOCKED
+                       transmitter is turned off by software
+               1: RFKILL_STATE_UNBLOCKED
+                       transmitter is (potentially) active
+               2: RFKILL_STATE_HARD_BLOCKED
+                       transmitter is forced off by something outside of
+                       the driver's control.
+
+
 What:          /sys/class/rfkill/rfkill[0-9]+/hard
 Date:          12-March-2010
 KernelVersion  v2.6.34
diff --git a/Documentation/cgroup-v1/00-INDEX b/Documentation/cgroup-v1/00-INDEX
new file mode 100644 (file)
index 0000000..6ad425f
--- /dev/null
@@ -0,0 +1,28 @@
+00-INDEX
+       - this file
+blkio-controller.txt
+       - Description for Block IO Controller, implementation and usage details.
+cgroups.txt
+       - Control Groups definition, implementation details, examples and API.
+cpuacct.txt
+       - CPU Accounting Controller; account CPU usage for groups of tasks.
+cpusets.txt
+       - documents the cpusets feature; assign CPUs and Mem to a set of tasks.
+devices.txt
+       - Device Whitelist Controller; description, interface and security.
+freezer-subsystem.txt
+       - checkpointing; rationale to not use signals, interface.
+hugetlb.txt
+       - HugeTLB Controller implementation and usage details.
+memcg_test.txt
+       - Memory Resource Controller; implementation details.
+memory.txt
+       - Memory Resource Controller; design, accounting, interface, testing.
+net_cls.txt
+       - Network classifier cgroups details and usages.
+net_prio.txt
+       - Network priority cgroups details and usages.
+pids.txt
+       - Process number cgroups details and usages.
+unified-hierarchy.txt
+       - Description the new/next cgroup interface.
diff --git a/Documentation/cgroup-v1/blkio-controller.txt b/Documentation/cgroup-v1/blkio-controller.txt
new file mode 100644 (file)
index 0000000..673dc34
--- /dev/null
@@ -0,0 +1,375 @@
+                               Block IO Controller
+                               ===================
+Overview
+========
+cgroup subsys "blkio" implements the block io controller. There seems to be
+a need of various kinds of IO control policies (like proportional BW, max BW)
+both at leaf nodes as well as at intermediate nodes in a storage hierarchy.
+Plan is to use the same cgroup based management interface for blkio controller
+and based on user options switch IO policies in the background.
+
+Currently two IO control policies are implemented. First one is proportional
+weight time based division of disk policy. It is implemented in CFQ. Hence
+this policy takes effect only on leaf nodes when CFQ is being used. The second
+one is throttling policy which can be used to specify upper IO rate limits
+on devices. This policy is implemented in generic block layer and can be
+used on leaf nodes as well as higher level logical devices like device mapper.
+
+HOWTO
+=====
+Proportional Weight division of bandwidth
+-----------------------------------------
+You can do a very simple testing of running two dd threads in two different
+cgroups. Here is what you can do.
+
+- Enable Block IO controller
+       CONFIG_BLK_CGROUP=y
+
+- Enable group scheduling in CFQ
+       CONFIG_CFQ_GROUP_IOSCHED=y
+
+- Compile and boot into kernel and mount IO controller (blkio); see
+  cgroups.txt, Why are cgroups needed?.
+
+       mount -t tmpfs cgroup_root /sys/fs/cgroup
+       mkdir /sys/fs/cgroup/blkio
+       mount -t cgroup -o blkio none /sys/fs/cgroup/blkio
+
+- Create two cgroups
+       mkdir -p /sys/fs/cgroup/blkio/test1/ /sys/fs/cgroup/blkio/test2
+
+- Set weights of group test1 and test2
+       echo 1000 > /sys/fs/cgroup/blkio/test1/blkio.weight
+       echo 500 > /sys/fs/cgroup/blkio/test2/blkio.weight
+
+- Create two same size files (say 512MB each) on same disk (file1, file2) and
+  launch two dd threads in different cgroup to read those files.
+
+       sync
+       echo 3 > /proc/sys/vm/drop_caches
+
+       dd if=/mnt/sdb/zerofile1 of=/dev/null &
+       echo $! > /sys/fs/cgroup/blkio/test1/tasks
+       cat /sys/fs/cgroup/blkio/test1/tasks
+
+       dd if=/mnt/sdb/zerofile2 of=/dev/null &
+       echo $! > /sys/fs/cgroup/blkio/test2/tasks
+       cat /sys/fs/cgroup/blkio/test2/tasks
+
+- At macro level, first dd should finish first. To get more precise data, keep
+  on looking at (with the help of script), at blkio.disk_time and
+  blkio.disk_sectors files of both test1 and test2 groups. This will tell how
+  much disk time (in milliseconds), each group got and how many sectors each
+  group dispatched to the disk. We provide fairness in terms of disk time, so
+  ideally io.disk_time of cgroups should be in proportion to the weight.
+
+Throttling/Upper Limit policy
+-----------------------------
+- Enable Block IO controller
+       CONFIG_BLK_CGROUP=y
+
+- Enable throttling in block layer
+       CONFIG_BLK_DEV_THROTTLING=y
+
+- Mount blkio controller (see cgroups.txt, Why are cgroups needed?)
+        mount -t cgroup -o blkio none /sys/fs/cgroup/blkio
+
+- Specify a bandwidth rate on particular device for root group. The format
+  for policy is "<major>:<minor>  <bytes_per_second>".
+
+        echo "8:16  1048576" > /sys/fs/cgroup/blkio/blkio.throttle.read_bps_device
+
+  Above will put a limit of 1MB/second on reads happening for root group
+  on device having major/minor number 8:16.
+
+- Run dd to read a file and see if rate is throttled to 1MB/s or not.
+
+        # dd iflag=direct if=/mnt/common/zerofile of=/dev/null bs=4K count=1024
+        1024+0 records in
+        1024+0 records out
+        4194304 bytes (4.2 MB) copied, 4.0001 s, 1.0 MB/s
+
+ Limits for writes can be put using blkio.throttle.write_bps_device file.
+
+Hierarchical Cgroups
+====================
+
+Both CFQ and throttling implement hierarchy support; however,
+throttling's hierarchy support is enabled iff "sane_behavior" is
+enabled from cgroup side, which currently is a development option and
+not publicly available.
+
+If somebody created a hierarchy like as follows.
+
+                       root
+                       /  \
+                    test1 test2
+                       |
+                    test3
+
+CFQ by default and throttling with "sane_behavior" will handle the
+hierarchy correctly.  For details on CFQ hierarchy support, refer to
+Documentation/block/cfq-iosched.txt.  For throttling, all limits apply
+to the whole subtree while all statistics are local to the IOs
+directly generated by tasks in that cgroup.
+
+Throttling without "sane_behavior" enabled from cgroup side will
+practically treat all groups at same level as if it looks like the
+following.
+
+                               pivot
+                            /  /   \  \
+                       root  test1 test2  test3
+
+Various user visible config options
+===================================
+CONFIG_BLK_CGROUP
+       - Block IO controller.
+
+CONFIG_DEBUG_BLK_CGROUP
+       - Debug help. Right now some additional stats file show up in cgroup
+         if this option is enabled.
+
+CONFIG_CFQ_GROUP_IOSCHED
+       - Enables group scheduling in CFQ. Currently only 1 level of group
+         creation is allowed.
+
+CONFIG_BLK_DEV_THROTTLING
+       - Enable block device throttling support in block layer.
+
+Details of cgroup files
+=======================
+Proportional weight policy files
+--------------------------------
+- blkio.weight
+       - Specifies per cgroup weight. This is default weight of the group
+         on all the devices until and unless overridden by per device rule.
+         (See blkio.weight_device).
+         Currently allowed range of weights is from 10 to 1000.
+
+- blkio.weight_device
+       - One can specify per cgroup per device rules using this interface.
+         These rules override the default value of group weight as specified
+         by blkio.weight.
+
+         Following is the format.
+
+         # echo dev_maj:dev_minor weight > blkio.weight_device
+         Configure weight=300 on /dev/sdb (8:16) in this cgroup
+         # echo 8:16 300 > blkio.weight_device
+         # cat blkio.weight_device
+         dev     weight
+         8:16    300
+
+         Configure weight=500 on /dev/sda (8:0) in this cgroup
+         # echo 8:0 500 > blkio.weight_device
+         # cat blkio.weight_device
+         dev     weight
+         8:0     500
+         8:16    300
+
+         Remove specific weight for /dev/sda in this cgroup
+         # echo 8:0 0 > blkio.weight_device
+         # cat blkio.weight_device
+         dev     weight
+         8:16    300
+
+- blkio.leaf_weight[_device]
+       - Equivalents of blkio.weight[_device] for the purpose of
+          deciding how much weight tasks in the given cgroup has while
+          competing with the cgroup's child cgroups. For details,
+          please refer to Documentation/block/cfq-iosched.txt.
+
+- blkio.time
+       - disk time allocated to cgroup per device in milliseconds. First
+         two fields specify the major and minor number of the device and
+         third field specifies the disk time allocated to group in
+         milliseconds.
+
+- blkio.sectors
+       - number of sectors transferred to/from disk by the group. First
+         two fields specify the major and minor number of the device and
+         third field specifies the number of sectors transferred by the
+         group to/from the device.
+
+- blkio.io_service_bytes
+       - Number of bytes transferred to/from the disk by the group. These
+         are further divided by the type of operation - read or write, sync
+         or async. First two fields specify the major and minor number of the
+         device, third field specifies the operation type and the fourth field
+         specifies the number of bytes.
+
+- blkio.io_serviced
+       - Number of IOs (bio) issued to the disk by the group. These
+         are further divided by the type of operation - read or write, sync
+         or async. First two fields specify the major and minor number of the
+         device, third field specifies the operation type and the fourth field
+         specifies the number of IOs.
+
+- blkio.io_service_time
+       - Total amount of time between request dispatch and request completion
+         for the IOs done by this cgroup. This is in nanoseconds to make it
+         meaningful for flash devices too. For devices with queue depth of 1,
+         this time represents the actual service time. When queue_depth > 1,
+         that is no longer true as requests may be served out of order. This
+         may cause the service time for a given IO to include the service time
+         of multiple IOs when served out of order which may result in total
+         io_service_time > actual time elapsed. This time is further divided by
+         the type of operation - read or write, sync or async. First two fields
+         specify the major and minor number of the device, third field
+         specifies the operation type and the fourth field specifies the
+         io_service_time in ns.
+
+- blkio.io_wait_time
+       - Total amount of time the IOs for this cgroup spent waiting in the
+         scheduler queues for service. This can be greater than the total time
+         elapsed since it is cumulative io_wait_time for all IOs. It is not a
+         measure of total time the cgroup spent waiting but rather a measure of
+         the wait_time for its individual IOs. For devices with queue_depth > 1
+         this metric does not include the time spent waiting for service once
+         the IO is dispatched to the device but till it actually gets serviced
+         (there might be a time lag here due to re-ordering of requests by the
+         device). This is in nanoseconds to make it meaningful for flash
+         devices too. This time is further divided by the type of operation -
+         read or write, sync or async. First two fields specify the major and
+         minor number of the device, third field specifies the operation type
+         and the fourth field specifies the io_wait_time in ns.
+
+- blkio.io_merged
+       - Total number of bios/requests merged into requests belonging to this
+         cgroup. This is further divided by the type of operation - read or
+         write, sync or async.
+
+- blkio.io_queued
+       - Total number of requests queued up at any given instant for this
+         cgroup. This is further divided by the type of operation - read or
+         write, sync or async.
+
+- blkio.avg_queue_size
+       - Debugging aid only enabled if CONFIG_DEBUG_BLK_CGROUP=y.
+         The average queue size for this cgroup over the entire time of this
+         cgroup's existence. Queue size samples are taken each time one of the
+         queues of this cgroup gets a timeslice.
+
+- blkio.group_wait_time
+       - Debugging aid only enabled if CONFIG_DEBUG_BLK_CGROUP=y.
+         This is the amount of time the cgroup had to wait since it became busy
+         (i.e., went from 0 to 1 request queued) to get a timeslice for one of
+         its queues. This is different from the io_wait_time which is the
+         cumulative total of the amount of time spent by each IO in that cgroup
+         waiting in the scheduler queue. This is in nanoseconds. If this is
+         read when the cgroup is in a waiting (for timeslice) state, the stat
+         will only report the group_wait_time accumulated till the last time it
+         got a timeslice and will not include the current delta.
+
+- blkio.empty_time
+       - Debugging aid only enabled if CONFIG_DEBUG_BLK_CGROUP=y.
+         This is the amount of time a cgroup spends without any pending
+         requests when not being served, i.e., it does not include any time
+         spent idling for one of the queues of the cgroup. This is in
+         nanoseconds. If this is read when the cgroup is in an empty state,
+         the stat will only report the empty_time accumulated till the last
+         time it had a pending request and will not include the current delta.
+
+- blkio.idle_time
+       - Debugging aid only enabled if CONFIG_DEBUG_BLK_CGROUP=y.
+         This is the amount of time spent by the IO scheduler idling for a
+         given cgroup in anticipation of a better request than the existing ones
+         from other queues/cgroups. This is in nanoseconds. If this is read
+         when the cgroup is in an idling state, the stat will only report the
+         idle_time accumulated till the last idle period and will not include
+         the current delta.
+
+- blkio.dequeue
+       - Debugging aid only enabled if CONFIG_DEBUG_BLK_CGROUP=y. This
+         gives the statistics about how many a times a group was dequeued
+         from service tree of the device. First two fields specify the major
+         and minor number of the device and third field specifies the number
+         of times a group was dequeued from a particular device.
+
+- blkio.*_recursive
+       - Recursive version of various stats. These files show the
+          same information as their non-recursive counterparts but
+          include stats from all the descendant cgroups.
+
+Throttling/Upper limit policy files
+-----------------------------------
+- blkio.throttle.read_bps_device
+       - Specifies upper limit on READ rate from the device. IO rate is
+         specified in bytes per second. Rules are per device. Following is
+         the format.
+
+  echo "<major>:<minor>  <rate_bytes_per_second>" > /cgrp/blkio.throttle.read_bps_device
+
+- blkio.throttle.write_bps_device
+       - Specifies upper limit on WRITE rate to the device. IO rate is
+         specified in bytes per second. Rules are per device. Following is
+         the format.
+
+  echo "<major>:<minor>  <rate_bytes_per_second>" > /cgrp/blkio.throttle.write_bps_device
+
+- blkio.throttle.read_iops_device
+       - Specifies upper limit on READ rate from the device. IO rate is
+         specified in IO per second. Rules are per device. Following is
+         the format.
+
+  echo "<major>:<minor>  <rate_io_per_second>" > /cgrp/blkio.throttle.read_iops_device
+
+- blkio.throttle.write_iops_device
+       - Specifies upper limit on WRITE rate to the device. IO rate is
+         specified in io per second. Rules are per device. Following is
+         the format.
+
+  echo "<major>:<minor>  <rate_io_per_second>" > /cgrp/blkio.throttle.write_iops_device
+
+Note: If both BW and IOPS rules are specified for a device, then IO is
+      subjected to both the constraints.
+
+- blkio.throttle.io_serviced
+       - Number of IOs (bio) issued to the disk by the group. These
+         are further divided by the type of operation - read or write, sync
+         or async. First two fields specify the major and minor number of the
+         device, third field specifies the operation type and the fourth field
+         specifies the number of IOs.
+
+- blkio.throttle.io_service_bytes
+       - Number of bytes transferred to/from the disk by the group. These
+         are further divided by the type of operation - read or write, sync
+         or async. First two fields specify the major and minor number of the
+         device, third field specifies the operation type and the fourth field
+         specifies the number of bytes.
+
+Common files among various policies
+-----------------------------------
+- blkio.reset_stats
+       - Writing an int to this file will result in resetting all the stats
+         for that cgroup.
+
+CFQ sysfs tunable
+=================
+/sys/block/<disk>/queue/iosched/slice_idle
+------------------------------------------
+On a faster hardware CFQ can be slow, especially with sequential workload.
+This happens because CFQ idles on a single queue and single queue might not
+drive deeper request queue depths to keep the storage busy. In such scenarios
+one can try setting slice_idle=0 and that would switch CFQ to IOPS
+(IO operations per second) mode on NCQ supporting hardware.
+
+That means CFQ will not idle between cfq queues of a cfq group and hence be
+able to driver higher queue depth and achieve better throughput. That also
+means that cfq provides fairness among groups in terms of IOPS and not in
+terms of disk time.
+
+/sys/block/<disk>/queue/iosched/group_idle
+------------------------------------------
+If one disables idling on individual cfq queues and cfq service trees by
+setting slice_idle=0, group_idle kicks in. That means CFQ will still idle
+on the group in an attempt to provide fairness among groups.
+
+By default group_idle is same as slice_idle and does not do anything if
+slice_idle is enabled.
+
+One can experience an overall throughput drop if you have created multiple
+groups and put applications in that group which are not driving enough
+IO to keep disk busy. In that case set group_idle=0, and CFQ will not idle
+on individual groups and throughput should improve.
diff --git a/Documentation/cgroup-v1/cgroups.txt b/Documentation/cgroup-v1/cgroups.txt
new file mode 100644 (file)
index 0000000..c6256ae
--- /dev/null
@@ -0,0 +1,682 @@
+                               CGROUPS
+                               -------
+
+Written by Paul Menage <menage@google.com> based on
+Documentation/cgroups/cpusets.txt
+
+Original copyright statements from cpusets.txt:
+Portions Copyright (C) 2004 BULL SA.
+Portions Copyright (c) 2004-2006 Silicon Graphics, Inc.
+Modified by Paul Jackson <pj@sgi.com>
+Modified by Christoph Lameter <clameter@sgi.com>
+
+CONTENTS:
+=========
+
+1. Control Groups
+  1.1 What are cgroups ?
+  1.2 Why are cgroups needed ?
+  1.3 How are cgroups implemented ?
+  1.4 What does notify_on_release do ?
+  1.5 What does clone_children do ?
+  1.6 How do I use cgroups ?
+2. Usage Examples and Syntax
+  2.1 Basic Usage
+  2.2 Attaching processes
+  2.3 Mounting hierarchies by name
+3. Kernel API
+  3.1 Overview
+  3.2 Synchronization
+  3.3 Subsystem API
+4. Extended attributes usage
+5. Questions
+
+1. Control Groups
+=================
+
+1.1 What are cgroups ?
+----------------------
+
+Control Groups provide a mechanism for aggregating/partitioning sets of
+tasks, and all their future children, into hierarchical groups with
+specialized behaviour.
+
+Definitions:
+
+A *cgroup* associates a set of tasks with a set of parameters for one
+or more subsystems.
+
+A *subsystem* is a module that makes use of the task grouping
+facilities provided by cgroups to treat groups of tasks in
+particular ways. A subsystem is typically a "resource controller" that
+schedules a resource or applies per-cgroup limits, but it may be
+anything that wants to act on a group of processes, e.g. a
+virtualization subsystem.
+
+A *hierarchy* is a set of cgroups arranged in a tree, such that
+every task in the system is in exactly one of the cgroups in the
+hierarchy, and a set of subsystems; each subsystem has system-specific
+state attached to each cgroup in the hierarchy.  Each hierarchy has
+an instance of the cgroup virtual filesystem associated with it.
+
+At any one time there may be multiple active hierarchies of task
+cgroups. Each hierarchy is a partition of all tasks in the system.
+
+User-level code may create and destroy cgroups by name in an
+instance of the cgroup virtual file system, specify and query to
+which cgroup a task is assigned, and list the task PIDs assigned to
+a cgroup. Those creations and assignments only affect the hierarchy
+associated with that instance of the cgroup file system.
+
+On their own, the only use for cgroups is for simple job
+tracking. The intention is that other subsystems hook into the generic
+cgroup support to provide new attributes for cgroups, such as
+accounting/limiting the resources which processes in a cgroup can
+access. For example, cpusets (see Documentation/cgroups/cpusets.txt) allow
+you to associate a set of CPUs and a set of memory nodes with the
+tasks in each cgroup.
+
+1.2 Why are cgroups needed ?
+----------------------------
+
+There are multiple efforts to provide process aggregations in the
+Linux kernel, mainly for resource-tracking purposes. Such efforts
+include cpusets, CKRM/ResGroups, UserBeanCounters, and virtual server
+namespaces. These all require the basic notion of a
+grouping/partitioning of processes, with newly forked processes ending
+up in the same group (cgroup) as their parent process.
+
+The kernel cgroup patch provides the minimum essential kernel
+mechanisms required to efficiently implement such groups. It has
+minimal impact on the system fast paths, and provides hooks for
+specific subsystems such as cpusets to provide additional behaviour as
+desired.
+
+Multiple hierarchy support is provided to allow for situations where
+the division of tasks into cgroups is distinctly different for
+different subsystems - having parallel hierarchies allows each
+hierarchy to be a natural division of tasks, without having to handle
+complex combinations of tasks that would be present if several
+unrelated subsystems needed to be forced into the same tree of
+cgroups.
+
+At one extreme, each resource controller or subsystem could be in a
+separate hierarchy; at the other extreme, all subsystems
+would be attached to the same hierarchy.
+
+As an example of a scenario (originally proposed by vatsa@in.ibm.com)
+that can benefit from multiple hierarchies, consider a large
+university server with various users - students, professors, system
+tasks etc. The resource planning for this server could be along the
+following lines:
+
+       CPU :          "Top cpuset"
+                       /       \
+               CPUSet1         CPUSet2
+                  |               |
+               (Professors)    (Students)
+
+               In addition (system tasks) are attached to topcpuset (so
+               that they can run anywhere) with a limit of 20%
+
+       Memory : Professors (50%), Students (30%), system (20%)
+
+       Disk : Professors (50%), Students (30%), system (20%)
+
+       Network : WWW browsing (20%), Network File System (60%), others (20%)
+                               / \
+               Professors (15%)  students (5%)
+
+Browsers like Firefox/Lynx go into the WWW network class, while (k)nfsd goes
+into the NFS network class.
+
+At the same time Firefox/Lynx will share an appropriate CPU/Memory class
+depending on who launched it (prof/student).
+
+With the ability to classify tasks differently for different resources
+(by putting those resource subsystems in different hierarchies),
+the admin can easily set up a script which receives exec notifications
+and depending on who is launching the browser he can
+
+    # echo browser_pid > /sys/fs/cgroup/<restype>/<userclass>/tasks
+
+With only a single hierarchy, he now would potentially have to create
+a separate cgroup for every browser launched and associate it with
+appropriate network and other resource class.  This may lead to
+proliferation of such cgroups.
+
+Also let's say that the administrator would like to give enhanced network
+access temporarily to a student's browser (since it is night and the user
+wants to do online gaming :))  OR give one of the student's simulation
+apps enhanced CPU power.
+
+With ability to write PIDs directly to resource classes, it's just a
+matter of:
+
+       # echo pid > /sys/fs/cgroup/network/<new_class>/tasks
+       (after some time)
+       # echo pid > /sys/fs/cgroup/network/<orig_class>/tasks
+
+Without this ability, the administrator would have to split the cgroup into
+multiple separate ones and then associate the new cgroups with the
+new resource classes.
+
+
+
+1.3 How are cgroups implemented ?
+---------------------------------
+
+Control Groups extends the kernel as follows:
+
+ - Each task in the system has a reference-counted pointer to a
+   css_set.
+
+ - A css_set contains a set of reference-counted pointers to
+   cgroup_subsys_state objects, one for each cgroup subsystem
+   registered in the system. There is no direct link from a task to
+   the cgroup of which it's a member in each hierarchy, but this
+   can be determined by following pointers through the
+   cgroup_subsys_state objects. This is because accessing the
+   subsystem state is something that's expected to happen frequently
+   and in performance-critical code, whereas operations that require a
+   task's actual cgroup assignments (in particular, moving between
+   cgroups) are less common. A linked list runs through the cg_list
+   field of each task_struct using the css_set, anchored at
+   css_set->tasks.
+
+ - A cgroup hierarchy filesystem can be mounted for browsing and
+   manipulation from user space.
+
+ - You can list all the tasks (by PID) attached to any cgroup.
+
+The implementation of cgroups requires a few, simple hooks
+into the rest of the kernel, none in performance-critical paths:
+
+ - in init/main.c, to initialize the root cgroups and initial
+   css_set at system boot.
+
+ - in fork and exit, to attach and detach a task from its css_set.
+
+In addition, a new file system of type "cgroup" may be mounted, to
+enable browsing and modifying the cgroups presently known to the
+kernel.  When mounting a cgroup hierarchy, you may specify a
+comma-separated list of subsystems to mount as the filesystem mount
+options.  By default, mounting the cgroup filesystem attempts to
+mount a hierarchy containing all registered subsystems.
+
+If an active hierarchy with exactly the same set of subsystems already
+exists, it will be reused for the new mount. If no existing hierarchy
+matches, and any of the requested subsystems are in use in an existing
+hierarchy, the mount will fail with -EBUSY. Otherwise, a new hierarchy
+is activated, associated with the requested subsystems.
+
+It's not currently possible to bind a new subsystem to an active
+cgroup hierarchy, or to unbind a subsystem from an active cgroup
+hierarchy. This may be possible in future, but is fraught with nasty
+error-recovery issues.
+
+When a cgroup filesystem is unmounted, if there are any
+child cgroups created below the top-level cgroup, that hierarchy
+will remain active even though unmounted; if there are no
+child cgroups then the hierarchy will be deactivated.
+
+No new system calls are added for cgroups - all support for
+querying and modifying cgroups is via this cgroup file system.
+
+Each task under /proc has an added file named 'cgroup' displaying,
+for each active hierarchy, the subsystem names and the cgroup name
+as the path relative to the root of the cgroup file system.
+
+Each cgroup is represented by a directory in the cgroup file system
+containing the following files describing that cgroup:
+
+ - tasks: list of tasks (by PID) attached to that cgroup.  This list
+   is not guaranteed to be sorted.  Writing a thread ID into this file
+   moves the thread into this cgroup.
+ - cgroup.procs: list of thread group IDs in the cgroup.  This list is
+   not guaranteed to be sorted or free of duplicate TGIDs, and userspace
+   should sort/uniquify the list if this property is required.
+   Writing a thread group ID into this file moves all threads in that
+   group into this cgroup.
+ - notify_on_release flag: run the release agent on exit?
+ - release_agent: the path to use for release notifications (this file
+   exists in the top cgroup only)
+
+Other subsystems such as cpusets may add additional files in each
+cgroup dir.
+
+New cgroups are created using the mkdir system call or shell
+command.  The properties of a cgroup, such as its flags, are
+modified by writing to the appropriate file in that cgroups
+directory, as listed above.
+
+The named hierarchical structure of nested cgroups allows partitioning
+a large system into nested, dynamically changeable, "soft-partitions".
+
+The attachment of each task, automatically inherited at fork by any
+children of that task, to a cgroup allows organizing the work load
+on a system into related sets of tasks.  A task may be re-attached to
+any other cgroup, if allowed by the permissions on the necessary
+cgroup file system directories.
+
+When a task is moved from one cgroup to another, it gets a new
+css_set pointer - if there's an already existing css_set with the
+desired collection of cgroups then that group is reused, otherwise a new
+css_set is allocated. The appropriate existing css_set is located by
+looking into a hash table.
+
+To allow access from a cgroup to the css_sets (and hence tasks)
+that comprise it, a set of cg_cgroup_link objects form a lattice;
+each cg_cgroup_link is linked into a list of cg_cgroup_links for
+a single cgroup on its cgrp_link_list field, and a list of
+cg_cgroup_links for a single css_set on its cg_link_list.
+
+Thus the set of tasks in a cgroup can be listed by iterating over
+each css_set that references the cgroup, and sub-iterating over
+each css_set's task set.
+
+The use of a Linux virtual file system (vfs) to represent the
+cgroup hierarchy provides for a familiar permission and name space
+for cgroups, with a minimum of additional kernel code.
+
+1.4 What does notify_on_release do ?
+------------------------------------
+
+If the notify_on_release flag is enabled (1) in a cgroup, then
+whenever the last task in the cgroup leaves (exits or attaches to
+some other cgroup) and the last child cgroup of that cgroup
+is removed, then the kernel runs the command specified by the contents
+of the "release_agent" file in that hierarchy's root directory,
+supplying the pathname (relative to the mount point of the cgroup
+file system) of the abandoned cgroup.  This enables automatic
+removal of abandoned cgroups.  The default value of
+notify_on_release in the root cgroup at system boot is disabled
+(0).  The default value of other cgroups at creation is the current
+value of their parents' notify_on_release settings. The default value of
+a cgroup hierarchy's release_agent path is empty.
+
+1.5 What does clone_children do ?
+---------------------------------
+
+This flag only affects the cpuset controller. If the clone_children
+flag is enabled (1) in a cgroup, a new cpuset cgroup will copy its
+configuration from the parent during initialization.
+
+1.6 How do I use cgroups ?
+--------------------------
+
+To start a new job that is to be contained within a cgroup, using
+the "cpuset" cgroup subsystem, the steps are something like:
+
+ 1) mount -t tmpfs cgroup_root /sys/fs/cgroup
+ 2) mkdir /sys/fs/cgroup/cpuset
+ 3) mount -t cgroup -ocpuset cpuset /sys/fs/cgroup/cpuset
+ 4) Create the new cgroup by doing mkdir's and write's (or echo's) in
+    the /sys/fs/cgroup/cpuset virtual file system.
+ 5) Start a task that will be the "founding father" of the new job.
+ 6) Attach that task to the new cgroup by writing its PID to the
+    /sys/fs/cgroup/cpuset tasks file for that cgroup.
+ 7) fork, exec or clone the job tasks from this founding father task.
+
+For example, the following sequence of commands will setup a cgroup
+named "Charlie", containing just CPUs 2 and 3, and Memory Node 1,
+and then start a subshell 'sh' in that cgroup:
+
+  mount -t tmpfs cgroup_root /sys/fs/cgroup
+  mkdir /sys/fs/cgroup/cpuset
+  mount -t cgroup cpuset -ocpuset /sys/fs/cgroup/cpuset
+  cd /sys/fs/cgroup/cpuset
+  mkdir Charlie
+  cd Charlie
+  /bin/echo 2-3 > cpuset.cpus
+  /bin/echo 1 > cpuset.mems
+  /bin/echo $$ > tasks
+  sh
+  # The subshell 'sh' is now running in cgroup Charlie
+  # The next line should display '/Charlie'
+  cat /proc/self/cgroup
+
+2. Usage Examples and Syntax
+============================
+
+2.1 Basic Usage
+---------------
+
+Creating, modifying, using cgroups can be done through the cgroup
+virtual filesystem.
+
+To mount a cgroup hierarchy with all available subsystems, type:
+# mount -t cgroup xxx /sys/fs/cgroup
+
+The "xxx" is not interpreted by the cgroup code, but will appear in
+/proc/mounts so may be any useful identifying string that you like.
+
+Note: Some subsystems do not work without some user input first.  For instance,
+if cpusets are enabled the user will have to populate the cpus and mems files
+for each new cgroup created before that group can be used.
+
+As explained in section `1.2 Why are cgroups needed?' you should create
+different hierarchies of cgroups for each single resource or group of
+resources you want to control. Therefore, you should mount a tmpfs on
+/sys/fs/cgroup and create directories for each cgroup resource or resource
+group.
+
+# mount -t tmpfs cgroup_root /sys/fs/cgroup
+# mkdir /sys/fs/cgroup/rg1
+
+To mount a cgroup hierarchy with just the cpuset and memory
+subsystems, type:
+# mount -t cgroup -o cpuset,memory hier1 /sys/fs/cgroup/rg1
+
+While remounting cgroups is currently supported, it is not recommend
+to use it. Remounting allows changing bound subsystems and
+release_agent. Rebinding is hardly useful as it only works when the
+hierarchy is empty and release_agent itself should be replaced with
+conventional fsnotify. The support for remounting will be removed in
+the future.
+
+To Specify a hierarchy's release_agent:
+# mount -t cgroup -o cpuset,release_agent="/sbin/cpuset_release_agent" \
+  xxx /sys/fs/cgroup/rg1
+
+Note that specifying 'release_agent' more than once will return failure.
+
+Note that changing the set of subsystems is currently only supported
+when the hierarchy consists of a single (root) cgroup. Supporting
+the ability to arbitrarily bind/unbind subsystems from an existing
+cgroup hierarchy is intended to be implemented in the future.
+
+Then under /sys/fs/cgroup/rg1 you can find a tree that corresponds to the
+tree of the cgroups in the system. For instance, /sys/fs/cgroup/rg1
+is the cgroup that holds the whole system.
+
+If you want to change the value of release_agent:
+# echo "/sbin/new_release_agent" > /sys/fs/cgroup/rg1/release_agent
+
+It can also be changed via remount.
+
+If you want to create a new cgroup under /sys/fs/cgroup/rg1:
+# cd /sys/fs/cgroup/rg1
+# mkdir my_cgroup
+
+Now you want to do something with this cgroup.
+# cd my_cgroup
+
+In this directory you can find several files:
+# ls
+cgroup.procs notify_on_release tasks
+(plus whatever files added by the attached subsystems)
+
+Now attach your shell to this cgroup:
+# /bin/echo $$ > tasks
+
+You can also create cgroups inside your cgroup by using mkdir in this
+directory.
+# mkdir my_sub_cs
+
+To remove a cgroup, just use rmdir:
+# rmdir my_sub_cs
+
+This will fail if the cgroup is in use (has cgroups inside, or
+has processes attached, or is held alive by other subsystem-specific
+reference).
+
+2.2 Attaching processes
+-----------------------
+
+# /bin/echo PID > tasks
+
+Note that it is PID, not PIDs. You can only attach ONE task at a time.
+If you have several tasks to attach, you have to do it one after another:
+
+# /bin/echo PID1 > tasks
+# /bin/echo PID2 > tasks
+       ...
+# /bin/echo PIDn > tasks
+
+You can attach the current shell task by echoing 0:
+
+# echo 0 > tasks
+
+You can use the cgroup.procs file instead of the tasks file to move all
+threads in a threadgroup at once. Echoing the PID of any task in a
+threadgroup to cgroup.procs causes all tasks in that threadgroup to be
+attached to the cgroup. Writing 0 to cgroup.procs moves all tasks
+in the writing task's threadgroup.
+
+Note: Since every task is always a member of exactly one cgroup in each
+mounted hierarchy, to remove a task from its current cgroup you must
+move it into a new cgroup (possibly the root cgroup) by writing to the
+new cgroup's tasks file.
+
+Note: Due to some restrictions enforced by some cgroup subsystems, moving
+a process to another cgroup can fail.
+
+2.3 Mounting hierarchies by name
+--------------------------------
+
+Passing the name=<x> option when mounting a cgroups hierarchy
+associates the given name with the hierarchy.  This can be used when
+mounting a pre-existing hierarchy, in order to refer to it by name
+rather than by its set of active subsystems.  Each hierarchy is either
+nameless, or has a unique name.
+
+The name should match [\w.-]+
+
+When passing a name=<x> option for a new hierarchy, you need to
+specify subsystems manually; the legacy behaviour of mounting all
+subsystems when none are explicitly specified is not supported when
+you give a subsystem a name.
+
+The name of the subsystem appears as part of the hierarchy description
+in /proc/mounts and /proc/<pid>/cgroups.
+
+
+3. Kernel API
+=============
+
+3.1 Overview
+------------
+
+Each kernel subsystem that wants to hook into the generic cgroup
+system needs to create a cgroup_subsys object. This contains
+various methods, which are callbacks from the cgroup system, along
+with a subsystem ID which will be assigned by the cgroup system.
+
+Other fields in the cgroup_subsys object include:
+
+- subsys_id: a unique array index for the subsystem, indicating which
+  entry in cgroup->subsys[] this subsystem should be managing.
+
+- name: should be initialized to a unique subsystem name. Should be
+  no longer than MAX_CGROUP_TYPE_NAMELEN.
+
+- early_init: indicate if the subsystem needs early initialization
+  at system boot.
+
+Each cgroup object created by the system has an array of pointers,
+indexed by subsystem ID; this pointer is entirely managed by the
+subsystem; the generic cgroup code will never touch this pointer.
+
+3.2 Synchronization
+-------------------
+
+There is a global mutex, cgroup_mutex, used by the cgroup
+system. This should be taken by anything that wants to modify a
+cgroup. It may also be taken to prevent cgroups from being
+modified, but more specific locks may be more appropriate in that
+situation.
+
+See kernel/cgroup.c for more details.
+
+Subsystems can take/release the cgroup_mutex via the functions
+cgroup_lock()/cgroup_unlock().
+
+Accessing a task's cgroup pointer may be done in the following ways:
+- while holding cgroup_mutex
+- while holding the task's alloc_lock (via task_lock())
+- inside an rcu_read_lock() section via rcu_dereference()
+
+3.3 Subsystem API
+-----------------
+
+Each subsystem should:
+
+- add an entry in linux/cgroup_subsys.h
+- define a cgroup_subsys object called <name>_subsys
+
+If a subsystem can be compiled as a module, it should also have in its
+module initcall a call to cgroup_load_subsys(), and in its exitcall a
+call to cgroup_unload_subsys(). It should also set its_subsys.module =
+THIS_MODULE in its .c file.
+
+Each subsystem may export the following methods. The only mandatory
+methods are css_alloc/free. Any others that are null are presumed to
+be successful no-ops.
+
+struct cgroup_subsys_state *css_alloc(struct cgroup *cgrp)
+(cgroup_mutex held by caller)
+
+Called to allocate a subsystem state object for a cgroup. The
+subsystem should allocate its subsystem state object for the passed
+cgroup, returning a pointer to the new object on success or a
+ERR_PTR() value. On success, the subsystem pointer should point to
+a structure of type cgroup_subsys_state (typically embedded in a
+larger subsystem-specific object), which will be initialized by the
+cgroup system. Note that this will be called at initialization to
+create the root subsystem state for this subsystem; this case can be
+identified by the passed cgroup object having a NULL parent (since
+it's the root of the hierarchy) and may be an appropriate place for
+initialization code.
+
+int css_online(struct cgroup *cgrp)
+(cgroup_mutex held by caller)
+
+Called after @cgrp successfully completed all allocations and made
+visible to cgroup_for_each_child/descendant_*() iterators. The
+subsystem may choose to fail creation by returning -errno. This
+callback can be used to implement reliable state sharing and
+propagation along the hierarchy. See the comment on
+cgroup_for_each_descendant_pre() for details.
+
+void css_offline(struct cgroup *cgrp);
+(cgroup_mutex held by caller)
+
+This is the counterpart of css_online() and called iff css_online()
+has succeeded on @cgrp. This signifies the beginning of the end of
+@cgrp. @cgrp is being removed and the subsystem should start dropping
+all references it's holding on @cgrp. When all references are dropped,
+cgroup removal will proceed to the next step - css_free(). After this
+callback, @cgrp should be considered dead to the subsystem.
+
+void css_free(struct cgroup *cgrp)
+(cgroup_mutex held by caller)
+
+The cgroup system is about to free @cgrp; the subsystem should free
+its subsystem state object. By the time this method is called, @cgrp
+is completely unused; @cgrp->parent is still valid. (Note - can also
+be called for a newly-created cgroup if an error occurs after this
+subsystem's create() method has been called for the new cgroup).
+
+int can_attach(struct cgroup *cgrp, struct cgroup_taskset *tset)
+(cgroup_mutex held by caller)
+
+Called prior to moving one or more tasks into a cgroup; if the
+subsystem returns an error, this will abort the attach operation.
+@tset contains the tasks to be attached and is guaranteed to have at
+least one task in it.
+
+If there are multiple tasks in the taskset, then:
+  - it's guaranteed that all are from the same thread group
+  - @tset contains all tasks from the thread group whether or not
+    they're switching cgroups
+  - the first task is the leader
+
+Each @tset entry also contains the task's old cgroup and tasks which
+aren't switching cgroup can be skipped easily using the
+cgroup_taskset_for_each() iterator. Note that this isn't called on a
+fork. If this method returns 0 (success) then this should remain valid
+while the caller holds cgroup_mutex and it is ensured that either
+attach() or cancel_attach() will be called in future.
+
+void css_reset(struct cgroup_subsys_state *css)
+(cgroup_mutex held by caller)
+
+An optional operation which should restore @css's configuration to the
+initial state.  This is currently only used on the unified hierarchy
+when a subsystem is disabled on a cgroup through
+"cgroup.subtree_control" but should remain enabled because other
+subsystems depend on it.  cgroup core makes such a css invisible by
+removing the associated interface files and invokes this callback so
+that the hidden subsystem can return to the initial neutral state.
+This prevents unexpected resource control from a hidden css and
+ensures that the configuration is in the initial state when it is made
+visible again later.
+
+void cancel_attach(struct cgroup *cgrp, struct cgroup_taskset *tset)
+(cgroup_mutex held by caller)
+
+Called when a task attach operation has failed after can_attach() has succeeded.
+A subsystem whose can_attach() has some side-effects should provide this
+function, so that the subsystem can implement a rollback. If not, not necessary.
+This will be called only about subsystems whose can_attach() operation have
+succeeded. The parameters are identical to can_attach().
+
+void attach(struct cgroup *cgrp, struct cgroup_taskset *tset)
+(cgroup_mutex held by caller)
+
+Called after the task has been attached to the cgroup, to allow any
+post-attachment activity that requires memory allocations or blocking.
+The parameters are identical to can_attach().
+
+void fork(struct task_struct *task)
+
+Called when a task is forked into a cgroup.
+
+void exit(struct task_struct *task)
+
+Called during task exit.
+
+void free(struct task_struct *task)
+
+Called when the task_struct is freed.
+
+void bind(struct cgroup *root)
+(cgroup_mutex held by caller)
+
+Called when a cgroup subsystem is rebound to a different hierarchy
+and root cgroup. Currently this will only involve movement between
+the default hierarchy (which never has sub-cgroups) and a hierarchy
+that is being created/destroyed (and hence has no sub-cgroups).
+
+4. Extended attribute usage
+===========================
+
+cgroup filesystem supports certain types of extended attributes in its
+directories and files.  The current supported types are:
+       - Trusted (XATTR_TRUSTED)
+       - Security (XATTR_SECURITY)
+
+Both require CAP_SYS_ADMIN capability to set.
+
+Like in tmpfs, the extended attributes in cgroup filesystem are stored
+using kernel memory and it's advised to keep the usage at minimum.  This
+is the reason why user defined extended attributes are not supported, since
+any user can do it and there's no limit in the value size.
+
+The current known users for this feature are SELinux to limit cgroup usage
+in containers and systemd for assorted meta data like main PID in a cgroup
+(systemd creates a cgroup per service).
+
+5. Questions
+============
+
+Q: what's up with this '/bin/echo' ?
+A: bash's builtin 'echo' command does not check calls to write() against
+   errors. If you use it in the cgroup file system, you won't be
+   able to tell whether a command succeeded or failed.
+
+Q: When I attach processes, only the first of the line gets really attached !
+A: We can only return one error code per call to write(). So you should also
+   put only ONE PID.
+
diff --git a/Documentation/cgroup-v1/cpuacct.txt b/Documentation/cgroup-v1/cpuacct.txt
new file mode 100644 (file)
index 0000000..9d73cc0
--- /dev/null
@@ -0,0 +1,49 @@
+CPU Accounting Controller
+-------------------------
+
+The CPU accounting controller is used to group tasks using cgroups and
+account the CPU usage of these groups of tasks.
+
+The CPU accounting controller supports multi-hierarchy groups. An accounting
+group accumulates the CPU usage of all of its child groups and the tasks
+directly present in its group.
+
+Accounting groups can be created by first mounting the cgroup filesystem.
+
+# mount -t cgroup -ocpuacct none /sys/fs/cgroup
+
+With the above step, the initial or the parent accounting group becomes
+visible at /sys/fs/cgroup. At bootup, this group includes all the tasks in
+the system. /sys/fs/cgroup/tasks lists the tasks in this cgroup.
+/sys/fs/cgroup/cpuacct.usage gives the CPU time (in nanoseconds) obtained
+by this group which is essentially the CPU time obtained by all the tasks
+in the system.
+
+New accounting groups can be created under the parent group /sys/fs/cgroup.
+
+# cd /sys/fs/cgroup
+# mkdir g1
+# echo $$ > g1/tasks
+
+The above steps create a new group g1 and move the current shell
+process (bash) into it. CPU time consumed by this bash and its children
+can be obtained from g1/cpuacct.usage and the same is accumulated in
+/sys/fs/cgroup/cpuacct.usage also.
+
+cpuacct.stat file lists a few statistics which further divide the
+CPU time obtained by the cgroup into user and system times. Currently
+the following statistics are supported:
+
+user: Time spent by tasks of the cgroup in user mode.
+system: Time spent by tasks of the cgroup in kernel mode.
+
+user and system are in USER_HZ unit.
+
+cpuacct controller uses percpu_counter interface to collect user and
+system times. This has two side effects:
+
+- It is theoretically possible to see wrong values for user and system times.
+  This is because percpu_counter_read() on 32bit systems isn't safe
+  against concurrent writes.
+- It is possible to see slightly outdated values for user and system times
+  due to the batch processing nature of percpu_counter.
diff --git a/Documentation/cgroup-v1/cpusets.txt b/Documentation/cgroup-v1/cpusets.txt
new file mode 100644 (file)
index 0000000..fdf7dff
--- /dev/null
@@ -0,0 +1,839 @@
+                               CPUSETS
+                               -------
+
+Copyright (C) 2004 BULL SA.
+Written by Simon.Derr@bull.net
+
+Portions Copyright (c) 2004-2006 Silicon Graphics, Inc.
+Modified by Paul Jackson <pj@sgi.com>
+Modified by Christoph Lameter <clameter@sgi.com>
+Modified by Paul Menage <menage@google.com>
+Modified by Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
+
+CONTENTS:
+=========
+
+1. Cpusets
+  1.1 What are cpusets ?
+  1.2 Why are cpusets needed ?
+  1.3 How are cpusets implemented ?
+  1.4 What are exclusive cpusets ?
+  1.5 What is memory_pressure ?
+  1.6 What is memory spread ?
+  1.7 What is sched_load_balance ?
+  1.8 What is sched_relax_domain_level ?
+  1.9 How do I use cpusets ?
+2. Usage Examples and Syntax
+  2.1 Basic Usage
+  2.2 Adding/removing cpus
+  2.3 Setting flags
+  2.4 Attaching processes
+3. Questions
+4. Contact
+
+1. Cpusets
+==========
+
+1.1 What are cpusets ?
+----------------------
+
+Cpusets provide a mechanism for assigning a set of CPUs and Memory
+Nodes to a set of tasks.   In this document "Memory Node" refers to
+an on-line node that contains memory.
+
+Cpusets constrain the CPU and Memory placement of tasks to only
+the resources within a task's current cpuset.  They form a nested
+hierarchy visible in a virtual file system.  These are the essential
+hooks, beyond what is already present, required to manage dynamic
+job placement on large systems.
+
+Cpusets use the generic cgroup subsystem described in
+Documentation/cgroups/cgroups.txt.
+
+Requests by a task, using the sched_setaffinity(2) system call to
+include CPUs in its CPU affinity mask, and using the mbind(2) and
+set_mempolicy(2) system calls to include Memory Nodes in its memory
+policy, are both filtered through that task's cpuset, filtering out any
+CPUs or Memory Nodes not in that cpuset.  The scheduler will not
+schedule a task on a CPU that is not allowed in its cpus_allowed
+vector, and the kernel page allocator will not allocate a page on a
+node that is not allowed in the requesting task's mems_allowed vector.
+
+User level code may create and destroy cpusets by name in the cgroup
+virtual file system, manage the attributes and permissions of these
+cpusets and which CPUs and Memory Nodes are assigned to each cpuset,
+specify and query to which cpuset a task is assigned, and list the
+task pids assigned to a cpuset.
+
+
+1.2 Why are cpusets needed ?
+----------------------------
+
+The management of large computer systems, with many processors (CPUs),
+complex memory cache hierarchies and multiple Memory Nodes having
+non-uniform access times (NUMA) presents additional challenges for
+the efficient scheduling and memory placement of processes.
+
+Frequently more modest sized systems can be operated with adequate
+efficiency just by letting the operating system automatically share
+the available CPU and Memory resources amongst the requesting tasks.
+
+But larger systems, which benefit more from careful processor and
+memory placement to reduce memory access times and contention,
+and which typically represent a larger investment for the customer,
+can benefit from explicitly placing jobs on properly sized subsets of
+the system.
+
+This can be especially valuable on:
+
+    * Web Servers running multiple instances of the same web application,
+    * Servers running different applications (for instance, a web server
+      and a database), or
+    * NUMA systems running large HPC applications with demanding
+      performance characteristics.
+
+These subsets, or "soft partitions" must be able to be dynamically
+adjusted, as the job mix changes, without impacting other concurrently
+executing jobs. The location of the running jobs pages may also be moved
+when the memory locations are changed.
+
+The kernel cpuset patch provides the minimum essential kernel
+mechanisms required to efficiently implement such subsets.  It
+leverages existing CPU and Memory Placement facilities in the Linux
+kernel to avoid any additional impact on the critical scheduler or
+memory allocator code.
+
+
+1.3 How are cpusets implemented ?
+---------------------------------
+
+Cpusets provide a Linux kernel mechanism to constrain which CPUs and
+Memory Nodes are used by a process or set of processes.
+
+The Linux kernel already has a pair of mechanisms to specify on which
+CPUs a task may be scheduled (sched_setaffinity) and on which Memory
+Nodes it may obtain memory (mbind, set_mempolicy).
+
+Cpusets extends these two mechanisms as follows:
+
+ - Cpusets are sets of allowed CPUs and Memory Nodes, known to the
+   kernel.
+ - Each task in the system is attached to a cpuset, via a pointer
+   in the task structure to a reference counted cgroup structure.
+ - Calls to sched_setaffinity are filtered to just those CPUs
+   allowed in that task's cpuset.
+ - Calls to mbind and set_mempolicy are filtered to just
+   those Memory Nodes allowed in that task's cpuset.
+ - The root cpuset contains all the systems CPUs and Memory
+   Nodes.
+ - For any cpuset, one can define child cpusets containing a subset
+   of the parents CPU and Memory Node resources.
+ - The hierarchy of cpusets can be mounted at /dev/cpuset, for
+   browsing and manipulation from user space.
+ - A cpuset may be marked exclusive, which ensures that no other
+   cpuset (except direct ancestors and descendants) may contain
+   any overlapping CPUs or Memory Nodes.
+ - You can list all the tasks (by pid) attached to any cpuset.
+
+The implementation of cpusets requires a few, simple hooks
+into the rest of the kernel, none in performance critical paths:
+
+ - in init/main.c, to initialize the root cpuset at system boot.
+ - in fork and exit, to attach and detach a task from its cpuset.
+ - in sched_setaffinity, to mask the requested CPUs by what's
+   allowed in that task's cpuset.
+ - in sched.c migrate_live_tasks(), to keep migrating tasks within
+   the CPUs allowed by their cpuset, if possible.
+ - in the mbind and set_mempolicy system calls, to mask the requested
+   Memory Nodes by what's allowed in that task's cpuset.
+ - in page_alloc.c, to restrict memory to allowed nodes.
+ - in vmscan.c, to restrict page recovery to the current cpuset.
+
+You should mount the "cgroup" filesystem type in order to enable
+browsing and modifying the cpusets presently known to the kernel.  No
+new system calls are added for cpusets - all support for querying and
+modifying cpusets is via this cpuset file system.
+
+The /proc/<pid>/status file for each task has four added lines,
+displaying the task's cpus_allowed (on which CPUs it may be scheduled)
+and mems_allowed (on which Memory Nodes it may obtain memory),
+in the two formats seen in the following example:
+
+  Cpus_allowed:   ffffffff,ffffffff,ffffffff,ffffffff
+  Cpus_allowed_list:      0-127
+  Mems_allowed:   ffffffff,ffffffff
+  Mems_allowed_list:      0-63
+
+Each cpuset is represented by a directory in the cgroup file system
+containing (on top of the standard cgroup files) the following
+files describing that cpuset:
+
+ - cpuset.cpus: list of CPUs in that cpuset
+ - cpuset.mems: list of Memory Nodes in that cpuset
+ - cpuset.memory_migrate flag: if set, move pages to cpusets nodes
+ - cpuset.cpu_exclusive flag: is cpu placement exclusive?
+ - cpuset.mem_exclusive flag: is memory placement exclusive?
+ - cpuset.mem_hardwall flag:  is memory allocation hardwalled
+ - cpuset.memory_pressure: measure of how much paging pressure in cpuset
+ - cpuset.memory_spread_page flag: if set, spread page cache evenly on allowed nodes
+ - cpuset.memory_spread_slab flag: if set, spread slab cache evenly on allowed nodes
+ - cpuset.sched_load_balance flag: if set, load balance within CPUs on that cpuset
+ - cpuset.sched_relax_domain_level: the searching range when migrating tasks
+
+In addition, only the root cpuset has the following file:
+ - cpuset.memory_pressure_enabled flag: compute memory_pressure?
+
+New cpusets are created using the mkdir system call or shell
+command.  The properties of a cpuset, such as its flags, allowed
+CPUs and Memory Nodes, and attached tasks, are modified by writing
+to the appropriate file in that cpusets directory, as listed above.
+
+The named hierarchical structure of nested cpusets allows partitioning
+a large system into nested, dynamically changeable, "soft-partitions".
+
+The attachment of each task, automatically inherited at fork by any
+children of that task, to a cpuset allows organizing the work load
+on a system into related sets of tasks such that each set is constrained
+to using the CPUs and Memory Nodes of a particular cpuset.  A task
+may be re-attached to any other cpuset, if allowed by the permissions
+on the necessary cpuset file system directories.
+
+Such management of a system "in the large" integrates smoothly with
+the detailed placement done on individual tasks and memory regions
+using the sched_setaffinity, mbind and set_mempolicy system calls.
+
+The following rules apply to each cpuset:
+
+ - Its CPUs and Memory Nodes must be a subset of its parents.
+ - It can't be marked exclusive unless its parent is.
+ - If its cpu or memory is exclusive, they may not overlap any sibling.
+
+These rules, and the natural hierarchy of cpusets, enable efficient
+enforcement of the exclusive guarantee, without having to scan all
+cpusets every time any of them change to ensure nothing overlaps a
+exclusive cpuset.  Also, the use of a Linux virtual file system (vfs)
+to represent the cpuset hierarchy provides for a familiar permission
+and name space for cpusets, with a minimum of additional kernel code.
+
+The cpus and mems files in the root (top_cpuset) cpuset are
+read-only.  The cpus file automatically tracks the value of
+cpu_online_mask using a CPU hotplug notifier, and the mems file
+automatically tracks the value of node_states[N_MEMORY]--i.e.,
+nodes with memory--using the cpuset_track_online_nodes() hook.
+
+
+1.4 What are exclusive cpusets ?
+--------------------------------
+
+If a cpuset is cpu or mem exclusive, no other cpuset, other than
+a direct ancestor or descendant, may share any of the same CPUs or
+Memory Nodes.
+
+A cpuset that is cpuset.mem_exclusive *or* cpuset.mem_hardwall is "hardwalled",
+i.e. it restricts kernel allocations for page, buffer and other data
+commonly shared by the kernel across multiple users.  All cpusets,
+whether hardwalled or not, restrict allocations of memory for user
+space.  This enables configuring a system so that several independent
+jobs can share common kernel data, such as file system pages, while
+isolating each job's user allocation in its own cpuset.  To do this,
+construct a large mem_exclusive cpuset to hold all the jobs, and
+construct child, non-mem_exclusive cpusets for each individual job.
+Only a small amount of typical kernel memory, such as requests from
+interrupt handlers, is allowed to be taken outside even a
+mem_exclusive cpuset.
+
+
+1.5 What is memory_pressure ?
+-----------------------------
+The memory_pressure of a cpuset provides a simple per-cpuset metric
+of the rate that the tasks in a cpuset are attempting to free up in
+use memory on the nodes of the cpuset to satisfy additional memory
+requests.
+
+This enables batch managers monitoring jobs running in dedicated
+cpusets to efficiently detect what level of memory pressure that job
+is causing.
+
+This is useful both on tightly managed systems running a wide mix of
+submitted jobs, which may choose to terminate or re-prioritize jobs that
+are trying to use more memory than allowed on the nodes assigned to them,
+and with tightly coupled, long running, massively parallel scientific
+computing jobs that will dramatically fail to meet required performance
+goals if they start to use more memory than allowed to them.
+
+This mechanism provides a very economical way for the batch manager
+to monitor a cpuset for signs of memory pressure.  It's up to the
+batch manager or other user code to decide what to do about it and
+take action.
+
+==> Unless this feature is enabled by writing "1" to the special file
+    /dev/cpuset/memory_pressure_enabled, the hook in the rebalance
+    code of __alloc_pages() for this metric reduces to simply noticing
+    that the cpuset_memory_pressure_enabled flag is zero.  So only
+    systems that enable this feature will compute the metric.
+
+Why a per-cpuset, running average:
+
+    Because this meter is per-cpuset, rather than per-task or mm,
+    the system load imposed by a batch scheduler monitoring this
+    metric is sharply reduced on large systems, because a scan of
+    the tasklist can be avoided on each set of queries.
+
+    Because this meter is a running average, instead of an accumulating
+    counter, a batch scheduler can detect memory pressure with a
+    single read, instead of having to read and accumulate results
+    for a period of time.
+
+    Because this meter is per-cpuset rather than per-task or mm,
+    the batch scheduler can obtain the key information, memory
+    pressure in a cpuset, with a single read, rather than having to
+    query and accumulate results over all the (dynamically changing)
+    set of tasks in the cpuset.
+
+A per-cpuset simple digital filter (requires a spinlock and 3 words
+of data per-cpuset) is kept, and updated by any task attached to that
+cpuset, if it enters the synchronous (direct) page reclaim code.
+
+A per-cpuset file provides an integer number representing the recent
+(half-life of 10 seconds) rate of direct page reclaims caused by
+the tasks in the cpuset, in units of reclaims attempted per second,
+times 1000.
+
+
+1.6 What is memory spread ?
+---------------------------
+There are two boolean flag files per cpuset that control where the
+kernel allocates pages for the file system buffers and related in
+kernel data structures.  They are called 'cpuset.memory_spread_page' and
+'cpuset.memory_spread_slab'.
+
+If the per-cpuset boolean flag file 'cpuset.memory_spread_page' is set, then
+the kernel will spread the file system buffers (page cache) evenly
+over all the nodes that the faulting task is allowed to use, instead
+of preferring to put those pages on the node where the task is running.
+
+If the per-cpuset boolean flag file 'cpuset.memory_spread_slab' is set,
+then the kernel will spread some file system related slab caches,
+such as for inodes and dentries evenly over all the nodes that the
+faulting task is allowed to use, instead of preferring to put those
+pages on the node where the task is running.
+
+The setting of these flags does not affect anonymous data segment or
+stack segment pages of a task.
+
+By default, both kinds of memory spreading are off, and memory
+pages are allocated on the node local to where the task is running,
+except perhaps as modified by the task's NUMA mempolicy or cpuset
+configuration, so long as sufficient free memory pages are available.
+
+When new cpusets are created, they inherit the memory spread settings
+of their parent.
+
+Setting memory spreading causes allocations for the affected page
+or slab caches to ignore the task's NUMA mempolicy and be spread
+instead.    Tasks using mbind() or set_mempolicy() calls to set NUMA
+mempolicies will not notice any change in these calls as a result of
+their containing task's memory spread settings.  If memory spreading
+is turned off, then the currently specified NUMA mempolicy once again
+applies to memory page allocations.
+
+Both 'cpuset.memory_spread_page' and 'cpuset.memory_spread_slab' are boolean flag
+files.  By default they contain "0", meaning that the feature is off
+for that cpuset.  If a "1" is written to that file, then that turns
+the named feature on.
+
+The implementation is simple.
+
+Setting the flag 'cpuset.memory_spread_page' turns on a per-process flag
+PFA_SPREAD_PAGE for each task that is in that cpuset or subsequently
+joins that cpuset.  The page allocation calls for the page cache
+is modified to perform an inline check for this PFA_SPREAD_PAGE task
+flag, and if set, a call to a new routine cpuset_mem_spread_node()
+returns the node to prefer for the allocation.
+
+Similarly, setting 'cpuset.memory_spread_slab' turns on the flag
+PFA_SPREAD_SLAB, and appropriately marked slab caches will allocate
+pages from the node returned by cpuset_mem_spread_node().
+
+The cpuset_mem_spread_node() routine is also simple.  It uses the
+value of a per-task rotor cpuset_mem_spread_rotor to select the next
+node in the current task's mems_allowed to prefer for the allocation.
+
+This memory placement policy is also known (in other contexts) as
+round-robin or interleave.
+
+This policy can provide substantial improvements for jobs that need
+to place thread local data on the corresponding node, but that need
+to access large file system data sets that need to be spread across
+the several nodes in the jobs cpuset in order to fit.  Without this
+policy, especially for jobs that might have one thread reading in the
+data set, the memory allocation across the nodes in the jobs cpuset
+can become very uneven.
+
+1.7 What is sched_load_balance ?
+--------------------------------
+
+The kernel scheduler (kernel/sched/core.c) automatically load balances
+tasks.  If one CPU is underutilized, kernel code running on that
+CPU will look for tasks on other more overloaded CPUs and move those
+tasks to itself, within the constraints of such placement mechanisms
+as cpusets and sched_setaffinity.
+
+The algorithmic cost of load balancing and its impact on key shared
+kernel data structures such as the task list increases more than
+linearly with the number of CPUs being balanced.  So the scheduler
+has support to partition the systems CPUs into a number of sched
+domains such that it only load balances within each sched domain.
+Each sched domain covers some subset of the CPUs in the system;
+no two sched domains overlap; some CPUs might not be in any sched
+domain and hence won't be load balanced.
+
+Put simply, it costs less to balance between two smaller sched domains
+than one big one, but doing so means that overloads in one of the
+two domains won't be load balanced to the other one.
+
+By default, there is one sched domain covering all CPUs, including those
+marked isolated using the kernel boot time "isolcpus=" argument. However,
+the isolated CPUs will not participate in load balancing, and will not
+have tasks running on them unless explicitly assigned.
+
+This default load balancing across all CPUs is not well suited for
+the following two situations:
+ 1) On large systems, load balancing across many CPUs is expensive.
+    If the system is managed using cpusets to place independent jobs
+    on separate sets of CPUs, full load balancing is unnecessary.
+ 2) Systems supporting realtime on some CPUs need to minimize
+    system overhead on those CPUs, including avoiding task load
+    balancing if that is not needed.
+
+When the per-cpuset flag "cpuset.sched_load_balance" is enabled (the default
+setting), it requests that all the CPUs in that cpusets allowed 'cpuset.cpus'
+be contained in a single sched domain, ensuring that load balancing
+can move a task (not otherwised pinned, as by sched_setaffinity)
+from any CPU in that cpuset to any other.
+
+When the per-cpuset flag "cpuset.sched_load_balance" is disabled, then the
+scheduler will avoid load balancing across the CPUs in that cpuset,
+--except-- in so far as is necessary because some overlapping cpuset
+has "sched_load_balance" enabled.
+
+So, for example, if the top cpuset has the flag "cpuset.sched_load_balance"
+enabled, then the scheduler will have one sched domain covering all
+CPUs, and the setting of the "cpuset.sched_load_balance" flag in any other
+cpusets won't matter, as we're already fully load balancing.
+
+Therefore in the above two situations, the top cpuset flag
+"cpuset.sched_load_balance" should be disabled, and only some of the smaller,
+child cpusets have this flag enabled.
+
+When doing this, you don't usually want to leave any unpinned tasks in
+the top cpuset that might use non-trivial amounts of CPU, as such tasks
+may be artificially constrained to some subset of CPUs, depending on
+the particulars of this flag setting in descendant cpusets.  Even if
+such a task could use spare CPU cycles in some other CPUs, the kernel
+scheduler might not consider the possibility of load balancing that
+task to that underused CPU.
+
+Of course, tasks pinned to a particular CPU can be left in a cpuset
+that disables "cpuset.sched_load_balance" as those tasks aren't going anywhere
+else anyway.
+
+There is an impedance mismatch here, between cpusets and sched domains.
+Cpusets are hierarchical and nest.  Sched domains are flat; they don't
+overlap and each CPU is in at most one sched domain.
+
+It is necessary for sched domains to be flat because load balancing
+across partially overlapping sets of CPUs would risk unstable dynamics
+that would be beyond our understanding.  So if each of two partially
+overlapping cpusets enables the flag 'cpuset.sched_load_balance', then we
+form a single sched domain that is a superset of both.  We won't move
+a task to a CPU outside its cpuset, but the scheduler load balancing
+code might waste some compute cycles considering that possibility.
+
+This mismatch is why there is not a simple one-to-one relation
+between which cpusets have the flag "cpuset.sched_load_balance" enabled,
+and the sched domain configuration.  If a cpuset enables the flag, it
+will get balancing across all its CPUs, but if it disables the flag,
+it will only be assured of no load balancing if no other overlapping
+cpuset enables the flag.
+
+If two cpusets have partially overlapping 'cpuset.cpus' allowed, and only
+one of them has this flag enabled, then the other may find its
+tasks only partially load balanced, just on the overlapping CPUs.
+This is just the general case of the top_cpuset example given a few
+paragraphs above.  In the general case, as in the top cpuset case,
+don't leave tasks that might use non-trivial amounts of CPU in
+such partially load balanced cpusets, as they may be artificially
+constrained to some subset of the CPUs allowed to them, for lack of
+load balancing to the other CPUs.
+
+CPUs in "cpuset.isolcpus" were excluded from load balancing by the
+isolcpus= kernel boot option, and will never be load balanced regardless
+of the value of "cpuset.sched_load_balance" in any cpuset.
+
+1.7.1 sched_load_balance implementation details.
+------------------------------------------------
+
+The per-cpuset flag 'cpuset.sched_load_balance' defaults to enabled (contrary
+to most cpuset flags.)  When enabled for a cpuset, the kernel will
+ensure that it can load balance across all the CPUs in that cpuset
+(makes sure that all the CPUs in the cpus_allowed of that cpuset are
+in the same sched domain.)
+
+If two overlapping cpusets both have 'cpuset.sched_load_balance' enabled,
+then they will be (must be) both in the same sched domain.
+
+If, as is the default, the top cpuset has 'cpuset.sched_load_balance' enabled,
+then by the above that means there is a single sched domain covering
+the whole system, regardless of any other cpuset settings.
+
+The kernel commits to user space that it will avoid load balancing
+where it can.  It will pick as fine a granularity partition of sched
+domains as it can while still providing load balancing for any set
+of CPUs allowed to a cpuset having 'cpuset.sched_load_balance' enabled.
+
+The internal kernel cpuset to scheduler interface passes from the
+cpuset code to the scheduler code a partition of the load balanced
+CPUs in the system. This partition is a set of subsets (represented
+as an array of struct cpumask) of CPUs, pairwise disjoint, that cover
+all the CPUs that must be load balanced.
+
+The cpuset code builds a new such partition and passes it to the
+scheduler sched domain setup code, to have the sched domains rebuilt
+as necessary, whenever:
+ - the 'cpuset.sched_load_balance' flag of a cpuset with non-empty CPUs changes,
+ - or CPUs come or go from a cpuset with this flag enabled,
+ - or 'cpuset.sched_relax_domain_level' value of a cpuset with non-empty CPUs
+   and with this flag enabled changes,
+ - or a cpuset with non-empty CPUs and with this flag enabled is removed,
+ - or a cpu is offlined/onlined.
+
+This partition exactly defines what sched domains the scheduler should
+setup - one sched domain for each element (struct cpumask) in the
+partition.
+
+The scheduler remembers the currently active sched domain partitions.
+When the scheduler routine partition_sched_domains() is invoked from
+the cpuset code to update these sched domains, it compares the new
+partition requested with the current, and updates its sched domains,
+removing the old and adding the new, for each change.
+
+
+1.8 What is sched_relax_domain_level ?
+--------------------------------------
+
+In sched domain, the scheduler migrates tasks in 2 ways; periodic load
+balance on tick, and at time of some schedule events.
+
+When a task is woken up, scheduler try to move the task on idle CPU.
+For example, if a task A running on CPU X activates another task B
+on the same CPU X, and if CPU Y is X's sibling and performing idle,
+then scheduler migrate task B to CPU Y so that task B can start on
+CPU Y without waiting task A on CPU X.
+
+And if a CPU run out of tasks in its runqueue, the CPU try to pull
+extra tasks from other busy CPUs to help them before it is going to
+be idle.
+
+Of course it takes some searching cost to find movable tasks and/or
+idle CPUs, the scheduler might not search all CPUs in the domain
+every time.  In fact, in some architectures, the searching ranges on
+events are limited in the same socket or node where the CPU locates,
+while the load balance on tick searches all.
+
+For example, assume CPU Z is relatively far from CPU X.  Even if CPU Z
+is idle while CPU X and the siblings are busy, scheduler can't migrate
+woken task B from X to Z since it is out of its searching range.
+As the result, task B on CPU X need to wait task A or wait load balance
+on the next tick.  For some applications in special situation, waiting
+1 tick may be too long.
+
+The 'cpuset.sched_relax_domain_level' file allows you to request changing
+this searching range as you like.  This file takes int value which
+indicates size of searching range in levels ideally as follows,
+otherwise initial value -1 that indicates the cpuset has no request.
+
+  -1  : no request. use system default or follow request of others.
+   0  : no search.
+   1  : search siblings (hyperthreads in a core).
+   2  : search cores in a package.
+   3  : search cpus in a node [= system wide on non-NUMA system]
+   4  : search nodes in a chunk of node [on NUMA system]
+   5  : search system wide [on NUMA system]
+
+The system default is architecture dependent.  The system default
+can be changed using the relax_domain_level= boot parameter.
+
+This file is per-cpuset and affect the sched domain where the cpuset
+belongs to.  Therefore if the flag 'cpuset.sched_load_balance' of a cpuset
+is disabled, then 'cpuset.sched_relax_domain_level' have no effect since
+there is no sched domain belonging the cpuset.
+
+If multiple cpusets are overlapping and hence they form a single sched
+domain, the largest value among those is used.  Be careful, if one
+requests 0 and others are -1 then 0 is used.
+
+Note that modifying this file will have both good and bad effects,
+and whether it is acceptable or not depends on your situation.
+Don't modify this file if you are not sure.
+
+If your situation is:
+ - The migration costs between each cpu can be assumed considerably
+   small(for you) due to your special application's behavior or
+   special hardware support for CPU cache etc.
+ - The searching cost doesn't have impact(for you) or you can make
+   the searching cost enough small by managing cpuset to compact etc.
+ - The latency is required even it sacrifices cache hit rate etc.
+then increasing 'sched_relax_domain_level' would benefit you.
+
+
+1.9 How do I use cpusets ?
+--------------------------
+
+In order to minimize the impact of cpusets on critical kernel
+code, such as the scheduler, and due to the fact that the kernel
+does not support one task updating the memory placement of another
+task directly, the impact on a task of changing its cpuset CPU
+or Memory Node placement, or of changing to which cpuset a task
+is attached, is subtle.
+
+If a cpuset has its Memory Nodes modified, then for each task attached
+to that cpuset, the next time that the kernel attempts to allocate
+a page of memory for that task, the kernel will notice the change
+in the task's cpuset, and update its per-task memory placement to
+remain within the new cpusets memory placement.  If the task was using
+mempolicy MPOL_BIND, and the nodes to which it was bound overlap with
+its new cpuset, then the task will continue to use whatever subset
+of MPOL_BIND nodes are still allowed in the new cpuset.  If the task
+was using MPOL_BIND and now none of its MPOL_BIND nodes are allowed
+in the new cpuset, then the task will be essentially treated as if it
+was MPOL_BIND bound to the new cpuset (even though its NUMA placement,
+as queried by get_mempolicy(), doesn't change).  If a task is moved
+from one cpuset to another, then the kernel will adjust the task's
+memory placement, as above, the next time that the kernel attempts
+to allocate a page of memory for that task.
+
+If a cpuset has its 'cpuset.cpus' modified, then each task in that cpuset
+will have its allowed CPU placement changed immediately.  Similarly,
+if a task's pid is written to another cpusets 'cpuset.tasks' file, then its
+allowed CPU placement is changed immediately.  If such a task had been
+bound to some subset of its cpuset using the sched_setaffinity() call,
+the task will be allowed to run on any CPU allowed in its new cpuset,
+negating the effect of the prior sched_setaffinity() call.
+
+In summary, the memory placement of a task whose cpuset is changed is
+updated by the kernel, on the next allocation of a page for that task,
+and the processor placement is updated immediately.
+
+Normally, once a page is allocated (given a physical page
+of main memory) then that page stays on whatever node it
+was allocated, so long as it remains allocated, even if the
+cpusets memory placement policy 'cpuset.mems' subsequently changes.
+If the cpuset flag file 'cpuset.memory_migrate' is set true, then when
+tasks are attached to that cpuset, any pages that task had
+allocated to it on nodes in its previous cpuset are migrated
+to the task's new cpuset. The relative placement of the page within
+the cpuset is preserved during these migration operations if possible.
+For example if the page was on the second valid node of the prior cpuset
+then the page will be placed on the second valid node of the new cpuset.
+
+Also if 'cpuset.memory_migrate' is set true, then if that cpuset's
+'cpuset.mems' file is modified, pages allocated to tasks in that
+cpuset, that were on nodes in the previous setting of 'cpuset.mems',
+will be moved to nodes in the new setting of 'mems.'
+Pages that were not in the task's prior cpuset, or in the cpuset's
+prior 'cpuset.mems' setting, will not be moved.
+
+There is an exception to the above.  If hotplug functionality is used
+to remove all the CPUs that are currently assigned to a cpuset,
+then all the tasks in that cpuset will be moved to the nearest ancestor
+with non-empty cpus.  But the moving of some (or all) tasks might fail if
+cpuset is bound with another cgroup subsystem which has some restrictions
+on task attaching.  In this failing case, those tasks will stay
+in the original cpuset, and the kernel will automatically update
+their cpus_allowed to allow all online CPUs.  When memory hotplug
+functionality for removing Memory Nodes is available, a similar exception
+is expected to apply there as well.  In general, the kernel prefers to
+violate cpuset placement, over starving a task that has had all
+its allowed CPUs or Memory Nodes taken offline.
+
+There is a second exception to the above.  GFP_ATOMIC requests are
+kernel internal allocations that must be satisfied, immediately.
+The kernel may drop some request, in rare cases even panic, if a
+GFP_ATOMIC alloc fails.  If the request cannot be satisfied within
+the current task's cpuset, then we relax the cpuset, and look for
+memory anywhere we can find it.  It's better to violate the cpuset
+than stress the kernel.
+
+To start a new job that is to be contained within a cpuset, the steps are:
+
+ 1) mkdir /sys/fs/cgroup/cpuset
+ 2) mount -t cgroup -ocpuset cpuset /sys/fs/cgroup/cpuset
+ 3) Create the new cpuset by doing mkdir's and write's (or echo's) in
+    the /sys/fs/cgroup/cpuset virtual file system.
+ 4) Start a task that will be the "founding father" of the new job.
+ 5) Attach that task to the new cpuset by writing its pid to the
+    /sys/fs/cgroup/cpuset tasks file for that cpuset.
+ 6) fork, exec or clone the job tasks from this founding father task.
+
+For example, the following sequence of commands will setup a cpuset
+named "Charlie", containing just CPUs 2 and 3, and Memory Node 1,
+and then start a subshell 'sh' in that cpuset:
+
+  mount -t cgroup -ocpuset cpuset /sys/fs/cgroup/cpuset
+  cd /sys/fs/cgroup/cpuset
+  mkdir Charlie
+  cd Charlie
+  /bin/echo 2-3 > cpuset.cpus
+  /bin/echo 1 > cpuset.mems
+  /bin/echo $$ > tasks
+  sh
+  # The subshell 'sh' is now running in cpuset Charlie
+  # The next line should display '/Charlie'
+  cat /proc/self/cpuset
+
+There are ways to query or modify cpusets:
+ - via the cpuset file system directly, using the various cd, mkdir, echo,
+   cat, rmdir commands from the shell, or their equivalent from C.
+ - via the C library libcpuset.
+ - via the C library libcgroup.
+   (http://sourceforge.net/projects/libcg/)
+ - via the python application cset.
+   (http://code.google.com/p/cpuset/)
+
+The sched_setaffinity calls can also be done at the shell prompt using
+SGI's runon or Robert Love's taskset.  The mbind and set_mempolicy
+calls can be done at the shell prompt using the numactl command
+(part of Andi Kleen's numa package).
+
+2. Usage Examples and Syntax
+============================
+
+2.1 Basic Usage
+---------------
+
+Creating, modifying, using the cpusets can be done through the cpuset
+virtual filesystem.
+
+To mount it, type:
+# mount -t cgroup -o cpuset cpuset /sys/fs/cgroup/cpuset
+
+Then under /sys/fs/cgroup/cpuset you can find a tree that corresponds to the
+tree of the cpusets in the system. For instance, /sys/fs/cgroup/cpuset
+is the cpuset that holds the whole system.
+
+If you want to create a new cpuset under /sys/fs/cgroup/cpuset:
+# cd /sys/fs/cgroup/cpuset
+# mkdir my_cpuset
+
+Now you want to do something with this cpuset.
+# cd my_cpuset
+
+In this directory you can find several files:
+# ls
+cgroup.clone_children  cpuset.memory_pressure
+cgroup.event_control   cpuset.memory_spread_page
+cgroup.procs           cpuset.memory_spread_slab
+cpuset.cpu_exclusive   cpuset.mems
+cpuset.cpus            cpuset.sched_load_balance
+cpuset.mem_exclusive   cpuset.sched_relax_domain_level
+cpuset.mem_hardwall    notify_on_release
+cpuset.memory_migrate  tasks
+
+Reading them will give you information about the state of this cpuset:
+the CPUs and Memory Nodes it can use, the processes that are using
+it, its properties.  By writing to these files you can manipulate
+the cpuset.
+
+Set some flags:
+# /bin/echo 1 > cpuset.cpu_exclusive
+
+Add some cpus:
+# /bin/echo 0-7 > cpuset.cpus
+
+Add some mems:
+# /bin/echo 0-7 > cpuset.mems
+
+Now attach your shell to this cpuset:
+# /bin/echo $$ > tasks
+
+You can also create cpusets inside your cpuset by using mkdir in this
+directory.
+# mkdir my_sub_cs
+
+To remove a cpuset, just use rmdir:
+# rmdir my_sub_cs
+This will fail if the cpuset is in use (has cpusets inside, or has
+processes attached).
+
+Note that for legacy reasons, the "cpuset" filesystem exists as a
+wrapper around the cgroup filesystem.
+
+The command
+
+mount -t cpuset X /sys/fs/cgroup/cpuset
+
+is equivalent to
+
+mount -t cgroup -ocpuset,noprefix X /sys/fs/cgroup/cpuset
+echo "/sbin/cpuset_release_agent" > /sys/fs/cgroup/cpuset/release_agent
+
+2.2 Adding/removing cpus
+------------------------
+
+This is the syntax to use when writing in the cpus or mems files
+in cpuset directories:
+
+# /bin/echo 1-4 > cpuset.cpus          -> set cpus list to cpus 1,2,3,4
+# /bin/echo 1,2,3,4 > cpuset.cpus      -> set cpus list to cpus 1,2,3,4
+
+To add a CPU to a cpuset, write the new list of CPUs including the
+CPU to be added. To add 6 to the above cpuset:
+
+# /bin/echo 1-4,6 > cpuset.cpus        -> set cpus list to cpus 1,2,3,4,6
+
+Similarly to remove a CPU from a cpuset, write the new list of CPUs
+without the CPU to be removed.
+
+To remove all the CPUs:
+
+# /bin/echo "" > cpuset.cpus           -> clear cpus list
+
+2.3 Setting flags
+-----------------
+
+The syntax is very simple:
+
+# /bin/echo 1 > cpuset.cpu_exclusive   -> set flag 'cpuset.cpu_exclusive'
+# /bin/echo 0 > cpuset.cpu_exclusive   -> unset flag 'cpuset.cpu_exclusive'
+
+2.4 Attaching processes
+-----------------------
+
+# /bin/echo PID > tasks
+
+Note that it is PID, not PIDs. You can only attach ONE task at a time.
+If you have several tasks to attach, you have to do it one after another:
+
+# /bin/echo PID1 > tasks
+# /bin/echo PID2 > tasks
+       ...
+# /bin/echo PIDn > tasks
+
+
+3. Questions
+============
+
+Q: what's up with this '/bin/echo' ?
+A: bash's builtin 'echo' command does not check calls to write() against
+   errors. If you use it in the cpuset file system, you won't be
+   able to tell whether a command succeeded or failed.
+
+Q: When I attach processes, only the first of the line gets really attached !
+A: We can only return one error code per call to write(). So you should also
+   put only ONE pid.
+
+4. Contact
+==========
+
+Web: http://www.bullopensource.org/cpuset
diff --git a/Documentation/cgroup-v1/devices.txt b/Documentation/cgroup-v1/devices.txt
new file mode 100644 (file)
index 0000000..3c1095c
--- /dev/null
@@ -0,0 +1,116 @@
+Device Whitelist Controller
+
+1. Description:
+
+Implement a cgroup to track and enforce open and mknod restrictions
+on device files.  A device cgroup associates a device access
+whitelist with each cgroup.  A whitelist entry has 4 fields.
+'type' is a (all), c (char), or b (block).  'all' means it applies
+to all types and all major and minor numbers.  Major and minor are
+either an integer or * for all.  Access is a composition of r
+(read), w (write), and m (mknod).
+
+The root device cgroup starts with rwm to 'all'.  A child device
+cgroup gets a copy of the parent.  Administrators can then remove
+devices from the whitelist or add new entries.  A child cgroup can
+never receive a device access which is denied by its parent.
+
+2. User Interface
+
+An entry is added using devices.allow, and removed using
+devices.deny.  For instance
+
+       echo 'c 1:3 mr' > /sys/fs/cgroup/1/devices.allow
+
+allows cgroup 1 to read and mknod the device usually known as
+/dev/null.  Doing
+
+       echo a > /sys/fs/cgroup/1/devices.deny
+
+will remove the default 'a *:* rwm' entry. Doing
+
+       echo a > /sys/fs/cgroup/1/devices.allow
+
+will add the 'a *:* rwm' entry to the whitelist.
+
+3. Security
+
+Any task can move itself between cgroups.  This clearly won't
+suffice, but we can decide the best way to adequately restrict
+movement as people get some experience with this.  We may just want
+to require CAP_SYS_ADMIN, which at least is a separate bit from
+CAP_MKNOD.  We may want to just refuse moving to a cgroup which
+isn't a descendant of the current one.  Or we may want to use
+CAP_MAC_ADMIN, since we really are trying to lock down root.
+
+CAP_SYS_ADMIN is needed to modify the whitelist or move another
+task to a new cgroup.  (Again we'll probably want to change that).
+
+A cgroup may not be granted more permissions than the cgroup's
+parent has.
+
+4. Hierarchy
+
+device cgroups maintain hierarchy by making sure a cgroup never has more
+access permissions than its parent.  Every time an entry is written to
+a cgroup's devices.deny file, all its children will have that entry removed
+from their whitelist and all the locally set whitelist entries will be
+re-evaluated.  In case one of the locally set whitelist entries would provide
+more access than the cgroup's parent, it'll be removed from the whitelist.
+
+Example:
+      A
+     / \
+        B
+
+    group        behavior      exceptions
+    A            allow         "b 8:* rwm", "c 116:1 rw"
+    B            deny          "c 1:3 rwm", "c 116:2 rwm", "b 3:* rwm"
+
+If a device is denied in group A:
+       # echo "c 116:* r" > A/devices.deny
+it'll propagate down and after revalidating B's entries, the whitelist entry
+"c 116:2 rwm" will be removed:
+
+    group        whitelist entries                        denied devices
+    A            all                                      "b 8:* rwm", "c 116:* rw"
+    B            "c 1:3 rwm", "b 3:* rwm"                 all the rest
+
+In case parent's exceptions change and local exceptions are not allowed
+anymore, they'll be deleted.
+
+Notice that new whitelist entries will not be propagated:
+      A
+     / \
+        B
+
+    group        whitelist entries                        denied devices
+    A            "c 1:3 rwm", "c 1:5 r"                   all the rest
+    B            "c 1:3 rwm", "c 1:5 r"                   all the rest
+
+when adding "c *:3 rwm":
+       # echo "c *:3 rwm" >A/devices.allow
+
+the result:
+    group        whitelist entries                        denied devices
+    A            "c *:3 rwm", "c 1:5 r"                   all the rest
+    B            "c 1:3 rwm", "c 1:5 r"                   all the rest
+
+but now it'll be possible to add new entries to B:
+       # echo "c 2:3 rwm" >B/devices.allow
+       # echo "c 50:3 r" >B/devices.allow
+or even
+       # echo "c *:3 rwm" >B/devices.allow
+
+Allowing or denying all by writing 'a' to devices.allow or devices.deny will
+not be possible once the device cgroups has children.
+
+4.1 Hierarchy (internal implementation)
+
+device cgroups is implemented internally using a behavior (ALLOW, DENY) and a
+list of exceptions.  The internal state is controlled using the same user
+interface to preserve compatibility with the previous whitelist-only
+implementation.  Removal or addition of exceptions that will reduce the access
+to devices will be propagated down the hierarchy.
+For every propagated exception, the effective rules will be re-evaluated based
+on current parent's access rules.
diff --git a/Documentation/cgroup-v1/freezer-subsystem.txt b/Documentation/cgroup-v1/freezer-subsystem.txt
new file mode 100644 (file)
index 0000000..e831cb2
--- /dev/null
@@ -0,0 +1,123 @@
+The cgroup freezer is useful to batch job management system which start
+and stop sets of tasks in order to schedule the resources of a machine
+according to the desires of a system administrator. This sort of program
+is often used on HPC clusters to schedule access to the cluster as a
+whole. The cgroup freezer uses cgroups to describe the set of tasks to
+be started/stopped by the batch job management system. It also provides
+a means to start and stop the tasks composing the job.
+
+The cgroup freezer will also be useful for checkpointing running groups
+of tasks. The freezer allows the checkpoint code to obtain a consistent
+image of the tasks by attempting to force the tasks in a cgroup into a
+quiescent state. Once the tasks are quiescent another task can
+walk /proc or invoke a kernel interface to gather information about the
+quiesced tasks. Checkpointed tasks can be restarted later should a
+recoverable error occur. This also allows the checkpointed tasks to be
+migrated between nodes in a cluster by copying the gathered information
+to another node and restarting the tasks there.
+
+Sequences of SIGSTOP and SIGCONT are not always sufficient for stopping
+and resuming tasks in userspace. Both of these signals are observable
+from within the tasks we wish to freeze. While SIGSTOP cannot be caught,
+blocked, or ignored it can be seen by waiting or ptracing parent tasks.
+SIGCONT is especially unsuitable since it can be caught by the task. Any
+programs designed to watch for SIGSTOP and SIGCONT could be broken by
+attempting to use SIGSTOP and SIGCONT to stop and resume tasks. We can
+demonstrate this problem using nested bash shells:
+
+       $ echo $$
+       16644
+       $ bash
+       $ echo $$
+       16690
+
+       From a second, unrelated bash shell:
+       $ kill -SIGSTOP 16690
+       $ kill -SIGCONT 16690
+
+       <at this point 16690 exits and causes 16644 to exit too>
+
+This happens because bash can observe both signals and choose how it
+responds to them.
+
+Another example of a program which catches and responds to these
+signals is gdb. In fact any program designed to use ptrace is likely to
+have a problem with this method of stopping and resuming tasks.
+
+In contrast, the cgroup freezer uses the kernel freezer code to
+prevent the freeze/unfreeze cycle from becoming visible to the tasks
+being frozen. This allows the bash example above and gdb to run as
+expected.
+
+The cgroup freezer is hierarchical. Freezing a cgroup freezes all
+tasks belonging to the cgroup and all its descendant cgroups. Each
+cgroup has its own state (self-state) and the state inherited from the
+parent (parent-state). Iff both states are THAWED, the cgroup is
+THAWED.
+
+The following cgroupfs files are created by cgroup freezer.
+
+* freezer.state: Read-write.
+
+  When read, returns the effective state of the cgroup - "THAWED",
+  "FREEZING" or "FROZEN". This is the combined self and parent-states.
+  If any is freezing, the cgroup is freezing (FREEZING or FROZEN).
+
+  FREEZING cgroup transitions into FROZEN state when all tasks
+  belonging to the cgroup and its descendants become frozen. Note that
+  a cgroup reverts to FREEZING from FROZEN after a new task is added
+  to the cgroup or one of its descendant cgroups until the new task is
+  frozen.
+
+  When written, sets the self-state of the cgroup. Two values are
+  allowed - "FROZEN" and "THAWED". If FROZEN is written, the cgroup,
+  if not already freezing, enters FREEZING state along with all its
+  descendant cgroups.
+
+  If THAWED is written, the self-state of the cgroup is changed to
+  THAWED.  Note that the effective state may not change to THAWED if
+  the parent-state is still freezing. If a cgroup's effective state
+  becomes THAWED, all its descendants which are freezing because of
+  the cgroup also leave the freezing state.
+
+* freezer.self_freezing: Read only.
+
+  Shows the self-state. 0 if the self-state is THAWED; otherwise, 1.
+  This value is 1 iff the last write to freezer.state was "FROZEN".
+
+* freezer.parent_freezing: Read only.
+
+  Shows the parent-state.  0 if none of the cgroup's ancestors is
+  frozen; otherwise, 1.
+
+The root cgroup is non-freezable and the above interface files don't
+exist.
+
+* Examples of usage :
+
+   # mkdir /sys/fs/cgroup/freezer
+   # mount -t cgroup -ofreezer freezer /sys/fs/cgroup/freezer
+   # mkdir /sys/fs/cgroup/freezer/0
+   # echo $some_pid > /sys/fs/cgroup/freezer/0/tasks
+
+to get status of the freezer subsystem :
+
+   # cat /sys/fs/cgroup/freezer/0/freezer.state
+   THAWED
+
+to freeze all tasks in the container :
+
+   # echo FROZEN > /sys/fs/cgroup/freezer/0/freezer.state
+   # cat /sys/fs/cgroup/freezer/0/freezer.state
+   FREEZING
+   # cat /sys/fs/cgroup/freezer/0/freezer.state
+   FROZEN
+
+to unfreeze all tasks in the container :
+
+   # echo THAWED > /sys/fs/cgroup/freezer/0/freezer.state
+   # cat /sys/fs/cgroup/freezer/0/freezer.state
+   THAWED
+
+This is the basic mechanism which should do the right thing for user space task
+in a simple scenario.
diff --git a/Documentation/cgroup-v1/hugetlb.txt b/Documentation/cgroup-v1/hugetlb.txt
new file mode 100644 (file)
index 0000000..106245c
--- /dev/null
@@ -0,0 +1,45 @@
+HugeTLB Controller
+-------------------
+
+The HugeTLB controller allows to limit the HugeTLB usage per control group and
+enforces the controller limit during page fault. Since HugeTLB doesn't
+support page reclaim, enforcing the limit at page fault time implies that,
+the application will get SIGBUS signal if it tries to access HugeTLB pages
+beyond its limit. This requires the application to know beforehand how much
+HugeTLB pages it would require for its use.
+
+HugeTLB controller can be created by first mounting the cgroup filesystem.
+
+# mount -t cgroup -o hugetlb none /sys/fs/cgroup
+
+With the above step, the initial or the parent HugeTLB group becomes
+visible at /sys/fs/cgroup. At bootup, this group includes all the tasks in
+the system. /sys/fs/cgroup/tasks lists the tasks in this cgroup.
+
+New groups can be created under the parent group /sys/fs/cgroup.
+
+# cd /sys/fs/cgroup
+# mkdir g1
+# echo $$ > g1/tasks
+
+The above steps create a new group g1 and move the current shell
+process (bash) into it.
+
+Brief summary of control files
+
+ hugetlb.<hugepagesize>.limit_in_bytes     # set/show limit of "hugepagesize" hugetlb usage
+ hugetlb.<hugepagesize>.max_usage_in_bytes # show max "hugepagesize" hugetlb  usage recorded
+ hugetlb.<hugepagesize>.usage_in_bytes     # show current usage for "hugepagesize" hugetlb
+ hugetlb.<hugepagesize>.failcnt                   # show the number of allocation failure due to HugeTLB limit
+
+For a system supporting two hugepage size (16M and 16G) the control
+files include:
+
+hugetlb.16GB.limit_in_bytes
+hugetlb.16GB.max_usage_in_bytes
+hugetlb.16GB.usage_in_bytes
+hugetlb.16GB.failcnt
+hugetlb.16MB.limit_in_bytes
+hugetlb.16MB.max_usage_in_bytes
+hugetlb.16MB.usage_in_bytes
+hugetlb.16MB.failcnt
diff --git a/Documentation/cgroup-v1/memcg_test.txt b/Documentation/cgroup-v1/memcg_test.txt
new file mode 100644 (file)
index 0000000..8870b02
--- /dev/null
@@ -0,0 +1,280 @@
+Memory Resource Controller(Memcg)  Implementation Memo.
+Last Updated: 2010/2
+Base Kernel Version: based on 2.6.33-rc7-mm(candidate for 34).
+
+Because VM is getting complex (one of reasons is memcg...), memcg's behavior
+is complex. This is a document for memcg's internal behavior.
+Please note that implementation details can be changed.
+
+(*) Topics on API should be in Documentation/cgroups/memory.txt)
+
+0. How to record usage ?
+   2 objects are used.
+
+   page_cgroup ....an object per page.
+       Allocated at boot or memory hotplug. Freed at memory hot removal.
+
+   swap_cgroup ... an entry per swp_entry.
+       Allocated at swapon(). Freed at swapoff().
+
+   The page_cgroup has USED bit and double count against a page_cgroup never
+   occurs. swap_cgroup is used only when a charged page is swapped-out.
+
+1. Charge
+
+   a page/swp_entry may be charged (usage += PAGE_SIZE) at
+
+       mem_cgroup_try_charge()
+
+2. Uncharge
+  a page/swp_entry may be uncharged (usage -= PAGE_SIZE) by
+
+       mem_cgroup_uncharge()
+         Called when a page's refcount goes down to 0.
+
+       mem_cgroup_uncharge_swap()
+         Called when swp_entry's refcnt goes down to 0. A charge against swap
+         disappears.
+
+3. charge-commit-cancel
+       Memcg pages are charged in two steps:
+               mem_cgroup_try_charge()
+               mem_cgroup_commit_charge() or mem_cgroup_cancel_charge()
+
+       At try_charge(), there are no flags to say "this page is charged".
+       at this point, usage += PAGE_SIZE.
+
+       At commit(), the page is associated with the memcg.
+
+       At cancel(), simply usage -= PAGE_SIZE.
+
+Under below explanation, we assume CONFIG_MEM_RES_CTRL_SWAP=y.
+
+4. Anonymous
+       Anonymous page is newly allocated at
+                 - page fault into MAP_ANONYMOUS mapping.
+                 - Copy-On-Write.
+
+       4.1 Swap-in.
+       At swap-in, the page is taken from swap-cache. There are 2 cases.
+
+       (a) If the SwapCache is newly allocated and read, it has no charges.
+       (b) If the SwapCache has been mapped by processes, it has been
+           charged already.
+
+       4.2 Swap-out.
+       At swap-out, typical state transition is below.
+
+       (a) add to swap cache. (marked as SwapCache)
+           swp_entry's refcnt += 1.
+       (b) fully unmapped.
+           swp_entry's refcnt += # of ptes.
+       (c) write back to swap.
+       (d) delete from swap cache. (remove from SwapCache)
+           swp_entry's refcnt -= 1.
+
+
+       Finally, at task exit,
+       (e) zap_pte() is called and swp_entry's refcnt -=1 -> 0.
+
+5. Page Cache
+       Page Cache is charged at
+       - add_to_page_cache_locked().
+
+       The logic is very clear. (About migration, see below)
+       Note: __remove_from_page_cache() is called by remove_from_page_cache()
+       and __remove_mapping().
+
+6. Shmem(tmpfs) Page Cache
+       The best way to understand shmem's page state transition is to read
+       mm/shmem.c.
+       But brief explanation of the behavior of memcg around shmem will be
+       helpful to understand the logic.
+
+       Shmem's page (just leaf page, not direct/indirect block) can be on
+               - radix-tree of shmem's inode.
+               - SwapCache.
+               - Both on radix-tree and SwapCache. This happens at swap-in
+                 and swap-out,
+
+       It's charged when...
+       - A new page is added to shmem's radix-tree.
+       - A swp page is read. (move a charge from swap_cgroup to page_cgroup)
+
+7. Page Migration
+
+       mem_cgroup_migrate()
+
+8. LRU
+        Each memcg has its own private LRU. Now, its handling is under global
+       VM's control (means that it's handled under global zone->lru_lock).
+       Almost all routines around memcg's LRU is called by global LRU's
+       list management functions under zone->lru_lock().
+
+       A special function is mem_cgroup_isolate_pages(). This scans
+       memcg's private LRU and call __isolate_lru_page() to extract a page
+       from LRU.
+       (By __isolate_lru_page(), the page is removed from both of global and
+        private LRU.)
+
+
+9. Typical Tests.
+
+ Tests for racy cases.
+
+ 9.1 Small limit to memcg.
+       When you do test to do racy case, it's good test to set memcg's limit
+       to be very small rather than GB. Many races found in the test under
+       xKB or xxMB limits.
+       (Memory behavior under GB and Memory behavior under MB shows very
+        different situation.)
+
+ 9.2 Shmem
+       Historically, memcg's shmem handling was poor and we saw some amount
+       of troubles here. This is because shmem is page-cache but can be
+       SwapCache. Test with shmem/tmpfs is always good test.
+
+ 9.3 Migration
+       For NUMA, migration is an another special case. To do easy test, cpuset
+       is useful. Following is a sample script to do migration.
+
+       mount -t cgroup -o cpuset none /opt/cpuset
+
+       mkdir /opt/cpuset/01
+       echo 1 > /opt/cpuset/01/cpuset.cpus
+       echo 0 > /opt/cpuset/01/cpuset.mems
+       echo 1 > /opt/cpuset/01/cpuset.memory_migrate
+       mkdir /opt/cpuset/02
+       echo 1 > /opt/cpuset/02/cpuset.cpus
+       echo 1 > /opt/cpuset/02/cpuset.mems
+       echo 1 > /opt/cpuset/02/cpuset.memory_migrate
+
+       In above set, when you moves a task from 01 to 02, page migration to
+       node 0 to node 1 will occur. Following is a script to migrate all
+       under cpuset.
+       --
+       move_task()
+       {
+       for pid in $1
+        do
+                /bin/echo $pid >$2/tasks 2>/dev/null
+               echo -n $pid
+               echo -n " "
+        done
+       echo END
+       }
+
+       G1_TASK=`cat ${G1}/tasks`
+       G2_TASK=`cat ${G2}/tasks`
+       move_task "${G1_TASK}" ${G2} &
+       --
+ 9.4 Memory hotplug.
+       memory hotplug test is one of good test.
+       to offline memory, do following.
+       # echo offline > /sys/devices/system/memory/memoryXXX/state
+       (XXX is the place of memory)
+       This is an easy way to test page migration, too.
+
+ 9.5 mkdir/rmdir
+       When using hierarchy, mkdir/rmdir test should be done.
+       Use tests like the following.
+
+       echo 1 >/opt/cgroup/01/memory/use_hierarchy
+       mkdir /opt/cgroup/01/child_a
+       mkdir /opt/cgroup/01/child_b
+
+       set limit to 01.
+       add limit to 01/child_b
+       run jobs under child_a and child_b
+
+       create/delete following groups at random while jobs are running.
+       /opt/cgroup/01/child_a/child_aa
+       /opt/cgroup/01/child_b/child_bb
+       /opt/cgroup/01/child_c
+
+       running new jobs in new group is also good.
+
+ 9.6 Mount with other subsystems.
+       Mounting with other subsystems is a good test because there is a
+       race and lock dependency with other cgroup subsystems.
+
+       example)
+       # mount -t cgroup none /cgroup -o cpuset,memory,cpu,devices
+
+       and do task move, mkdir, rmdir etc...under this.
+
+ 9.7 swapoff.
+       Besides management of swap is one of complicated parts of memcg,
+       call path of swap-in at swapoff is not same as usual swap-in path..
+       It's worth to be tested explicitly.
+
+       For example, test like following is good.
+       (Shell-A)
+       # mount -t cgroup none /cgroup -o memory
+       # mkdir /cgroup/test
+       # echo 40M > /cgroup/test/memory.limit_in_bytes
+       # echo 0 > /cgroup/test/tasks
+       Run malloc(100M) program under this. You'll see 60M of swaps.
+       (Shell-B)
+       # move all tasks in /cgroup/test to /cgroup
+       # /sbin/swapoff -a
+       # rmdir /cgroup/test
+       # kill malloc task.
+
+       Of course, tmpfs v.s. swapoff test should be tested, too.
+
+ 9.8 OOM-Killer
+       Out-of-memory caused by memcg's limit will kill tasks under
+       the memcg. When hierarchy is used, a task under hierarchy
+       will be killed by the kernel.
+       In this case, panic_on_oom shouldn't be invoked and tasks
+       in other groups shouldn't be killed.
+
+       It's not difficult to cause OOM under memcg as following.
+       Case A) when you can swapoff
+       #swapoff -a
+       #echo 50M > /memory.limit_in_bytes
+       run 51M of malloc
+
+       Case B) when you use mem+swap limitation.
+       #echo 50M > memory.limit_in_bytes
+       #echo 50M > memory.memsw.limit_in_bytes
+       run 51M of malloc
+
+ 9.9 Move charges at task migration
+       Charges associated with a task can be moved along with task migration.
+
+       (Shell-A)
+       #mkdir /cgroup/A
+       #echo $$ >/cgroup/A/tasks
+       run some programs which uses some amount of memory in /cgroup/A.
+
+       (Shell-B)
+       #mkdir /cgroup/B
+       #echo 1 >/cgroup/B/memory.move_charge_at_immigrate
+       #echo "pid of the program running in group A" >/cgroup/B/tasks
+
+       You can see charges have been moved by reading *.usage_in_bytes or
+       memory.stat of both A and B.
+       See 8.2 of Documentation/cgroups/memory.txt to see what value should be
+       written to move_charge_at_immigrate.
+
+ 9.10 Memory thresholds
+       Memory controller implements memory thresholds using cgroups notification
+       API. You can use tools/cgroup/cgroup_event_listener.c to test it.
+
+       (Shell-A) Create cgroup and run event listener
+       # mkdir /cgroup/A
+       # ./cgroup_event_listener /cgroup/A/memory.usage_in_bytes 5M
+
+       (Shell-B) Add task to cgroup and try to allocate and free memory
+       # echo $$ >/cgroup/A/tasks
+       # a="$(dd if=/dev/zero bs=1M count=10)"
+       # a=
+
+       You will see message from cgroup_event_listener every time you cross
+       the thresholds.
+
+       Use /cgroup/A/memory.memsw.usage_in_bytes to test memsw thresholds.
+
+       It's good idea to test root cgroup as well.
diff --git a/Documentation/cgroup-v1/memory.txt b/Documentation/cgroup-v1/memory.txt
new file mode 100644 (file)
index 0000000..ff71e16
--- /dev/null
@@ -0,0 +1,876 @@
+Memory Resource Controller
+
+NOTE: This document is hopelessly outdated and it asks for a complete
+      rewrite. It still contains a useful information so we are keeping it
+      here but make sure to check the current code if you need a deeper
+      understanding.
+
+NOTE: The Memory Resource Controller has generically been referred to as the
+      memory controller in this document. Do not confuse memory controller
+      used here with the memory controller that is used in hardware.
+
+(For editors)
+In this document:
+      When we mention a cgroup (cgroupfs's directory) with memory controller,
+      we call it "memory cgroup". When you see git-log and source code, you'll
+      see patch's title and function names tend to use "memcg".
+      In this document, we avoid using it.
+
+Benefits and Purpose of the memory controller
+
+The memory controller isolates the memory behaviour of a group of tasks
+from the rest of the system. The article on LWN [12] mentions some probable
+uses of the memory controller. The memory controller can be used to
+
+a. Isolate an application or a group of applications
+   Memory-hungry applications can be isolated and limited to a smaller
+   amount of memory.
+b. Create a cgroup with a limited amount of memory; this can be used
+   as a good alternative to booting with mem=XXXX.
+c. Virtualization solutions can control the amount of memory they want
+   to assign to a virtual machine instance.
+d. A CD/DVD burner could control the amount of memory used by the
+   rest of the system to ensure that burning does not fail due to lack
+   of available memory.
+e. There are several other use cases; find one or use the controller just
+   for fun (to learn and hack on the VM subsystem).
+
+Current Status: linux-2.6.34-mmotm(development version of 2010/April)
+
+Features:
+ - accounting anonymous pages, file caches, swap caches usage and limiting them.
+ - pages are linked to per-memcg LRU exclusively, and there is no global LRU.
+ - optionally, memory+swap usage can be accounted and limited.
+ - hierarchical accounting
+ - soft limit
+ - moving (recharging) account at moving a task is selectable.
+ - usage threshold notifier
+ - memory pressure notifier
+ - oom-killer disable knob and oom-notifier
+ - Root cgroup has no limit controls.
+
+ Kernel memory support is a work in progress, and the current version provides
+ basically functionality. (See Section 2.7)
+
+Brief summary of control files.
+
+ tasks                          # attach a task(thread) and show list of threads
+ cgroup.procs                   # show list of processes
+ cgroup.event_control           # an interface for event_fd()
+ memory.usage_in_bytes          # show current usage for memory
+                                (See 5.5 for details)
+ memory.memsw.usage_in_bytes    # show current usage for memory+Swap
+                                (See 5.5 for details)
+ memory.limit_in_bytes          # set/show limit of memory usage
+ memory.memsw.limit_in_bytes    # set/show limit of memory+Swap usage
+ memory.failcnt                         # show the number of memory usage hits limits
+ memory.memsw.failcnt           # show the number of memory+Swap hits limits
+ memory.max_usage_in_bytes      # show max memory usage recorded
+ memory.memsw.max_usage_in_bytes # show max memory+Swap usage recorded
+ memory.soft_limit_in_bytes     # set/show soft limit of memory usage
+ memory.stat                    # show various statistics
+ memory.use_hierarchy           # set/show hierarchical account enabled
+ memory.force_empty             # trigger forced move charge to parent
+ memory.pressure_level          # set memory pressure notifications
+ memory.swappiness              # set/show swappiness parameter of vmscan
+                                (See sysctl's vm.swappiness)
+ memory.move_charge_at_immigrate # set/show controls of moving charges
+ memory.oom_control             # set/show oom controls.
+ memory.numa_stat               # show the number of memory usage per numa node
+
+ memory.kmem.limit_in_bytes      # set/show hard limit for kernel memory
+ memory.kmem.usage_in_bytes      # show current kernel memory allocation
+ memory.kmem.failcnt             # show the number of kernel memory usage hits limits
+ memory.kmem.max_usage_in_bytes  # show max kernel memory usage recorded
+
+ memory.kmem.tcp.limit_in_bytes  # set/show hard limit for tcp buf memory
+ memory.kmem.tcp.usage_in_bytes  # show current tcp buf memory allocation
+ memory.kmem.tcp.failcnt            # show the number of tcp buf memory usage hits limits
+ memory.kmem.tcp.max_usage_in_bytes # show max tcp buf memory usage recorded
+
+1. History
+
+The memory controller has a long history. A request for comments for the memory
+controller was posted by Balbir Singh [1]. At the time the RFC was posted
+there were several implementations for memory control. The goal of the
+RFC was to build consensus and agreement for the minimal features required
+for memory control. The first RSS controller was posted by Balbir Singh[2]
+in Feb 2007. Pavel Emelianov [3][4][5] has since posted three versions of the
+RSS controller. At OLS, at the resource management BoF, everyone suggested
+that we handle both page cache and RSS together. Another request was raised
+to allow user space handling of OOM. The current memory controller is
+at version 6; it combines both mapped (RSS) and unmapped Page
+Cache Control [11].
+
+2. Memory Control
+
+Memory is a unique resource in the sense that it is present in a limited
+amount. If a task requires a lot of CPU processing, the task can spread
+its processing over a period of hours, days, months or years, but with
+memory, the same physical memory needs to be reused to accomplish the task.
+
+The memory controller implementation has been divided into phases. These
+are:
+
+1. Memory controller
+2. mlock(2) controller
+3. Kernel user memory accounting and slab control
+4. user mappings length controller
+
+The memory controller is the first controller developed.
+
+2.1. Design
+
+The core of the design is a counter called the page_counter. The
+page_counter tracks the current memory usage and limit of the group of
+processes associated with the controller. Each cgroup has a memory controller
+specific data structure (mem_cgroup) associated with it.
+
+2.2. Accounting
+
+               +--------------------+
+               |  mem_cgroup        |
+               |  (page_counter)    |
+               +--------------------+
+                /            ^      \
+               /             |       \
+           +---------------+  |        +---------------+
+           | mm_struct     |  |....    | mm_struct     |
+           |               |  |        |               |
+           +---------------+  |        +---------------+
+                              |
+                              + --------------+
+                                              |
+           +---------------+           +------+--------+
+           | page          +---------->  page_cgroup|
+           |               |           |               |
+           +---------------+           +---------------+
+
+             (Figure 1: Hierarchy of Accounting)
+
+
+Figure 1 shows the important aspects of the controller
+
+1. Accounting happens per cgroup
+2. Each mm_struct knows about which cgroup it belongs to
+3. Each page has a pointer to the page_cgroup, which in turn knows the
+   cgroup it belongs to
+
+The accounting is done as follows: mem_cgroup_charge_common() is invoked to
+set up the necessary data structures and check if the cgroup that is being
+charged is over its limit. If it is, then reclaim is invoked on the cgroup.
+More details can be found in the reclaim section of this document.
+If everything goes well, a page meta-data-structure called page_cgroup is
+updated. page_cgroup has its own LRU on cgroup.
+(*) page_cgroup structure is allocated at boot/memory-hotplug time.
+
+2.2.1 Accounting details
+
+All mapped anon pages (RSS) and cache pages (Page Cache) are accounted.
+Some pages which are never reclaimable and will not be on the LRU
+are not accounted. We just account pages under usual VM management.
+
+RSS pages are accounted at page_fault unless they've already been accounted
+for earlier. A file page will be accounted for as Page Cache when it's
+inserted into inode (radix-tree). While it's mapped into the page tables of
+processes, duplicate accounting is carefully avoided.
+
+An RSS page is unaccounted when it's fully unmapped. A PageCache page is
+unaccounted when it's removed from radix-tree. Even if RSS pages are fully
+unmapped (by kswapd), they may exist as SwapCache in the system until they
+are really freed. Such SwapCaches are also accounted.
+A swapped-in page is not accounted until it's mapped.
+
+Note: The kernel does swapin-readahead and reads multiple swaps at once.
+This means swapped-in pages may contain pages for other tasks than a task
+causing page fault. So, we avoid accounting at swap-in I/O.
+
+At page migration, accounting information is kept.
+
+Note: we just account pages-on-LRU because our purpose is to control amount
+of used pages; not-on-LRU pages tend to be out-of-control from VM view.
+
+2.3 Shared Page Accounting
+
+Shared pages are accounted on the basis of the first touch approach. The
+cgroup that first touches a page is accounted for the page. The principle
+behind this approach is that a cgroup that aggressively uses a shared
+page will eventually get charged for it (once it is uncharged from
+the cgroup that brought it in -- this will happen on memory pressure).
+
+But see section 8.2: when moving a task to another cgroup, its pages may
+be recharged to the new cgroup, if move_charge_at_immigrate has been chosen.
+
+Exception: If CONFIG_MEMCG_SWAP is not used.
+When you do swapoff and make swapped-out pages of shmem(tmpfs) to
+be backed into memory in force, charges for pages are accounted against the
+caller of swapoff rather than the users of shmem.
+
+2.4 Swap Extension (CONFIG_MEMCG_SWAP)
+
+Swap Extension allows you to record charge for swap. A swapped-in page is
+charged back to original page allocator if possible.
+
+When swap is accounted, following files are added.
+ - memory.memsw.usage_in_bytes.
+ - memory.memsw.limit_in_bytes.
+
+memsw means memory+swap. Usage of memory+swap is limited by
+memsw.limit_in_bytes.
+
+Example: Assume a system with 4G of swap. A task which allocates 6G of memory
+(by mistake) under 2G memory limitation will use all swap.
+In this case, setting memsw.limit_in_bytes=3G will prevent bad use of swap.
+By using the memsw limit, you can avoid system OOM which can be caused by swap
+shortage.
+
+* why 'memory+swap' rather than swap.
+The global LRU(kswapd) can swap out arbitrary pages. Swap-out means
+to move account from memory to swap...there is no change in usage of
+memory+swap. In other words, when we want to limit the usage of swap without
+affecting global LRU, memory+swap limit is better than just limiting swap from
+an OS point of view.
+
+* What happens when a cgroup hits memory.memsw.limit_in_bytes
+When a cgroup hits memory.memsw.limit_in_bytes, it's useless to do swap-out
+in this cgroup. Then, swap-out will not be done by cgroup routine and file
+caches are dropped. But as mentioned above, global LRU can do swapout memory
+from it for sanity of the system's memory management state. You can't forbid
+it by cgroup.
+
+2.5 Reclaim
+
+Each cgroup maintains a per cgroup LRU which has the same structure as
+global VM. When a cgroup goes over its limit, we first try
+to reclaim memory from the cgroup so as to make space for the new
+pages that the cgroup has touched. If the reclaim is unsuccessful,
+an OOM routine is invoked to select and kill the bulkiest task in the
+cgroup. (See 10. OOM Control below.)
+
+The reclaim algorithm has not been modified for cgroups, except that
+pages that are selected for reclaiming come from the per-cgroup LRU
+list.
+
+NOTE: Reclaim does not work for the root cgroup, since we cannot set any
+limits on the root cgroup.
+
+Note2: When panic_on_oom is set to "2", the whole system will panic.
+
+When oom event notifier is registered, event will be delivered.
+(See oom_control section)
+
+2.6 Locking
+
+   lock_page_cgroup()/unlock_page_cgroup() should not be called under
+   mapping->tree_lock.
+
+   Other lock order is following:
+   PG_locked.
+   mm->page_table_lock
+       zone->lru_lock
+         lock_page_cgroup.
+  In many cases, just lock_page_cgroup() is called.
+  per-zone-per-cgroup LRU (cgroup's private LRU) is just guarded by
+  zone->lru_lock, it has no lock of its own.
+
+2.7 Kernel Memory Extension (CONFIG_MEMCG_KMEM)
+
+With the Kernel memory extension, the Memory Controller is able to limit
+the amount of kernel memory used by the system. Kernel memory is fundamentally
+different than user memory, since it can't be swapped out, which makes it
+possible to DoS the system by consuming too much of this precious resource.
+
+Kernel memory won't be accounted at all until limit on a group is set. This
+allows for existing setups to continue working without disruption.  The limit
+cannot be set if the cgroup have children, or if there are already tasks in the
+cgroup. Attempting to set the limit under those conditions will return -EBUSY.
+When use_hierarchy == 1 and a group is accounted, its children will
+automatically be accounted regardless of their limit value.
+
+After a group is first limited, it will be kept being accounted until it
+is removed. The memory limitation itself, can of course be removed by writing
+-1 to memory.kmem.limit_in_bytes. In this case, kmem will be accounted, but not
+limited.
+
+Kernel memory limits are not imposed for the root cgroup. Usage for the root
+cgroup may or may not be accounted. The memory used is accumulated into
+memory.kmem.usage_in_bytes, or in a separate counter when it makes sense.
+(currently only for tcp).
+The main "kmem" counter is fed into the main counter, so kmem charges will
+also be visible from the user counter.
+
+Currently no soft limit is implemented for kernel memory. It is future work
+to trigger slab reclaim when those limits are reached.
+
+2.7.1 Current Kernel Memory resources accounted
+
+* stack pages: every process consumes some stack pages. By accounting into
+kernel memory, we prevent new processes from being created when the kernel
+memory usage is too high.
+
+* slab pages: pages allocated by the SLAB or SLUB allocator are tracked. A copy
+of each kmem_cache is created every time the cache is touched by the first time
+from inside the memcg. The creation is done lazily, so some objects can still be
+skipped while the cache is being created. All objects in a slab page should
+belong to the same memcg. This only fails to hold when a task is migrated to a
+different memcg during the page allocation by the cache.
+
+* sockets memory pressure: some sockets protocols have memory pressure
+thresholds. The Memory Controller allows them to be controlled individually
+per cgroup, instead of globally.
+
+* tcp memory pressure: sockets memory pressure for the tcp protocol.
+
+2.7.2 Common use cases
+
+Because the "kmem" counter is fed to the main user counter, kernel memory can
+never be limited completely independently of user memory. Say "U" is the user
+limit, and "K" the kernel limit. There are three possible ways limits can be
+set:
+
+    U != 0, K = unlimited:
+    This is the standard memcg limitation mechanism already present before kmem
+    accounting. Kernel memory is completely ignored.
+
+    U != 0, K < U:
+    Kernel memory is a subset of the user memory. This setup is useful in
+    deployments where the total amount of memory per-cgroup is overcommited.
+    Overcommiting kernel memory limits is definitely not recommended, since the
+    box can still run out of non-reclaimable memory.
+    In this case, the admin could set up K so that the sum of all groups is
+    never greater than the total memory, and freely set U at the cost of his
+    QoS.
+    WARNING: In the current implementation, memory reclaim will NOT be
+    triggered for a cgroup when it hits K while staying below U, which makes
+    this setup impractical.
+
+    U != 0, K >= U:
+    Since kmem charges will also be fed to the user counter and reclaim will be
+    triggered for the cgroup for both kinds of memory. This setup gives the
+    admin a unified view of memory, and it is also useful for people who just
+    want to track kernel memory usage.
+
+3. User Interface
+
+3.0. Configuration
+
+a. Enable CONFIG_CGROUPS
+b. Enable CONFIG_MEMCG
+c. Enable CONFIG_MEMCG_SWAP (to use swap extension)
+d. Enable CONFIG_MEMCG_KMEM (to use kmem extension)
+
+3.1. Prepare the cgroups (see cgroups.txt, Why are cgroups needed?)
+# mount -t tmpfs none /sys/fs/cgroup
+# mkdir /sys/fs/cgroup/memory
+# mount -t cgroup none /sys/fs/cgroup/memory -o memory
+
+3.2. Make the new group and move bash into it
+# mkdir /sys/fs/cgroup/memory/0
+# echo $$ > /sys/fs/cgroup/memory/0/tasks
+
+Since now we're in the 0 cgroup, we can alter the memory limit:
+# echo 4M > /sys/fs/cgroup/memory/0/memory.limit_in_bytes
+
+NOTE: We can use a suffix (k, K, m, M, g or G) to indicate values in kilo,
+mega or gigabytes. (Here, Kilo, Mega, Giga are Kibibytes, Mebibytes, Gibibytes.)
+
+NOTE: We can write "-1" to reset the *.limit_in_bytes(unlimited).
+NOTE: We cannot set limits on the root cgroup any more.
+
+# cat /sys/fs/cgroup/memory/0/memory.limit_in_bytes
+4194304
+
+We can check the usage:
+# cat /sys/fs/cgroup/memory/0/memory.usage_in_bytes
+1216512
+
+A successful write to this file does not guarantee a successful setting of
+this limit to the value written into the file. This can be due to a
+number of factors, such as rounding up to page boundaries or the total
+availability of memory on the system. The user is required to re-read
+this file after a write to guarantee the value committed by the kernel.
+
+# echo 1 > memory.limit_in_bytes
+# cat memory.limit_in_bytes
+4096
+
+The memory.failcnt field gives the number of times that the cgroup limit was
+exceeded.
+
+The memory.stat file gives accounting information. Now, the number of
+caches, RSS and Active pages/Inactive pages are shown.
+
+4. Testing
+
+For testing features and implementation, see memcg_test.txt.
+
+Performance test is also important. To see pure memory controller's overhead,
+testing on tmpfs will give you good numbers of small overheads.
+Example: do kernel make on tmpfs.
+
+Page-fault scalability is also important. At measuring parallel
+page fault test, multi-process test may be better than multi-thread
+test because it has noise of shared objects/status.
+
+But the above two are testing extreme situations.
+Trying usual test under memory controller is always helpful.
+
+4.1 Troubleshooting
+
+Sometimes a user might find that the application under a cgroup is
+terminated by the OOM killer. There are several causes for this:
+
+1. The cgroup limit is too low (just too low to do anything useful)
+2. The user is using anonymous memory and swap is turned off or too low
+
+A sync followed by echo 1 > /proc/sys/vm/drop_caches will help get rid of
+some of the pages cached in the cgroup (page cache pages).
+
+To know what happens, disabling OOM_Kill as per "10. OOM Control" (below) and
+seeing what happens will be helpful.
+
+4.2 Task migration
+
+When a task migrates from one cgroup to another, its charge is not
+carried forward by default. The pages allocated from the original cgroup still
+remain charged to it, the charge is dropped when the page is freed or
+reclaimed.
+
+You can move charges of a task along with task migration.
+See 8. "Move charges at task migration"
+
+4.3 Removing a cgroup
+
+A cgroup can be removed by rmdir, but as discussed in sections 4.1 and 4.2, a
+cgroup might have some charge associated with it, even though all
+tasks have migrated away from it. (because we charge against pages, not
+against tasks.)
+
+We move the stats to root (if use_hierarchy==0) or parent (if
+use_hierarchy==1), and no change on the charge except uncharging
+from the child.
+
+Charges recorded in swap information is not updated at removal of cgroup.
+Recorded information is discarded and a cgroup which uses swap (swapcache)
+will be charged as a new owner of it.
+
+About use_hierarchy, see Section 6.
+
+5. Misc. interfaces.
+
+5.1 force_empty
+  memory.force_empty interface is provided to make cgroup's memory usage empty.
+  When writing anything to this
+
+  # echo 0 > memory.force_empty
+
+  the cgroup will be reclaimed and as many pages reclaimed as possible.
+
+  The typical use case for this interface is before calling rmdir().
+  Because rmdir() moves all pages to parent, some out-of-use page caches can be
+  moved to the parent. If you want to avoid that, force_empty will be useful.
+
+  Also, note that when memory.kmem.limit_in_bytes is set the charges due to
+  kernel pages will still be seen. This is not considered a failure and the
+  write will still return success. In this case, it is expected that
+  memory.kmem.usage_in_bytes == memory.usage_in_bytes.
+
+  About use_hierarchy, see Section 6.
+
+5.2 stat file
+
+memory.stat file includes following statistics
+
+# per-memory cgroup local status
+cache          - # of bytes of page cache memory.
+rss            - # of bytes of anonymous and swap cache memory (includes
+               transparent hugepages).
+rss_huge       - # of bytes of anonymous transparent hugepages.
+mapped_file    - # of bytes of mapped file (includes tmpfs/shmem)
+pgpgin         - # of charging events to the memory cgroup. The charging
+               event happens each time a page is accounted as either mapped
+               anon page(RSS) or cache page(Page Cache) to the cgroup.
+pgpgout                - # of uncharging events to the memory cgroup. The uncharging
+               event happens each time a page is unaccounted from the cgroup.
+swap           - # of bytes of swap usage
+dirty          - # of bytes that are waiting to get written back to the disk.
+writeback      - # of bytes of file/anon cache that are queued for syncing to
+               disk.
+inactive_anon  - # of bytes of anonymous and swap cache memory on inactive
+               LRU list.
+active_anon    - # of bytes of anonymous and swap cache memory on active
+               LRU list.
+inactive_file  - # of bytes of file-backed memory on inactive LRU list.
+active_file    - # of bytes of file-backed memory on active LRU list.
+unevictable    - # of bytes of memory that cannot be reclaimed (mlocked etc).
+
+# status considering hierarchy (see memory.use_hierarchy settings)
+
+hierarchical_memory_limit - # of bytes of memory limit with regard to hierarchy
+                       under which the memory cgroup is
+hierarchical_memsw_limit - # of bytes of memory+swap limit with regard to
+                       hierarchy under which memory cgroup is.
+
+total_<counter>                - # hierarchical version of <counter>, which in
+                       addition to the cgroup's own value includes the
+                       sum of all hierarchical children's values of
+                       <counter>, i.e. total_cache
+
+# The following additional stats are dependent on CONFIG_DEBUG_VM.
+
+recent_rotated_anon    - VM internal parameter. (see mm/vmscan.c)
+recent_rotated_file    - VM internal parameter. (see mm/vmscan.c)
+recent_scanned_anon    - VM internal parameter. (see mm/vmscan.c)
+recent_scanned_file    - VM internal parameter. (see mm/vmscan.c)
+
+Memo:
+       recent_rotated means recent frequency of LRU rotation.
+       recent_scanned means recent # of scans to LRU.
+       showing for better debug please see the code for meanings.
+
+Note:
+       Only anonymous and swap cache memory is listed as part of 'rss' stat.
+       This should not be confused with the true 'resident set size' or the
+       amount of physical memory used by the cgroup.
+       'rss + file_mapped" will give you resident set size of cgroup.
+       (Note: file and shmem may be shared among other cgroups. In that case,
+        file_mapped is accounted only when the memory cgroup is owner of page
+        cache.)
+
+5.3 swappiness
+
+Overrides /proc/sys/vm/swappiness for the particular group. The tunable
+in the root cgroup corresponds to the global swappiness setting.
+
+Please note that unlike during the global reclaim, limit reclaim
+enforces that 0 swappiness really prevents from any swapping even if
+there is a swap storage available. This might lead to memcg OOM killer
+if there are no file pages to reclaim.
+
+5.4 failcnt
+
+A memory cgroup provides memory.failcnt and memory.memsw.failcnt files.
+This failcnt(== failure count) shows the number of times that a usage counter
+hit its limit. When a memory cgroup hits a limit, failcnt increases and
+memory under it will be reclaimed.
+
+You can reset failcnt by writing 0 to failcnt file.
+# echo 0 > .../memory.failcnt
+
+5.5 usage_in_bytes
+
+For efficiency, as other kernel components, memory cgroup uses some optimization
+to avoid unnecessary cacheline false sharing. usage_in_bytes is affected by the
+method and doesn't show 'exact' value of memory (and swap) usage, it's a fuzz
+value for efficient access. (Of course, when necessary, it's synchronized.)
+If you want to know more exact memory usage, you should use RSS+CACHE(+SWAP)
+value in memory.stat(see 5.2).
+
+5.6 numa_stat
+
+This is similar to numa_maps but operates on a per-memcg basis.  This is
+useful for providing visibility into the numa locality information within
+an memcg since the pages are allowed to be allocated from any physical
+node.  One of the use cases is evaluating application performance by
+combining this information with the application's CPU allocation.
+
+Each memcg's numa_stat file includes "total", "file", "anon" and "unevictable"
+per-node page counts including "hierarchical_<counter>" which sums up all
+hierarchical children's values in addition to the memcg's own value.
+
+The output format of memory.numa_stat is:
+
+total=<total pages> N0=<node 0 pages> N1=<node 1 pages> ...
+file=<total file pages> N0=<node 0 pages> N1=<node 1 pages> ...
+anon=<total anon pages> N0=<node 0 pages> N1=<node 1 pages> ...
+unevictable=<total anon pages> N0=<node 0 pages> N1=<node 1 pages> ...
+hierarchical_<counter>=<counter pages> N0=<node 0 pages> N1=<node 1 pages> ...
+
+The "total" count is sum of file + anon + unevictable.
+
+6. Hierarchy support
+
+The memory controller supports a deep hierarchy and hierarchical accounting.
+The hierarchy is created by creating the appropriate cgroups in the
+cgroup filesystem. Consider for example, the following cgroup filesystem
+hierarchy
+
+              root
+            /  |   \
+            /  |    \
+          a    b     c
+                     | \
+                     |  \
+                     d   e
+
+In the diagram above, with hierarchical accounting enabled, all memory
+usage of e, is accounted to its ancestors up until the root (i.e, c and root),
+that has memory.use_hierarchy enabled. If one of the ancestors goes over its
+limit, the reclaim algorithm reclaims from the tasks in the ancestor and the
+children of the ancestor.
+
+6.1 Enabling hierarchical accounting and reclaim
+
+A memory cgroup by default disables the hierarchy feature. Support
+can be enabled by writing 1 to memory.use_hierarchy file of the root cgroup
+
+# echo 1 > memory.use_hierarchy
+
+The feature can be disabled by
+
+# echo 0 > memory.use_hierarchy
+
+NOTE1: Enabling/disabling will fail if either the cgroup already has other
+       cgroups created below it, or if the parent cgroup has use_hierarchy
+       enabled.
+
+NOTE2: When panic_on_oom is set to "2", the whole system will panic in
+       case of an OOM event in any cgroup.
+
+7. Soft limits
+
+Soft limits allow for greater sharing of memory. The idea behind soft limits
+is to allow control groups to use as much of the memory as needed, provided
+
+a. There is no memory contention
+b. They do not exceed their hard limit
+
+When the system detects memory contention or low memory, control groups
+are pushed back to their soft limits. If the soft limit of each control
+group is very high, they are pushed back as much as possible to make
+sure that one control group does not starve the others of memory.
+
+Please note that soft limits is a best-effort feature; it comes with
+no guarantees, but it does its best to make sure that when memory is
+heavily contended for, memory is allocated based on the soft limit
+hints/setup. Currently soft limit based reclaim is set up such that
+it gets invoked from balance_pgdat (kswapd).
+
+7.1 Interface
+
+Soft limits can be setup by using the following commands (in this example we
+assume a soft limit of 256 MiB)
+
+# echo 256M > memory.soft_limit_in_bytes
+
+If we want to change this to 1G, we can at any time use
+
+# echo 1G > memory.soft_limit_in_bytes
+
+NOTE1: Soft limits take effect over a long period of time, since they involve
+       reclaiming memory for balancing between memory cgroups
+NOTE2: It is recommended to set the soft limit always below the hard limit,
+       otherwise the hard limit will take precedence.
+
+8. Move charges at task migration
+
+Users can move charges associated with a task along with task migration, that
+is, uncharge task's pages from the old cgroup and charge them to the new cgroup.
+This feature is not supported in !CONFIG_MMU environments because of lack of
+page tables.
+
+8.1 Interface
+
+This feature is disabled by default. It can be enabled (and disabled again) by
+writing to memory.move_charge_at_immigrate of the destination cgroup.
+
+If you want to enable it:
+
+# echo (some positive value) > memory.move_charge_at_immigrate
+
+Note: Each bits of move_charge_at_immigrate has its own meaning about what type
+      of charges should be moved. See 8.2 for details.
+Note: Charges are moved only when you move mm->owner, in other words,
+      a leader of a thread group.
+Note: If we cannot find enough space for the task in the destination cgroup, we
+      try to make space by reclaiming memory. Task migration may fail if we
+      cannot make enough space.
+Note: It can take several seconds if you move charges much.
+
+And if you want disable it again:
+
+# echo 0 > memory.move_charge_at_immigrate
+
+8.2 Type of charges which can be moved
+
+Each bit in move_charge_at_immigrate has its own meaning about what type of
+charges should be moved. But in any case, it must be noted that an account of
+a page or a swap can be moved only when it is charged to the task's current
+(old) memory cgroup.
+
+  bit | what type of charges would be moved ?
+ -----+------------------------------------------------------------------------
+   0  | A charge of an anonymous page (or swap of it) used by the target task.
+      | You must enable Swap Extension (see 2.4) to enable move of swap charges.
+ -----+------------------------------------------------------------------------
+   1  | A charge of file pages (normal file, tmpfs file (e.g. ipc shared memory)
+      | and swaps of tmpfs file) mmapped by the target task. Unlike the case of
+      | anonymous pages, file pages (and swaps) in the range mmapped by the task
+      | will be moved even if the task hasn't done page fault, i.e. they might
+      | not be the task's "RSS", but other task's "RSS" that maps the same file.
+      | And mapcount of the page is ignored (the page can be moved even if
+      | page_mapcount(page) > 1). You must enable Swap Extension (see 2.4) to
+      | enable move of swap charges.
+
+8.3 TODO
+
+- All of moving charge operations are done under cgroup_mutex. It's not good
+  behavior to hold the mutex too long, so we may need some trick.
+
+9. Memory thresholds
+
+Memory cgroup implements memory thresholds using the cgroups notification
+API (see cgroups.txt). It allows to register multiple memory and memsw
+thresholds and gets notifications when it crosses.
+
+To register a threshold, an application must:
+- create an eventfd using eventfd(2);
+- open memory.usage_in_bytes or memory.memsw.usage_in_bytes;
+- write string like "<event_fd> <fd of memory.usage_in_bytes> <threshold>" to
+  cgroup.event_control.
+
+Application will be notified through eventfd when memory usage crosses
+threshold in any direction.
+
+It's applicable for root and non-root cgroup.
+
+10. OOM Control
+
+memory.oom_control file is for OOM notification and other controls.
+
+Memory cgroup implements OOM notifier using the cgroup notification
+API (See cgroups.txt). It allows to register multiple OOM notification
+delivery and gets notification when OOM happens.
+
+To register a notifier, an application must:
+ - create an eventfd using eventfd(2)
+ - open memory.oom_control file
+ - write string like "<event_fd> <fd of memory.oom_control>" to
+   cgroup.event_control
+
+The application will be notified through eventfd when OOM happens.
+OOM notification doesn't work for the root cgroup.
+
+You can disable the OOM-killer by writing "1" to memory.oom_control file, as:
+
+       #echo 1 > memory.oom_control
+
+If OOM-killer is disabled, tasks under cgroup will hang/sleep
+in memory cgroup's OOM-waitqueue when they request accountable memory.
+
+For running them, you have to relax the memory cgroup's OOM status by
+       * enlarge limit or reduce usage.
+To reduce usage,
+       * kill some tasks.
+       * move some tasks to other group with account migration.
+       * remove some files (on tmpfs?)
+
+Then, stopped tasks will work again.
+
+At reading, current status of OOM is shown.
+       oom_kill_disable 0 or 1 (if 1, oom-killer is disabled)
+       under_oom        0 or 1 (if 1, the memory cgroup is under OOM, tasks may
+                                be stopped.)
+
+11. Memory Pressure
+
+The pressure level notifications can be used to monitor the memory
+allocation cost; based on the pressure, applications can implement
+different strategies of managing their memory resources. The pressure
+levels are defined as following:
+
+The "low" level means that the system is reclaiming memory for new
+allocations. Monitoring this reclaiming activity might be useful for
+maintaining cache level. Upon notification, the program (typically
+"Activity Manager") might analyze vmstat and act in advance (i.e.
+prematurely shutdown unimportant services).
+
+The "medium" level means that the system is experiencing medium memory
+pressure, the system might be making swap, paging out active file caches,
+etc. Upon this event applications may decide to further analyze
+vmstat/zoneinfo/memcg or internal memory usage statistics and free any
+resources that can be easily reconstructed or re-read from a disk.
+
+The "critical" level means that the system is actively thrashing, it is
+about to out of memory (OOM) or even the in-kernel OOM killer is on its
+way to trigger. Applications should do whatever they can to help the
+system. It might be too late to consult with vmstat or any other
+statistics, so it's advisable to take an immediate action.
+
+The events are propagated upward until the event is handled, i.e. the
+events are not pass-through. Here is what this means: for example you have
+three cgroups: A->B->C. Now you set up an event listener on cgroups A, B
+and C, and suppose group C experiences some pressure. In this situation,
+only group C will receive the notification, i.e. groups A and B will not
+receive it. This is done to avoid excessive "broadcasting" of messages,
+which disturbs the system and which is especially bad if we are low on
+memory or thrashing. So, organize the cgroups wisely, or propagate the
+events manually (or, ask us to implement the pass-through events,
+explaining why would you need them.)
+
+The file memory.pressure_level is only used to setup an eventfd. To
+register a notification, an application must:
+
+- create an eventfd using eventfd(2);
+- open memory.pressure_level;
+- write string like "<event_fd> <fd of memory.pressure_level> <level>"
+  to cgroup.event_control.
+
+Application will be notified through eventfd when memory pressure is at
+the specific level (or higher). Read/write operations to
+memory.pressure_level are no implemented.
+
+Test:
+
+   Here is a small script example that makes a new cgroup, sets up a
+   memory limit, sets up a notification in the cgroup and then makes child
+   cgroup experience a critical pressure:
+
+   # cd /sys/fs/cgroup/memory/
+   # mkdir foo
+   # cd foo
+   # cgroup_event_listener memory.pressure_level low &
+   # echo 8000000 > memory.limit_in_bytes
+   # echo 8000000 > memory.memsw.limit_in_bytes
+   # echo $$ > tasks
+   # dd if=/dev/zero | read x
+
+   (Expect a bunch of notifications, and eventually, the oom-killer will
+   trigger.)
+
+12. TODO
+
+1. Make per-cgroup scanner reclaim not-shared pages first
+2. Teach controller to account for shared-pages
+3. Start reclamation in the background when the limit is
+   not yet hit but the usage is getting closer
+
+Summary
+
+Overall, the memory controller has been a stable controller and has been
+commented and discussed quite extensively in the community.
+
+References
+
+1. Singh, Balbir. RFC: Memory Controller, http://lwn.net/Articles/206697/
+2. Singh, Balbir. Memory Controller (RSS Control),
+   http://lwn.net/Articles/222762/
+3. Emelianov, Pavel. Resource controllers based on process cgroups
+   http://lkml.org/lkml/2007/3/6/198
+4. Emelianov, Pavel. RSS controller based on process cgroups (v2)
+   http://lkml.org/lkml/2007/4/9/78
+5. Emelianov, Pavel. RSS controller based on process cgroups (v3)
+   http://lkml.org/lkml/2007/5/30/244
+6. Menage, Paul. Control Groups v10, http://lwn.net/Articles/236032/
+7. Vaidyanathan, Srinivasan, Control Groups: Pagecache accounting and control
+   subsystem (v3), http://lwn.net/Articles/235534/
+8. Singh, Balbir. RSS controller v2 test results (lmbench),
+   http://lkml.org/lkml/2007/5/17/232
+9. Singh, Balbir. RSS controller v2 AIM9 results
+   http://lkml.org/lkml/2007/5/18/1
+10. Singh, Balbir. Memory controller v6 test results,
+    http://lkml.org/lkml/2007/8/19/36
+11. Singh, Balbir. Memory controller introduction (v6),
+    http://lkml.org/lkml/2007/8/17/69
+12. Corbet, Jonathan, Controlling memory use in cgroups,
+    http://lwn.net/Articles/243795/
diff --git a/Documentation/cgroup-v1/net_cls.txt b/Documentation/cgroup-v1/net_cls.txt
new file mode 100644 (file)
index 0000000..ec18234
--- /dev/null
@@ -0,0 +1,39 @@
+Network classifier cgroup
+-------------------------
+
+The Network classifier cgroup provides an interface to
+tag network packets with a class identifier (classid).
+
+The Traffic Controller (tc) can be used to assign
+different priorities to packets from different cgroups.
+Also, Netfilter (iptables) can use this tag to perform
+actions on such packets.
+
+Creating a net_cls cgroups instance creates a net_cls.classid file.
+This net_cls.classid value is initialized to 0.
+
+You can write hexadecimal values to net_cls.classid; the format for these
+values is 0xAAAABBBB; AAAA is the major handle number and BBBB
+is the minor handle number.
+Reading net_cls.classid yields a decimal result.
+
+Example:
+mkdir /sys/fs/cgroup/net_cls
+mount -t cgroup -onet_cls net_cls /sys/fs/cgroup/net_cls
+mkdir /sys/fs/cgroup/net_cls/0
+echo 0x100001 >  /sys/fs/cgroup/net_cls/0/net_cls.classid
+       - setting a 10:1 handle.
+
+cat /sys/fs/cgroup/net_cls/0/net_cls.classid
+1048577
+
+configuring tc:
+tc qdisc add dev eth0 root handle 10: htb
+
+tc class add dev eth0 parent 10: classid 10:1 htb rate 40mbit
+ - creating traffic class 10:1
+
+tc filter add dev eth0 parent 10: protocol ip prio 10 handle 1: cgroup
+
+configuring iptables, basic example:
+iptables -A OUTPUT -m cgroup ! --cgroup 0x100001 -j DROP
diff --git a/Documentation/cgroup-v1/net_prio.txt b/Documentation/cgroup-v1/net_prio.txt
new file mode 100644 (file)
index 0000000..a82cbd2
--- /dev/null
@@ -0,0 +1,55 @@
+Network priority cgroup
+-------------------------
+
+The Network priority cgroup provides an interface to allow an administrator to
+dynamically set the priority of network traffic generated by various
+applications
+
+Nominally, an application would set the priority of its traffic via the
+SO_PRIORITY socket option.  This however, is not always possible because:
+
+1) The application may not have been coded to set this value
+2) The priority of application traffic is often a site-specific administrative
+   decision rather than an application defined one.
+
+This cgroup allows an administrator to assign a process to a group which defines
+the priority of egress traffic on a given interface. Network priority groups can
+be created by first mounting the cgroup filesystem.
+
+# mount -t cgroup -onet_prio none /sys/fs/cgroup/net_prio
+
+With the above step, the initial group acting as the parent accounting group
+becomes visible at '/sys/fs/cgroup/net_prio'.  This group includes all tasks in
+the system. '/sys/fs/cgroup/net_prio/tasks' lists the tasks in this cgroup.
+
+Each net_prio cgroup contains two files that are subsystem specific
+
+net_prio.prioidx
+This file is read-only, and is simply informative.  It contains a unique integer
+value that the kernel uses as an internal representation of this cgroup.
+
+net_prio.ifpriomap
+This file contains a map of the priorities assigned to traffic originating from
+processes in this group and egressing the system on various interfaces. It
+contains a list of tuples in the form <ifname priority>.  Contents of this file
+can be modified by echoing a string into the file using the same tuple format.
+for example:
+
+echo "eth0 5" > /sys/fs/cgroups/net_prio/iscsi/net_prio.ifpriomap
+
+This command would force any traffic originating from processes belonging to the
+iscsi net_prio cgroup and egressing on interface eth0 to have the priority of
+said traffic set to the value 5. The parent accounting group also has a
+writeable 'net_prio.ifpriomap' file that can be used to set a system default
+priority.
+
+Priorities are set immediately prior to queueing a frame to the device
+queueing discipline (qdisc) so priorities will be assigned prior to the hardware
+queue selection being made.
+
+One usage for the net_prio cgroup is with mqprio qdisc allowing application
+traffic to be steered to hardware/driver based traffic classes. These mappings
+can then be managed by administrators or other networking protocols such as
+DCBX.
+
+A new net_prio cgroup inherits the parent's configuration.
diff --git a/Documentation/cgroup-v1/pids.txt b/Documentation/cgroup-v1/pids.txt
new file mode 100644 (file)
index 0000000..1a078b5
--- /dev/null
@@ -0,0 +1,85 @@
+                                                  Process Number Controller
+                                                  =========================
+
+Abstract
+--------
+
+The process number controller is used to allow a cgroup hierarchy to stop any
+new tasks from being fork()'d or clone()'d after a certain limit is reached.
+
+Since it is trivial to hit the task limit without hitting any kmemcg limits in
+place, PIDs are a fundamental resource. As such, PID exhaustion must be
+preventable in the scope of a cgroup hierarchy by allowing resource limiting of
+the number of tasks in a cgroup.
+
+Usage
+-----
+
+In order to use the `pids` controller, set the maximum number of tasks in
+pids.max (this is not available in the root cgroup for obvious reasons). The
+number of processes currently in the cgroup is given by pids.current.
+
+Organisational operations are not blocked by cgroup policies, so it is possible
+to have pids.current > pids.max. This can be done by either setting the limit to
+be smaller than pids.current, or attaching enough processes to the cgroup such
+that pids.current > pids.max. However, it is not possible to violate a cgroup
+policy through fork() or clone(). fork() and clone() will return -EAGAIN if the
+creation of a new process would cause a cgroup policy to be violated.
+
+To set a cgroup to have no limit, set pids.max to "max". This is the default for
+all new cgroups (N.B. that PID limits are hierarchical, so the most stringent
+limit in the hierarchy is followed).
+
+pids.current tracks all child cgroup hierarchies, so parent/pids.current is a
+superset of parent/child/pids.current.
+
+Example
+-------
+
+First, we mount the pids controller:
+# mkdir -p /sys/fs/cgroup/pids
+# mount -t cgroup -o pids none /sys/fs/cgroup/pids
+
+Then we create a hierarchy, set limits and attach processes to it:
+# mkdir -p /sys/fs/cgroup/pids/parent/child
+# echo 2 > /sys/fs/cgroup/pids/parent/pids.max
+# echo $$ > /sys/fs/cgroup/pids/parent/cgroup.procs
+# cat /sys/fs/cgroup/pids/parent/pids.current
+2
+#
+
+It should be noted that attempts to overcome the set limit (2 in this case) will
+fail:
+
+# cat /sys/fs/cgroup/pids/parent/pids.current
+2
+# ( /bin/echo "Here's some processes for you." | cat )
+sh: fork: Resource temporary unavailable
+#
+
+Even if we migrate to a child cgroup (which doesn't have a set limit), we will
+not be able to overcome the most stringent limit in the hierarchy (in this case,
+parent's):
+
+# echo $$ > /sys/fs/cgroup/pids/parent/child/cgroup.procs
+# cat /sys/fs/cgroup/pids/parent/pids.current
+2
+# cat /sys/fs/cgroup/pids/parent/child/pids.current
+2
+# cat /sys/fs/cgroup/pids/parent/child/pids.max
+max
+# ( /bin/echo "Here's some processes for you." | cat )
+sh: fork: Resource temporary unavailable
+#
+
+We can set a limit that is smaller than pids.current, which will stop any new
+processes from being forked at all (note that the shell itself counts towards
+pids.current):
+
+# echo 1 > /sys/fs/cgroup/pids/parent/pids.max
+# /bin/echo "We can't even spawn a single process now."
+sh: fork: Resource temporary unavailable
+# echo 0 > /sys/fs/cgroup/pids/parent/pids.max
+# /bin/echo "We can't even spawn a single process now."
+sh: fork: Resource temporary unavailable
+#
diff --git a/Documentation/cgroup-v2.txt b/Documentation/cgroup-v2.txt
new file mode 100644 (file)
index 0000000..31d1f7b
--- /dev/null
@@ -0,0 +1,1293 @@
+
+Control Group v2
+
+October, 2015          Tejun Heo <tj@kernel.org>
+
+This is the authoritative documentation on the design, interface and
+conventions of cgroup v2.  It describes all userland-visible aspects
+of cgroup including core and specific controller behaviors.  All
+future changes must be reflected in this document.  Documentation for
+v1 is available under Documentation/cgroup-legacy/.
+
+CONTENTS
+
+1. Introduction
+  1-1. Terminology
+  1-2. What is cgroup?
+2. Basic Operations
+  2-1. Mounting
+  2-2. Organizing Processes
+  2-3. [Un]populated Notification
+  2-4. Controlling Controllers
+    2-4-1. Enabling and Disabling
+    2-4-2. Top-down Constraint
+    2-4-3. No Internal Process Constraint
+  2-5. Delegation
+    2-5-1. Model of Delegation
+    2-5-2. Delegation Containment
+  2-6. Guidelines
+    2-6-1. Organize Once and Control
+    2-6-2. Avoid Name Collisions
+3. Resource Distribution Models
+  3-1. Weights
+  3-2. Limits
+  3-3. Protections
+  3-4. Allocations
+4. Interface Files
+  4-1. Format
+  4-2. Conventions
+  4-3. Core Interface Files
+5. Controllers
+  5-1. CPU
+    5-1-1. CPU Interface Files
+  5-2. Memory
+    5-2-1. Memory Interface Files
+    5-2-2. Usage Guidelines
+    5-2-3. Memory Ownership
+  5-3. IO
+    5-3-1. IO Interface Files
+    5-3-2. Writeback
+P. Information on Kernel Programming
+  P-1. Filesystem Support for Writeback
+D. Deprecated v1 Core Features
+R. Issues with v1 and Rationales for v2
+  R-1. Multiple Hierarchies
+  R-2. Thread Granularity
+  R-3. Competition Between Inner Nodes and Threads
+  R-4. Other Interface Issues
+  R-5. Controller Issues and Remedies
+    R-5-1. Memory
+
+
+1. Introduction
+
+1-1. Terminology
+
+"cgroup" stands for "control group" and is never capitalized.  The
+singular form is used to designate the whole feature and also as a
+qualifier as in "cgroup controllers".  When explicitly referring to
+multiple individual control groups, the plural form "cgroups" is used.
+
+
+1-2. What is cgroup?
+
+cgroup is a mechanism to organize processes hierarchically and
+distribute system resources along the hierarchy in a controlled and
+configurable manner.
+
+cgroup is largely composed of two parts - the core and controllers.
+cgroup core is primarily responsible for hierarchically organizing
+processes.  A cgroup controller is usually responsible for
+distributing a specific type of system resource along the hierarchy
+although there are utility controllers which serve purposes other than
+resource distribution.
+
+cgroups form a tree structure and every process in the system belongs
+to one and only one cgroup.  All threads of a process belong to the
+same cgroup.  On creation, all processes are put in the cgroup that
+the parent process belongs to at the time.  A process can be migrated
+to another cgroup.  Migration of a process doesn't affect already
+existing descendant processes.
+
+Following certain structural constraints, controllers may be enabled or
+disabled selectively on a cgroup.  All controller behaviors are
+hierarchical - if a controller is enabled on a cgroup, it affects all
+processes which belong to the cgroups consisting the inclusive
+sub-hierarchy of the cgroup.  When a controller is enabled on a nested
+cgroup, it always restricts the resource distribution further.  The
+restrictions set closer to the root in the hierarchy can not be
+overridden from further away.
+
+
+2. Basic Operations
+
+2-1. Mounting
+
+Unlike v1, cgroup v2 has only single hierarchy.  The cgroup v2
+hierarchy can be mounted with the following mount command.
+
+  # mount -t cgroup2 none $MOUNT_POINT
+
+cgroup2 filesystem has the magic number 0x63677270 ("cgrp").  All
+controllers which support v2 and are not bound to a v1 hierarchy are
+automatically bound to the v2 hierarchy and show up at the root.
+Controllers which are not in active use in the v2 hierarchy can be
+bound to other hierarchies.  This allows mixing v2 hierarchy with the
+legacy v1 multiple hierarchies in a fully backward compatible way.
+
+A controller can be moved across hierarchies only after the controller
+is no longer referenced in its current hierarchy.  Because per-cgroup
+controller states are destroyed asynchronously and controllers may
+have lingering references, a controller may not show up immediately on
+the v2 hierarchy after the final umount of the previous hierarchy.
+Similarly, a controller should be fully disabled to be moved out of
+the unified hierarchy and it may take some time for the disabled
+controller to become available for other hierarchies; furthermore, due
+to inter-controller dependencies, other controllers may need to be
+disabled too.
+
+While useful for development and manual configurations, moving
+controllers dynamically between the v2 and other hierarchies is
+strongly discouraged for production use.  It is recommended to decide
+the hierarchies and controller associations before starting using the
+controllers after system boot.
+
+
+2-2. Organizing Processes
+
+Initially, only the root cgroup exists to which all processes belong.
+A child cgroup can be created by creating a sub-directory.
+
+  # mkdir $CGROUP_NAME
+
+A given cgroup may have multiple child cgroups forming a tree
+structure.  Each cgroup has a read-writable interface file
+"cgroup.procs".  When read, it lists the PIDs of all processes which
+belong to the cgroup one-per-line.  The PIDs are not ordered and the
+same PID may show up more than once if the process got moved to
+another cgroup and then back or the PID got recycled while reading.
+
+A process can be migrated into a cgroup by writing its PID to the
+target cgroup's "cgroup.procs" file.  Only one process can be migrated
+on a single write(2) call.  If a process is composed of multiple
+threads, writing the PID of any thread migrates all threads of the
+process.
+
+When a process forks a child process, the new process is born into the
+cgroup that the forking process belongs to at the time of the
+operation.  After exit, a process stays associated with the cgroup
+that it belonged to at the time of exit until it's reaped; however, a
+zombie process does not appear in "cgroup.procs" and thus can't be
+moved to another cgroup.
+
+A cgroup which doesn't have any children or live processes can be
+destroyed by removing the directory.  Note that a cgroup which doesn't
+have any children and is associated only with zombie processes is
+considered empty and can be removed.
+
+  # rmdir $CGROUP_NAME
+
+"/proc/$PID/cgroup" lists a process's cgroup membership.  If legacy
+cgroup is in use in the system, this file may contain multiple lines,
+one for each hierarchy.  The entry for cgroup v2 is always in the
+format "0::$PATH".
+
+  # cat /proc/842/cgroup
+  ...
+  0::/test-cgroup/test-cgroup-nested
+
+If the process becomes a zombie and the cgroup it was associated with
+is removed subsequently, " (deleted)" is appended to the path.
+
+  # cat /proc/842/cgroup
+  ...
+  0::/test-cgroup/test-cgroup-nested (deleted)
+
+
+2-3. [Un]populated Notification
+
+Each non-root cgroup has a "cgroup.events" file which contains
+"populated" field indicating whether the cgroup's sub-hierarchy has
+live processes in it.  Its value is 0 if there is no live process in
+the cgroup and its descendants; otherwise, 1.  poll and [id]notify
+events are triggered when the value changes.  This can be used, for
+example, to start a clean-up operation after all processes of a given
+sub-hierarchy have exited.  The populated state updates and
+notifications are recursive.  Consider the following sub-hierarchy
+where the numbers in the parentheses represent the numbers of processes
+in each cgroup.
+
+  A(4) - B(0) - C(1)
+              \ D(0)
+
+A, B and C's "populated" fields would be 1 while D's 0.  After the one
+process in C exits, B and C's "populated" fields would flip to "0" and
+file modified events will be generated on the "cgroup.events" files of
+both cgroups.
+
+
+2-4. Controlling Controllers
+
+2-4-1. Enabling and Disabling
+
+Each cgroup has a "cgroup.controllers" file which lists all
+controllers available for the cgroup to enable.
+
+  # cat cgroup.controllers
+  cpu io memory
+
+No controller is enabled by default.  Controllers can be enabled and
+disabled by writing to the "cgroup.subtree_control" file.
+
+  # echo "+cpu +memory -io" > cgroup.subtree_control
+
+Only controllers which are listed in "cgroup.controllers" can be
+enabled.  When multiple operations are specified as above, either they
+all succeed or fail.  If multiple operations on the same controller
+are specified, the last one is effective.
+
+Enabling a controller in a cgroup indicates that the distribution of
+the target resource across its immediate children will be controlled.
+Consider the following sub-hierarchy.  The enabled controllers are
+listed in parentheses.
+
+  A(cpu,memory) - B(memory) - C()
+                            \ D()
+
+As A has "cpu" and "memory" enabled, A will control the distribution
+of CPU cycles and memory to its children, in this case, B.  As B has
+"memory" enabled but not "CPU", C and D will compete freely on CPU
+cycles but their division of memory available to B will be controlled.
+
+As a controller regulates the distribution of the target resource to
+the cgroup's children, enabling it creates the controller's interface
+files in the child cgroups.  In the above example, enabling "cpu" on B
+would create the "cpu." prefixed controller interface files in C and
+D.  Likewise, disabling "memory" from B would remove the "memory."
+prefixed controller interface files from C and D.  This means that the
+controller interface files - anything which doesn't start with
+"cgroup." are owned by the parent rather than the cgroup itself.
+
+
+2-4-2. Top-down Constraint
+
+Resources are distributed top-down and a cgroup can further distribute
+a resource only if the resource has been distributed to it from the
+parent.  This means that all non-root "cgroup.subtree_control" files
+can only contain controllers which are enabled in the parent's
+"cgroup.subtree_control" file.  A controller can be enabled only if
+the parent has the controller enabled and a controller can't be
+disabled if one or more children have it enabled.
+
+
+2-4-3. No Internal Process Constraint
+
+Non-root cgroups can only distribute resources to their children when
+they don't have any processes of their own.  In other words, only
+cgroups which don't contain any processes can have controllers enabled
+in their "cgroup.subtree_control" files.
+
+This guarantees that, when a controller is looking at the part of the
+hierarchy which has it enabled, processes are always only on the
+leaves.  This rules out situations where child cgroups compete against
+internal processes of the parent.
+
+The root cgroup is exempt from this restriction.  Root contains
+processes and anonymous resource consumption which can't be associated
+with any other cgroups and requires special treatment from most
+controllers.  How resource consumption in the root cgroup is governed
+is up to each controller.
+
+Note that the restriction doesn't get in the way if there is no
+enabled controller in the cgroup's "cgroup.subtree_control".  This is
+important as otherwise it wouldn't be possible to create children of a
+populated cgroup.  To control resource distribution of a cgroup, the
+cgroup must create children and transfer all its processes to the
+children before enabling controllers in its "cgroup.subtree_control"
+file.
+
+
+2-5. Delegation
+
+2-5-1. Model of Delegation
+
+A cgroup can be delegated to a less privileged user by granting write
+access of the directory and its "cgroup.procs" file to the user.  Note
+that resource control interface files in a given directory control the
+distribution of the parent's resources and thus must not be delegated
+along with the directory.
+
+Once delegated, the user can build sub-hierarchy under the directory,
+organize processes as it sees fit and further distribute the resources
+it received from the parent.  The limits and other settings of all
+resource controllers are hierarchical and regardless of what happens
+in the delegated sub-hierarchy, nothing can escape the resource
+restrictions imposed by the parent.
+
+Currently, cgroup doesn't impose any restrictions on the number of
+cgroups in or nesting depth of a delegated sub-hierarchy; however,
+this may be limited explicitly in the future.
+
+
+2-5-2. Delegation Containment
+
+A delegated sub-hierarchy is contained in the sense that processes
+can't be moved into or out of the sub-hierarchy by the delegatee.  For
+a process with a non-root euid to migrate a target process into a
+cgroup by writing its PID to the "cgroup.procs" file, the following
+conditions must be met.
+
+- The writer's euid must match either uid or suid of the target process.
+
+- The writer must have write access to the "cgroup.procs" file.
+
+- The writer must have write access to the "cgroup.procs" file of the
+  common ancestor of the source and destination cgroups.
+
+The above three constraints ensure that while a delegatee may migrate
+processes around freely in the delegated sub-hierarchy it can't pull
+in from or push out to outside the sub-hierarchy.
+
+For an example, let's assume cgroups C0 and C1 have been delegated to
+user U0 who created C00, C01 under C0 and C10 under C1 as follows and
+all processes under C0 and C1 belong to U0.
+
+  ~~~~~~~~~~~~~ - C0 - C00
+  ~ cgroup    ~      \ C01
+  ~ hierarchy ~
+  ~~~~~~~~~~~~~ - C1 - C10
+
+Let's also say U0 wants to write the PID of a process which is
+currently in C10 into "C00/cgroup.procs".  U0 has write access to the
+file and uid match on the process; however, the common ancestor of the
+source cgroup C10 and the destination cgroup C00 is above the points
+of delegation and U0 would not have write access to its "cgroup.procs"
+files and thus the write will be denied with -EACCES.
+
+
+2-6. Guidelines
+
+2-6-1. Organize Once and Control
+
+Migrating a process across cgroups is a relatively expensive operation
+and stateful resources such as memory are not moved together with the
+process.  This is an explicit design decision as there often exist
+inherent trade-offs between migration and various hot paths in terms
+of synchronization cost.
+
+As such, migrating processes across cgroups frequently as a means to
+apply different resource restrictions is discouraged.  A workload
+should be assigned to a cgroup according to the system's logical and
+resource structure once on start-up.  Dynamic adjustments to resource
+distribution can be made by changing controller configuration through
+the interface files.
+
+
+2-6-2. Avoid Name Collisions
+
+Interface files for a cgroup and its children cgroups occupy the same
+directory and it is possible to create children cgroups which collide
+with interface files.
+
+All cgroup core interface files are prefixed with "cgroup." and each
+controller's interface files are prefixed with the controller name and
+a dot.  A controller's name is composed of lower case alphabets and
+'_'s but never begins with an '_' so it can be used as the prefix
+character for collision avoidance.  Also, interface file names won't
+start or end with terms which are often used in categorizing workloads
+such as job, service, slice, unit or workload.
+
+cgroup doesn't do anything to prevent name collisions and it's the
+user's responsibility to avoid them.
+
+
+3. Resource Distribution Models
+
+cgroup controllers implement several resource distribution schemes
+depending on the resource type and expected use cases.  This section
+describes major schemes in use along with their expected behaviors.
+
+
+3-1. Weights
+
+A parent's resource is distributed by adding up the weights of all
+active children and giving each the fraction matching the ratio of its
+weight against the sum.  As only children which can make use of the
+resource at the moment participate in the distribution, this is
+work-conserving.  Due to the dynamic nature, this model is usually
+used for stateless resources.
+
+All weights are in the range [1, 10000] with the default at 100.  This
+allows symmetric multiplicative biases in both directions at fine
+enough granularity while staying in the intuitive range.
+
+As long as the weight is in range, all configuration combinations are
+valid and there is no reason to reject configuration changes or
+process migrations.
+
+"cpu.weight" proportionally distributes CPU cycles to active children
+and is an example of this type.
+
+
+3-2. Limits
+
+A child can only consume upto the configured amount of the resource.
+Limits can be over-committed - the sum of the limits of children can
+exceed the amount of resource available to the parent.
+
+Limits are in the range [0, max] and defaults to "max", which is noop.
+
+As limits can be over-committed, all configuration combinations are
+valid and there is no reason to reject configuration changes or
+process migrations.
+
+"io.max" limits the maximum BPS and/or IOPS that a cgroup can consume
+on an IO device and is an example of this type.
+
+
+3-3. Protections
+
+A cgroup is protected to be allocated upto the configured amount of
+the resource if the usages of all its ancestors are under their
+protected levels.  Protections can be hard guarantees or best effort
+soft boundaries.  Protections can also be over-committed in which case
+only upto the amount available to the parent is protected among
+children.
+
+Protections are in the range [0, max] and defaults to 0, which is
+noop.
+
+As protections can be over-committed, all configuration combinations
+are valid and there is no reason to reject configuration changes or
+process migrations.
+
+"memory.low" implements best-effort memory protection and is an
+example of this type.
+
+
+3-4. Allocations
+
+A cgroup is exclusively allocated a certain amount of a finite
+resource.  Allocations can't be over-committed - the sum of the
+allocations of children can not exceed the amount of resource
+available to the parent.
+
+Allocations are in the range [0, max] and defaults to 0, which is no
+resource.
+
+As allocations can't be over-committed, some configuration
+combinations are invalid and should be rejected.  Also, if the
+resource is mandatory for execution of processes, process migrations
+may be rejected.
+
+"cpu.rt.max" hard-allocates realtime slices and is an example of this
+type.
+
+
+4. Interface Files
+
+4-1. Format
+
+All interface files should be in one of the following formats whenever
+possible.
+
+  New-line separated values
+  (when only one value can be written at once)
+
+       VAL0\n
+       VAL1\n
+       ...
+
+  Space separated values
+  (when read-only or multiple values can be written at once)
+
+       VAL0 VAL1 ...\n
+
+  Flat keyed
+
+       KEY0 VAL0\n
+       KEY1 VAL1\n
+       ...
+
+  Nested keyed
+
+       KEY0 SUB_KEY0=VAL00 SUB_KEY1=VAL01...
+       KEY1 SUB_KEY0=VAL10 SUB_KEY1=VAL11...
+       ...
+
+For a writable file, the format for writing should generally match
+reading; however, controllers may allow omitting later fields or
+implement restricted shortcuts for most common use cases.
+
+For both flat and nested keyed files, only the values for a single key
+can be written at a time.  For nested keyed files, the sub key pairs
+may be specified in any order and not all pairs have to be specified.
+
+
+4-2. Conventions
+
+- Settings for a single feature should be contained in a single file.
+
+- The root cgroup should be exempt from resource control and thus
+  shouldn't have resource control interface files.  Also,
+  informational files on the root cgroup which end up showing global
+  information available elsewhere shouldn't exist.
+
+- If a controller implements weight based resource distribution, its
+  interface file should be named "weight" and have the range [1,
+  10000] with 100 as the default.  The values are chosen to allow
+  enough and symmetric bias in both directions while keeping it
+  intuitive (the default is 100%).
+
+- If a controller implements an absolute resource guarantee and/or
+  limit, the interface files should be named "min" and "max"
+  respectively.  If a controller implements best effort resource
+  guarantee and/or limit, the interface files should be named "low"
+  and "high" respectively.
+
+  In the above four control files, the special token "max" should be
+  used to represent upward infinity for both reading and writing.
+
+- If a setting has a configurable default value and keyed specific
+  overrides, the default entry should be keyed with "default" and
+  appear as the first entry in the file.
+
+  The default value can be updated by writing either "default $VAL" or
+  "$VAL".
+
+  When writing to update a specific override, "default" can be used as
+  the value to indicate removal of the override.  Override entries
+  with "default" as the value must not appear when read.
+
+  For example, a setting which is keyed by major:minor device numbers
+  with integer values may look like the following.
+
+    # cat cgroup-example-interface-file
+    default 150
+    8:0 300
+
+  The default value can be updated by
+
+    # echo 125 > cgroup-example-interface-file
+
+  or
+
+    # echo "default 125" > cgroup-example-interface-file
+
+  An override can be set by
+
+    # echo "8:16 170" > cgroup-example-interface-file
+
+  and cleared by
+
+    # echo "8:0 default" > cgroup-example-interface-file
+    # cat cgroup-example-interface-file
+    default 125
+    8:16 170
+
+- For events which are not very high frequency, an interface file
+  "events" should be created which lists event key value pairs.
+  Whenever a notifiable event happens, file modified event should be
+  generated on the file.
+
+
+4-3. Core Interface Files
+
+All cgroup core files are prefixed with "cgroup."
+
+  cgroup.procs
+
+       A read-write new-line separated values file which exists on
+       all cgroups.
+
+       When read, it lists the PIDs of all processes which belong to
+       the cgroup one-per-line.  The PIDs are not ordered and the
+       same PID may show up more than once if the process got moved
+       to another cgroup and then back or the PID got recycled while
+       reading.
+
+       A PID can be written to migrate the process associated with
+       the PID to the cgroup.  The writer should match all of the
+       following conditions.
+
+       - Its euid is either root or must match either uid or suid of
+          the target process.
+
+       - It must have write access to the "cgroup.procs" file.
+
+       - It must have write access to the "cgroup.procs" file of the
+         common ancestor of the source and destination cgroups.
+
+       When delegating a sub-hierarchy, write access to this file
+       should be granted along with the containing directory.
+
+  cgroup.controllers
+
+       A read-only space separated values file which exists on all
+       cgroups.
+
+       It shows space separated list of all controllers available to
+       the cgroup.  The controllers are not ordered.
+
+  cgroup.subtree_control
+
+       A read-write space separated values file which exists on all
+       cgroups.  Starts out empty.
+
+       When read, it shows space separated list of the controllers
+       which are enabled to control resource distribution from the
+       cgroup to its children.
+
+       Space separated list of controllers prefixed with '+' or '-'
+       can be written to enable or disable controllers.  A controller
+       name prefixed with '+' enables the controller and '-'
+       disables.  If a controller appears more than once on the list,
+       the last one is effective.  When multiple enable and disable
+       operations are specified, either all succeed or all fail.
+
+  cgroup.events
+
+       A read-only flat-keyed file which exists on non-root cgroups.
+       The following entries are defined.  Unless specified
+       otherwise, a value change in this file generates a file
+       modified event.
+
+         populated
+
+               1 if the cgroup or its descendants contains any live
+               processes; otherwise, 0.
+
+
+5. Controllers
+
+5-1. CPU
+
+[NOTE: The interface for the cpu controller hasn't been merged yet]
+
+The "cpu" controllers regulates distribution of CPU cycles.  This
+controller implements weight and absolute bandwidth limit models for
+normal scheduling policy and absolute bandwidth allocation model for
+realtime scheduling policy.
+
+
+5-1-1. CPU Interface Files
+
+All time durations are in microseconds.
+
+  cpu.stat
+
+       A read-only flat-keyed file which exists on non-root cgroups.
+
+       It reports the following six stats.
+
+         usage_usec
+         user_usec
+         system_usec
+         nr_periods
+         nr_throttled
+         throttled_usec
+
+  cpu.weight
+
+       A read-write single value file which exists on non-root
+       cgroups.  The default is "100".
+
+       The weight in the range [1, 10000].
+
+  cpu.max
+
+       A read-write two value file which exists on non-root cgroups.
+       The default is "max 100000".
+
+       The maximum bandwidth limit.  It's in the following format.
+
+         $MAX $PERIOD
+
+       which indicates that the group may consume upto $MAX in each
+       $PERIOD duration.  "max" for $MAX indicates no limit.  If only
+       one number is written, $MAX is updated.
+
+  cpu.rt.max
+
+  [NOTE: The semantics of this file is still under discussion and the
+   interface hasn't been merged yet]
+
+       A read-write two value file which exists on all cgroups.
+       The default is "0 100000".
+
+       The maximum realtime runtime allocation.  Over-committing
+       configurations are disallowed and process migrations are
+       rejected if not enough bandwidth is available.  It's in the
+       following format.
+
+         $MAX $PERIOD
+
+       which indicates that the group may consume upto $MAX in each
+       $PERIOD duration.  If only one number is written, $MAX is
+       updated.
+
+
+5-2. Memory
+
+The "memory" controller regulates distribution of memory.  Memory is
+stateful and implements both limit and protection models.  Due to the
+intertwining between memory usage and reclaim pressure and the
+stateful nature of memory, the distribution model is relatively
+complex.
+
+While not completely water-tight, all major memory usages by a given
+cgroup are tracked so that the total memory consumption can be
+accounted and controlled to a reasonable extent.  Currently, the
+following types of memory usages are tracked.
+
+- Userland memory - page cache and anonymous memory.
+
+- Kernel data structures such as dentries and inodes.
+
+- TCP socket buffers.
+
+The above list may expand in the future for better coverage.
+
+
+5-2-1. Memory Interface Files
+
+All memory amounts are in bytes.  If a value which is not aligned to
+PAGE_SIZE is written, the value may be rounded up to the closest
+PAGE_SIZE multiple when read back.
+
+  memory.current
+
+       A read-only single value file which exists on non-root
+       cgroups.
+
+       The total amount of memory currently being used by the cgroup
+       and its descendants.
+
+  memory.low
+
+       A read-write single value file which exists on non-root
+       cgroups.  The default is "0".
+
+       Best-effort memory protection.  If the memory usages of a
+       cgroup and all its ancestors are below their low boundaries,
+       the cgroup's memory won't be reclaimed unless memory can be
+       reclaimed from unprotected cgroups.
+
+       Putting more memory than generally available under this
+       protection is discouraged.
+
+  memory.high
+
+       A read-write single value file which exists on non-root
+       cgroups.  The default is "max".
+
+       Memory usage throttle limit.  This is the main mechanism to
+       control memory usage of a cgroup.  If a cgroup's usage goes
+       over the high boundary, the processes of the cgroup are
+       throttled and put under heavy reclaim pressure.
+
+       Going over the high limit never invokes the OOM killer and
+       under extreme conditions the limit may be breached.
+
+  memory.max
+
+       A read-write single value file which exists on non-root
+       cgroups.  The default is "max".
+
+       Memory usage hard limit.  This is the final protection
+       mechanism.  If a cgroup's memory usage reaches this limit and
+       can't be reduced, the OOM killer is invoked in the cgroup.
+       Under certain circumstances, the usage may go over the limit
+       temporarily.
+
+       This is the ultimate protection mechanism.  As long as the
+       high limit is used and monitored properly, this limit's
+       utility is limited to providing the final safety net.
+
+  memory.events
+
+       A read-only flat-keyed file which exists on non-root cgroups.
+       The following entries are defined.  Unless specified
+       otherwise, a value change in this file generates a file
+       modified event.
+
+         low
+
+               The number of times the cgroup is reclaimed due to
+               high memory pressure even though its usage is under
+               the low boundary.  This usually indicates that the low
+               boundary is over-committed.
+
+         high
+
+               The number of times processes of the cgroup are
+               throttled and routed to perform direct memory reclaim
+               because the high memory boundary was exceeded.  For a
+               cgroup whose memory usage is capped by the high limit
+               rather than global memory pressure, this event's
+               occurrences are expected.
+
+         max
+
+               The number of times the cgroup's memory usage was
+               about to go over the max boundary.  If direct reclaim
+               fails to bring it down, the OOM killer is invoked.
+
+         oom
+
+               The number of times the OOM killer has been invoked in
+               the cgroup.  This may not exactly match the number of
+               processes killed but should generally be close.
+
+
+5-2-2. General Usage
+
+"memory.high" is the main mechanism to control memory usage.
+Over-committing on high limit (sum of high limits > available memory)
+and letting global memory pressure to distribute memory according to
+usage is a viable strategy.
+
+Because breach of the high limit doesn't trigger the OOM killer but
+throttles the offending cgroup, a management agent has ample
+opportunities to monitor and take appropriate actions such as granting
+more memory or terminating the workload.
+
+Determining whether a cgroup has enough memory is not trivial as
+memory usage doesn't indicate whether the workload can benefit from
+more memory.  For example, a workload which writes data received from
+network to a file can use all available memory but can also operate as
+performant with a small amount of memory.  A measure of memory
+pressure - how much the workload is being impacted due to lack of
+memory - is necessary to determine whether a workload needs more
+memory; unfortunately, memory pressure monitoring mechanism isn't
+implemented yet.
+
+
+5-2-3. Memory Ownership
+
+A memory area is charged to the cgroup which instantiated it and stays
+charged to the cgroup until the area is released.  Migrating a process
+to a different cgroup doesn't move the memory usages that it
+instantiated while in the previous cgroup to the new cgroup.
+
+A memory area may be used by processes belonging to different cgroups.
+To which cgroup the area will be charged is in-deterministic; however,
+over time, the memory area is likely to end up in a cgroup which has
+enough memory allowance to avoid high reclaim pressure.
+
+If a cgroup sweeps a considerable amount of memory which is expected
+to be accessed repeatedly by other cgroups, it may make sense to use
+POSIX_FADV_DONTNEED to relinquish the ownership of memory areas
+belonging to the affected files to ensure correct memory ownership.
+
+
+5-3. IO
+
+The "io" controller regulates the distribution of IO resources.  This
+controller implements both weight based and absolute bandwidth or IOPS
+limit distribution; however, weight based distribution is available
+only if cfq-iosched is in use and neither scheme is available for
+blk-mq devices.
+
+
+5-3-1. IO Interface Files
+
+  io.stat
+
+       A read-only nested-keyed file which exists on non-root
+       cgroups.
+
+       Lines are keyed by $MAJ:$MIN device numbers and not ordered.
+       The following nested keys are defined.
+
+         rbytes        Bytes read
+         wbytes        Bytes written
+         rios          Number of read IOs
+         wios          Number of write IOs
+
+       An example read output follows.
+
+         8:16 rbytes=1459200 wbytes=314773504 rios=192 wios=353
+         8:0 rbytes=90430464 wbytes=299008000 rios=8950 wios=1252
+
+  io.weight
+
+       A read-write flat-keyed file which exists on non-root cgroups.
+       The default is "default 100".
+
+       The first line is the default weight applied to devices
+       without specific override.  The rest are overrides keyed by
+       $MAJ:$MIN device numbers and not ordered.  The weights are in
+       the range [1, 10000] and specifies the relative amount IO time
+       the cgroup can use in relation to its siblings.
+
+       The default weight can be updated by writing either "default
+       $WEIGHT" or simply "$WEIGHT".  Overrides can be set by writing
+       "$MAJ:$MIN $WEIGHT" and unset by writing "$MAJ:$MIN default".
+
+       An example read output follows.
+
+         default 100
+         8:16 200
+         8:0 50
+
+  io.max
+
+       A read-write nested-keyed file which exists on non-root
+       cgroups.
+
+       BPS and IOPS based IO limit.  Lines are keyed by $MAJ:$MIN
+       device numbers and not ordered.  The following nested keys are
+       defined.
+
+         rbps          Max read bytes per second
+         wbps          Max write bytes per second
+         riops         Max read IO operations per second
+         wiops         Max write IO operations per second
+
+       When writing, any number of nested key-value pairs can be
+       specified in any order.  "max" can be specified as the value
+       to remove a specific limit.  If the same key is specified
+       multiple times, the outcome is undefined.
+
+       BPS and IOPS are measured in each IO direction and IOs are
+       delayed if limit is reached.  Temporary bursts are allowed.
+
+       Setting read limit at 2M BPS and write at 120 IOPS for 8:16.
+
+         echo "8:16 rbps=2097152 wiops=120" > io.max
+
+       Reading returns the following.
+
+         8:16 rbps=2097152 wbps=max riops=max wiops=120
+
+       Write IOPS limit can be removed by writing the following.
+
+         echo "8:16 wiops=max" > io.max
+
+       Reading now returns the following.
+
+         8:16 rbps=2097152 wbps=max riops=max wiops=max
+
+
+5-3-2. Writeback
+
+Page cache is dirtied through buffered writes and shared mmaps and
+written asynchronously to the backing filesystem by the writeback
+mechanism.  Writeback sits between the memory and IO domains and
+regulates the proportion of dirty memory by balancing dirtying and
+write IOs.
+
+The io controller, in conjunction with the memory controller,
+implements control of page cache writeback IOs.  The memory controller
+defines the memory domain that dirty memory ratio is calculated and
+maintained for and the io controller defines the io domain which
+writes out dirty pages for the memory domain.  Both system-wide and
+per-cgroup dirty memory states are examined and the more restrictive
+of the two is enforced.
+
+cgroup writeback requires explicit support from the underlying
+filesystem.  Currently, cgroup writeback is implemented on ext2, ext4
+and btrfs.  On other filesystems, all writeback IOs are attributed to
+the root cgroup.
+
+There are inherent differences in memory and writeback management
+which affects how cgroup ownership is tracked.  Memory is tracked per
+page while writeback per inode.  For the purpose of writeback, an
+inode is assigned to a cgroup and all IO requests to write dirty pages
+from the inode are attributed to that cgroup.
+
+As cgroup ownership for memory is tracked per page, there can be pages
+which are associated with different cgroups than the one the inode is
+associated with.  These are called foreign pages.  The writeback
+constantly keeps track of foreign pages and, if a particular foreign
+cgroup becomes the majority over a certain period of time, switches
+the ownership of the inode to that cgroup.
+
+While this model is enough for most use cases where a given inode is
+mostly dirtied by a single cgroup even when the main writing cgroup
+changes over time, use cases where multiple cgroups write to a single
+inode simultaneously are not supported well.  In such circumstances, a
+significant portion of IOs are likely to be attributed incorrectly.
+As memory controller assigns page ownership on the first use and
+doesn't update it until the page is released, even if writeback
+strictly follows page ownership, multiple cgroups dirtying overlapping
+areas wouldn't work as expected.  It's recommended to avoid such usage
+patterns.
+
+The sysctl knobs which affect writeback behavior are applied to cgroup
+writeback as follows.
+
+  vm.dirty_background_ratio
+  vm.dirty_ratio
+
+       These ratios apply the same to cgroup writeback with the
+       amount of available memory capped by limits imposed by the
+       memory controller and system-wide clean memory.
+
+  vm.dirty_background_bytes
+  vm.dirty_bytes
+
+       For cgroup writeback, this is calculated into ratio against
+       total available memory and applied the same way as
+       vm.dirty[_background]_ratio.
+
+
+P. Information on Kernel Programming
+
+This section contains kernel programming information in the areas
+where interacting with cgroup is necessary.  cgroup core and
+controllers are not covered.
+
+
+P-1. Filesystem Support for Writeback
+
+A filesystem can support cgroup writeback by updating
+address_space_operations->writepage[s]() to annotate bio's using the
+following two functions.
+
+  wbc_init_bio(@wbc, @bio)
+
+       Should be called for each bio carrying writeback data and
+       associates the bio with the inode's owner cgroup.  Can be
+       called anytime between bio allocation and submission.
+
+  wbc_account_io(@wbc, @page, @bytes)
+
+       Should be called for each data segment being written out.
+       While this function doesn't care exactly when it's called
+       during the writeback session, it's the easiest and most
+       natural to call it as data segments are added to a bio.
+
+With writeback bio's annotated, cgroup support can be enabled per
+super_block by setting SB_I_CGROUPWB in ->s_iflags.  This allows for
+selective disabling of cgroup writeback support which is helpful when
+certain filesystem features, e.g. journaled data mode, are
+incompatible.
+
+wbc_init_bio() binds the specified bio to its cgroup.  Depending on
+the configuration, the bio may be executed at a lower priority and if
+the writeback session is holding shared resources, e.g. a journal
+entry, may lead to priority inversion.  There is no one easy solution
+for the problem.  Filesystems can try to work around specific problem
+cases by skipping wbc_init_bio() or using bio_associate_blkcg()
+directly.
+
+
+D. Deprecated v1 Core Features
+
+- Multiple hierarchies including named ones are not supported.
+
+- All mount options and remounting are not supported.
+
+- The "tasks" file is removed and "cgroup.procs" is not sorted.
+
+- "cgroup.clone_children" is removed.
+
+- /proc/cgroups is meaningless for v2.  Use "cgroup.controllers" file
+  at the root instead.
+
+
+R. Issues with v1 and Rationales for v2
+
+R-1. Multiple Hierarchies
+
+cgroup v1 allowed an arbitrary number of hierarchies and each
+hierarchy could host any number of controllers.  While this seemed to
+provide a high level of flexibility, it wasn't useful in practice.
+
+For example, as there is only one instance of each controller, utility
+type controllers such as freezer which can be useful in all
+hierarchies could only be used in one.  The issue is exacerbated by
+the fact that controllers couldn't be moved to another hierarchy once
+hierarchies were populated.  Another issue was that all controllers
+bound to a hierarchy were forced to have exactly the same view of the
+hierarchy.  It wasn't possible to vary the granularity depending on
+the specific controller.
+
+In practice, these issues heavily limited which controllers could be
+put on the same hierarchy and most configurations resorted to putting
+each controller on its own hierarchy.  Only closely related ones, such
+as the cpu and cpuacct controllers, made sense to be put on the same
+hierarchy.  This often meant that userland ended up managing multiple
+similar hierarchies repeating the same steps on each hierarchy
+whenever a hierarchy management operation was necessary.
+
+Furthermore, support for multiple hierarchies came at a steep cost.
+It greatly complicated cgroup core implementation but more importantly
+the support for multiple hierarchies restricted how cgroup could be
+used in general and what controllers was able to do.
+
+There was no limit on how many hierarchies there might be, which meant
+that a thread's cgroup membership couldn't be described in finite
+length.  The key might contain any number of entries and was unlimited
+in length, which made it highly awkward to manipulate and led to
+addition of controllers which existed only to identify membership,
+which in turn exacerbated the original problem of proliferating number
+of hierarchies.
+
+Also, as a controller couldn't have any expectation regarding the
+topologies of hierarchies other controllers might be on, each
+controller had to assume that all other controllers were attached to
+completely orthogonal hierarchies.  This made it impossible, or at
+least very cumbersome, for controllers to cooperate with each other.
+
+In most use cases, putting controllers on hierarchies which are
+completely orthogonal to each other isn't necessary.  What usually is
+called for is the ability to have differing levels of granularity
+depending on the specific controller.  In other words, hierarchy may
+be collapsed from leaf towards root when viewed from specific
+controllers.  For example, a given configuration might not care about
+how memory is distributed beyond a certain level while still wanting
+to control how CPU cycles are distributed.
+
+
+R-2. Thread Granularity
+
+cgroup v1 allowed threads of a process to belong to different cgroups.
+This didn't make sense for some controllers and those controllers
+ended up implementing different ways to ignore such situations but
+much more importantly it blurred the line between API exposed to
+individual applications and system management interface.
+
+Generally, in-process knowledge is available only to the process
+itself; thus, unlike service-level organization of processes,
+categorizing threads of a process requires active participation from
+the application which owns the target process.
+
+cgroup v1 had an ambiguously defined delegation model which got abused
+in combination with thread granularity.  cgroups were delegated to
+individual applications so that they can create and manage their own
+sub-hierarchies and control resource distributions along them.  This
+effectively raised cgroup to the status of a syscall-like API exposed
+to lay programs.
+
+First of all, cgroup has a fundamentally inadequate interface to be
+exposed this way.  For a process to access its own knobs, it has to
+extract the path on the target hierarchy from /proc/self/cgroup,
+construct the path by appending the name of the knob to the path, open
+and then read and/or write to it.  This is not only extremely clunky
+and unusual but also inherently racy.  There is no conventional way to
+define transaction across the required steps and nothing can guarantee
+that the process would actually be operating on its own sub-hierarchy.
+
+cgroup controllers implemented a number of knobs which would never be
+accepted as public APIs because they were just adding control knobs to
+system-management pseudo filesystem.  cgroup ended up with interface
+knobs which were not properly abstracted or refined and directly
+revealed kernel internal details.  These knobs got exposed to
+individual applications through the ill-defined delegation mechanism
+effectively abusing cgroup as a shortcut to implementing public APIs
+without going through the required scrutiny.
+
+This was painful for both userland and kernel.  Userland ended up with
+misbehaving and poorly abstracted interfaces and kernel exposing and
+locked into constructs inadvertently.
+
+
+R-3. Competition Between Inner Nodes and Threads
+
+cgroup v1 allowed threads to be in any cgroups which created an
+interesting problem where threads belonging to a parent cgroup and its
+children cgroups competed for resources.  This was nasty as two
+different types of entities competed and there was no obvious way to
+settle it.  Different controllers did different things.
+
+The cpu controller considered threads and cgroups as equivalents and
+mapped nice levels to cgroup weights.  This worked for some cases but
+fell flat when children wanted to be allocated specific ratios of CPU
+cycles and the number of internal threads fluctuated - the ratios
+constantly changed as the number of competing entities fluctuated.
+There also were other issues.  The mapping from nice level to weight
+wasn't obvious or universal, and there were various other knobs which
+simply weren't available for threads.
+
+The io controller implicitly created a hidden leaf node for each
+cgroup to host the threads.  The hidden leaf had its own copies of all
+the knobs with "leaf_" prefixed.  While this allowed equivalent
+control over internal threads, it was with serious drawbacks.  It
+always added an extra layer of nesting which wouldn't be necessary
+otherwise, made the interface messy and significantly complicated the
+implementation.
+
+The memory controller didn't have a way to control what happened
+between internal tasks and child cgroups and the behavior was not
+clearly defined.  There were attempts to add ad-hoc behaviors and
+knobs to tailor the behavior to specific workloads which would have
+led to problems extremely difficult to resolve in the long term.
+
+Multiple controllers struggled with internal tasks and came up with
+different ways to deal with it; unfortunately, all the approaches were
+severely flawed and, furthermore, the widely different behaviors
+made cgroup as a whole highly inconsistent.
+
+This clearly is a problem which needs to be addressed from cgroup core
+in a uniform way.
+
+
+R-4. Other Interface Issues
+
+cgroup v1 grew without oversight and developed a large number of
+idiosyncrasies and inconsistencies.  One issue on the cgroup core side
+was how an empty cgroup was notified - a userland helper binary was
+forked and executed for each event.  The event delivery wasn't
+recursive or delegatable.  The limitations of the mechanism also led
+to in-kernel event delivery filtering mechanism further complicating
+the interface.
+
+Controller interfaces were problematic too.  An extreme example is
+controllers completely ignoring hierarchical organization and treating
+all cgroups as if they were all located directly under the root
+cgroup.  Some controllers exposed a large amount of inconsistent
+implementation details to userland.
+
+There also was no consistency across controllers.  When a new cgroup
+was created, some controllers defaulted to not imposing extra
+restrictions while others disallowed any resource usage until
+explicitly configured.  Configuration knobs for the same type of
+control used widely differing naming schemes and formats.  Statistics
+and information knobs were named arbitrarily and used different
+formats and units even in the same controller.
+
+cgroup v2 establishes common conventions where appropriate and updates
+controllers so that they expose minimal and consistent interfaces.
+
+
+R-5. Controller Issues and Remedies
+
+R-5-1. Memory
+
+The original lower boundary, the soft limit, is defined as a limit
+that is per default unset.  As a result, the set of cgroups that
+global reclaim prefers is opt-in, rather than opt-out.  The costs for
+optimizing these mostly negative lookups are so high that the
+implementation, despite its enormous size, does not even provide the
+basic desirable behavior.  First off, the soft limit has no
+hierarchical meaning.  All configured groups are organized in a global
+rbtree and treated like equal peers, regardless where they are located
+in the hierarchy.  This makes subtree delegation impossible.  Second,
+the soft limit reclaim pass is so aggressive that it not just
+introduces high allocation latencies into the system, but also impacts
+system performance due to overreclaim, to the point where the feature
+becomes self-defeating.
+
+The memory.low boundary on the other hand is a top-down allocated
+reserve.  A cgroup enjoys reclaim protection when it and all its
+ancestors are below their low boundaries, which makes delegation of
+subtrees possible.  Secondly, new cgroups have no reserve per default
+and in the common case most cgroups are eligible for the preferred
+reclaim pass.  This allows the new low boundary to be efficiently
+implemented with just a minor addition to the generic reclaim code,
+without the need for out-of-band data structures and reclaim passes.
+Because the generic reclaim code considers all cgroups except for the
+ones running low in the preferred first reclaim pass, overreclaim of
+individual groups is eliminated as well, resulting in much better
+overall workload performance.
+
+The original high boundary, the hard limit, is defined as a strict
+limit that can not budge, even if the OOM killer has to be called.
+But this generally goes against the goal of making the most out of the
+available memory.  The memory consumption of workloads varies during
+runtime, and that requires users to overcommit.  But doing that with a
+strict upper limit requires either a fairly accurate prediction of the
+working set size or adding slack to the limit.  Since working set size
+estimation is hard and error prone, and getting it wrong results in
+OOM kills, most users tend to err on the side of a looser limit and
+end up wasting precious resources.
+
+The memory.high boundary on the other hand can be set much more
+conservatively.  When hit, it throttles allocations by forcing them
+into direct reclaim to work off the excess, but it never invokes the
+OOM killer.  As a result, a high boundary that is chosen too
+aggressively will not terminate the processes, but instead it will
+lead to gradual performance degradation.  The user can monitor this
+and make corrections until the minimal memory footprint that still
+gives acceptable performance is found.
+
+In extreme cases, with many concurrent allocations and a complete
+breakdown of reclaim progress within the group, the high boundary can
+be exceeded.  But even then it's mostly better to satisfy the
+allocation from the slack available in other groups or the rest of the
+system than killing the group.  Otherwise, memory.max is there to
+limit this type of spillover and ultimately contain buggy or even
+malicious applications.
diff --git a/Documentation/cgroups/00-INDEX b/Documentation/cgroups/00-INDEX
deleted file mode 100644 (file)
index 3f5a40f..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-00-INDEX
-       - this file
-blkio-controller.txt
-       - Description for Block IO Controller, implementation and usage details.
-cgroups.txt
-       - Control Groups definition, implementation details, examples and API.
-cpuacct.txt
-       - CPU Accounting Controller; account CPU usage for groups of tasks.
-cpusets.txt
-       - documents the cpusets feature; assign CPUs and Mem to a set of tasks.
-devices.txt
-       - Device Whitelist Controller; description, interface and security.
-freezer-subsystem.txt
-       - checkpointing; rationale to not use signals, interface.
-hugetlb.txt
-       - HugeTLB Controller implementation and usage details.
-memcg_test.txt
-       - Memory Resource Controller; implementation details.
-memory.txt
-       - Memory Resource Controller; design, accounting, interface, testing.
-net_cls.txt
-       - Network classifier cgroups details and usages.
-net_prio.txt
-       - Network priority cgroups details and usages.
-pids.txt
-       - Process number cgroups details and usages.
-resource_counter.txt
-       - Resource Counter API.
-unified-hierarchy.txt
-       - Description the new/next cgroup interface.
diff --git a/Documentation/cgroups/blkio-controller.txt b/Documentation/cgroups/blkio-controller.txt
deleted file mode 100644 (file)
index 52fa9f3..0000000
+++ /dev/null
@@ -1,455 +0,0 @@
-                               Block IO Controller
-                               ===================
-Overview
-========
-cgroup subsys "blkio" implements the block io controller. There seems to be
-a need of various kinds of IO control policies (like proportional BW, max BW)
-both at leaf nodes as well as at intermediate nodes in a storage hierarchy.
-Plan is to use the same cgroup based management interface for blkio controller
-and based on user options switch IO policies in the background.
-
-Currently two IO control policies are implemented. First one is proportional
-weight time based division of disk policy. It is implemented in CFQ. Hence
-this policy takes effect only on leaf nodes when CFQ is being used. The second
-one is throttling policy which can be used to specify upper IO rate limits
-on devices. This policy is implemented in generic block layer and can be
-used on leaf nodes as well as higher level logical devices like device mapper.
-
-HOWTO
-=====
-Proportional Weight division of bandwidth
------------------------------------------
-You can do a very simple testing of running two dd threads in two different
-cgroups. Here is what you can do.
-
-- Enable Block IO controller
-       CONFIG_BLK_CGROUP=y
-
-- Enable group scheduling in CFQ
-       CONFIG_CFQ_GROUP_IOSCHED=y
-
-- Compile and boot into kernel and mount IO controller (blkio); see
-  cgroups.txt, Why are cgroups needed?.
-
-       mount -t tmpfs cgroup_root /sys/fs/cgroup
-       mkdir /sys/fs/cgroup/blkio
-       mount -t cgroup -o blkio none /sys/fs/cgroup/blkio
-
-- Create two cgroups
-       mkdir -p /sys/fs/cgroup/blkio/test1/ /sys/fs/cgroup/blkio/test2
-
-- Set weights of group test1 and test2
-       echo 1000 > /sys/fs/cgroup/blkio/test1/blkio.weight
-       echo 500 > /sys/fs/cgroup/blkio/test2/blkio.weight
-
-- Create two same size files (say 512MB each) on same disk (file1, file2) and
-  launch two dd threads in different cgroup to read those files.
-
-       sync
-       echo 3 > /proc/sys/vm/drop_caches
-
-       dd if=/mnt/sdb/zerofile1 of=/dev/null &
-       echo $! > /sys/fs/cgroup/blkio/test1/tasks
-       cat /sys/fs/cgroup/blkio/test1/tasks
-
-       dd if=/mnt/sdb/zerofile2 of=/dev/null &
-       echo $! > /sys/fs/cgroup/blkio/test2/tasks
-       cat /sys/fs/cgroup/blkio/test2/tasks
-
-- At macro level, first dd should finish first. To get more precise data, keep
-  on looking at (with the help of script), at blkio.disk_time and
-  blkio.disk_sectors files of both test1 and test2 groups. This will tell how
-  much disk time (in milliseconds), each group got and how many sectors each
-  group dispatched to the disk. We provide fairness in terms of disk time, so
-  ideally io.disk_time of cgroups should be in proportion to the weight.
-
-Throttling/Upper Limit policy
------------------------------
-- Enable Block IO controller
-       CONFIG_BLK_CGROUP=y
-
-- Enable throttling in block layer
-       CONFIG_BLK_DEV_THROTTLING=y
-
-- Mount blkio controller (see cgroups.txt, Why are cgroups needed?)
-        mount -t cgroup -o blkio none /sys/fs/cgroup/blkio
-
-- Specify a bandwidth rate on particular device for root group. The format
-  for policy is "<major>:<minor>  <bytes_per_second>".
-
-        echo "8:16  1048576" > /sys/fs/cgroup/blkio/blkio.throttle.read_bps_device
-
-  Above will put a limit of 1MB/second on reads happening for root group
-  on device having major/minor number 8:16.
-
-- Run dd to read a file and see if rate is throttled to 1MB/s or not.
-
-               # dd if=/mnt/common/zerofile of=/dev/null bs=4K count=1024
-               # iflag=direct
-        1024+0 records in
-        1024+0 records out
-        4194304 bytes (4.2 MB) copied, 4.0001 s, 1.0 MB/s
-
- Limits for writes can be put using blkio.throttle.write_bps_device file.
-
-Hierarchical Cgroups
-====================
-
-Both CFQ and throttling implement hierarchy support; however,
-throttling's hierarchy support is enabled iff "sane_behavior" is
-enabled from cgroup side, which currently is a development option and
-not publicly available.
-
-If somebody created a hierarchy like as follows.
-
-                       root
-                       /  \
-                    test1 test2
-                       |
-                    test3
-
-CFQ by default and throttling with "sane_behavior" will handle the
-hierarchy correctly.  For details on CFQ hierarchy support, refer to
-Documentation/block/cfq-iosched.txt.  For throttling, all limits apply
-to the whole subtree while all statistics are local to the IOs
-directly generated by tasks in that cgroup.
-
-Throttling without "sane_behavior" enabled from cgroup side will
-practically treat all groups at same level as if it looks like the
-following.
-
-                               pivot
-                            /  /   \  \
-                       root  test1 test2  test3
-
-Various user visible config options
-===================================
-CONFIG_BLK_CGROUP
-       - Block IO controller.
-
-CONFIG_DEBUG_BLK_CGROUP
-       - Debug help. Right now some additional stats file show up in cgroup
-         if this option is enabled.
-
-CONFIG_CFQ_GROUP_IOSCHED
-       - Enables group scheduling in CFQ. Currently only 1 level of group
-         creation is allowed.
-
-CONFIG_BLK_DEV_THROTTLING
-       - Enable block device throttling support in block layer.
-
-Details of cgroup files
-=======================
-Proportional weight policy files
---------------------------------
-- blkio.weight
-       - Specifies per cgroup weight. This is default weight of the group
-         on all the devices until and unless overridden by per device rule.
-         (See blkio.weight_device).
-         Currently allowed range of weights is from 10 to 1000.
-
-- blkio.weight_device
-       - One can specify per cgroup per device rules using this interface.
-         These rules override the default value of group weight as specified
-         by blkio.weight.
-
-         Following is the format.
-
-         # echo dev_maj:dev_minor weight > blkio.weight_device
-         Configure weight=300 on /dev/sdb (8:16) in this cgroup
-         # echo 8:16 300 > blkio.weight_device
-         # cat blkio.weight_device
-         dev     weight
-         8:16    300
-
-         Configure weight=500 on /dev/sda (8:0) in this cgroup
-         # echo 8:0 500 > blkio.weight_device
-         # cat blkio.weight_device
-         dev     weight
-         8:0     500
-         8:16    300
-
-         Remove specific weight for /dev/sda in this cgroup
-         # echo 8:0 0 > blkio.weight_device
-         # cat blkio.weight_device
-         dev     weight
-         8:16    300
-
-- blkio.leaf_weight[_device]
-       - Equivalents of blkio.weight[_device] for the purpose of
-          deciding how much weight tasks in the given cgroup has while
-          competing with the cgroup's child cgroups. For details,
-          please refer to Documentation/block/cfq-iosched.txt.
-
-- blkio.time
-       - disk time allocated to cgroup per device in milliseconds. First
-         two fields specify the major and minor number of the device and
-         third field specifies the disk time allocated to group in
-         milliseconds.
-
-- blkio.sectors
-       - number of sectors transferred to/from disk by the group. First
-         two fields specify the major and minor number of the device and
-         third field specifies the number of sectors transferred by the
-         group to/from the device.
-
-- blkio.io_service_bytes
-       - Number of bytes transferred to/from the disk by the group. These
-         are further divided by the type of operation - read or write, sync
-         or async. First two fields specify the major and minor number of the
-         device, third field specifies the operation type and the fourth field
-         specifies the number of bytes.
-
-- blkio.io_serviced
-       - Number of IOs (bio) issued to the disk by the group. These
-         are further divided by the type of operation - read or write, sync
-         or async. First two fields specify the major and minor number of the
-         device, third field specifies the operation type and the fourth field
-         specifies the number of IOs.
-
-- blkio.io_service_time
-       - Total amount of time between request dispatch and request completion
-         for the IOs done by this cgroup. This is in nanoseconds to make it
-         meaningful for flash devices too. For devices with queue depth of 1,
-         this time represents the actual service time. When queue_depth > 1,
-         that is no longer true as requests may be served out of order. This
-         may cause the service time for a given IO to include the service time
-         of multiple IOs when served out of order which may result in total
-         io_service_time > actual time elapsed. This time is further divided by
-         the type of operation - read or write, sync or async. First two fields
-         specify the major and minor number of the device, third field
-         specifies the operation type and the fourth field specifies the
-         io_service_time in ns.
-
-- blkio.io_wait_time
-       - Total amount of time the IOs for this cgroup spent waiting in the
-         scheduler queues for service. This can be greater than the total time
-         elapsed since it is cumulative io_wait_time for all IOs. It is not a
-         measure of total time the cgroup spent waiting but rather a measure of
-         the wait_time for its individual IOs. For devices with queue_depth > 1
-         this metric does not include the time spent waiting for service once
-         the IO is dispatched to the device but till it actually gets serviced
-         (there might be a time lag here due to re-ordering of requests by the
-         device). This is in nanoseconds to make it meaningful for flash
-         devices too. This time is further divided by the type of operation -
-         read or write, sync or async. First two fields specify the major and
-         minor number of the device, third field specifies the operation type
-         and the fourth field specifies the io_wait_time in ns.
-
-- blkio.io_merged
-       - Total number of bios/requests merged into requests belonging to this
-         cgroup. This is further divided by the type of operation - read or
-         write, sync or async.
-
-- blkio.io_queued
-       - Total number of requests queued up at any given instant for this
-         cgroup. This is further divided by the type of operation - read or
-         write, sync or async.
-
-- blkio.avg_queue_size
-       - Debugging aid only enabled if CONFIG_DEBUG_BLK_CGROUP=y.
-         The average queue size for this cgroup over the entire time of this
-         cgroup's existence. Queue size samples are taken each time one of the
-         queues of this cgroup gets a timeslice.
-
-- blkio.group_wait_time
-       - Debugging aid only enabled if CONFIG_DEBUG_BLK_CGROUP=y.
-         This is the amount of time the cgroup had to wait since it became busy
-         (i.e., went from 0 to 1 request queued) to get a timeslice for one of
-         its queues. This is different from the io_wait_time which is the
-         cumulative total of the amount of time spent by each IO in that cgroup
-         waiting in the scheduler queue. This is in nanoseconds. If this is
-         read when the cgroup is in a waiting (for timeslice) state, the stat
-         will only report the group_wait_time accumulated till the last time it
-         got a timeslice and will not include the current delta.
-
-- blkio.empty_time
-       - Debugging aid only enabled if CONFIG_DEBUG_BLK_CGROUP=y.
-         This is the amount of time a cgroup spends without any pending
-         requests when not being served, i.e., it does not include any time
-         spent idling for one of the queues of the cgroup. This is in
-         nanoseconds. If this is read when the cgroup is in an empty state,
-         the stat will only report the empty_time accumulated till the last
-         time it had a pending request and will not include the current delta.
-
-- blkio.idle_time
-       - Debugging aid only enabled if CONFIG_DEBUG_BLK_CGROUP=y.
-         This is the amount of time spent by the IO scheduler idling for a
-         given cgroup in anticipation of a better request than the existing ones
-         from other queues/cgroups. This is in nanoseconds. If this is read
-         when the cgroup is in an idling state, the stat will only report the
-         idle_time accumulated till the last idle period and will not include
-         the current delta.
-
-- blkio.dequeue
-       - Debugging aid only enabled if CONFIG_DEBUG_BLK_CGROUP=y. This
-         gives the statistics about how many a times a group was dequeued
-         from service tree of the device. First two fields specify the major
-         and minor number of the device and third field specifies the number
-         of times a group was dequeued from a particular device.
-
-- blkio.*_recursive
-       - Recursive version of various stats. These files show the
-          same information as their non-recursive counterparts but
-          include stats from all the descendant cgroups.
-
-Throttling/Upper limit policy files
------------------------------------
-- blkio.throttle.read_bps_device
-       - Specifies upper limit on READ rate from the device. IO rate is
-         specified in bytes per second. Rules are per device. Following is
-         the format.
-
-  echo "<major>:<minor>  <rate_bytes_per_second>" > /cgrp/blkio.throttle.read_bps_device
-
-- blkio.throttle.write_bps_device
-       - Specifies upper limit on WRITE rate to the device. IO rate is
-         specified in bytes per second. Rules are per device. Following is
-         the format.
-
-  echo "<major>:<minor>  <rate_bytes_per_second>" > /cgrp/blkio.throttle.write_bps_device
-
-- blkio.throttle.read_iops_device
-       - Specifies upper limit on READ rate from the device. IO rate is
-         specified in IO per second. Rules are per device. Following is
-         the format.
-
-  echo "<major>:<minor>  <rate_io_per_second>" > /cgrp/blkio.throttle.read_iops_device
-
-- blkio.throttle.write_iops_device
-       - Specifies upper limit on WRITE rate to the device. IO rate is
-         specified in io per second. Rules are per device. Following is
-         the format.
-
-  echo "<major>:<minor>  <rate_io_per_second>" > /cgrp/blkio.throttle.write_iops_device
-
-Note: If both BW and IOPS rules are specified for a device, then IO is
-      subjected to both the constraints.
-
-- blkio.throttle.io_serviced
-       - Number of IOs (bio) issued to the disk by the group. These
-         are further divided by the type of operation - read or write, sync
-         or async. First two fields specify the major and minor number of the
-         device, third field specifies the operation type and the fourth field
-         specifies the number of IOs.
-
-- blkio.throttle.io_service_bytes
-       - Number of bytes transferred to/from the disk by the group. These
-         are further divided by the type of operation - read or write, sync
-         or async. First two fields specify the major and minor number of the
-         device, third field specifies the operation type and the fourth field
-         specifies the number of bytes.
-
-Common files among various policies
------------------------------------
-- blkio.reset_stats
-       - Writing an int to this file will result in resetting all the stats
-         for that cgroup.
-
-CFQ sysfs tunable
-=================
-/sys/block/<disk>/queue/iosched/slice_idle
-------------------------------------------
-On a faster hardware CFQ can be slow, especially with sequential workload.
-This happens because CFQ idles on a single queue and single queue might not
-drive deeper request queue depths to keep the storage busy. In such scenarios
-one can try setting slice_idle=0 and that would switch CFQ to IOPS
-(IO operations per second) mode on NCQ supporting hardware.
-
-That means CFQ will not idle between cfq queues of a cfq group and hence be
-able to driver higher queue depth and achieve better throughput. That also
-means that cfq provides fairness among groups in terms of IOPS and not in
-terms of disk time.
-
-/sys/block/<disk>/queue/iosched/group_idle
-------------------------------------------
-If one disables idling on individual cfq queues and cfq service trees by
-setting slice_idle=0, group_idle kicks in. That means CFQ will still idle
-on the group in an attempt to provide fairness among groups.
-
-By default group_idle is same as slice_idle and does not do anything if
-slice_idle is enabled.
-
-One can experience an overall throughput drop if you have created multiple
-groups and put applications in that group which are not driving enough
-IO to keep disk busy. In that case set group_idle=0, and CFQ will not idle
-on individual groups and throughput should improve.
-
-Writeback
-=========
-
-Page cache is dirtied through buffered writes and shared mmaps and
-written asynchronously to the backing filesystem by the writeback
-mechanism.  Writeback sits between the memory and IO domains and
-regulates the proportion of dirty memory by balancing dirtying and
-write IOs.
-
-On traditional cgroup hierarchies, relationships between different
-controllers cannot be established making it impossible for writeback
-to operate accounting for cgroup resource restrictions and all
-writeback IOs are attributed to the root cgroup.
-
-If both the blkio and memory controllers are used on the v2 hierarchy
-and the filesystem supports cgroup writeback, writeback operations
-correctly follow the resource restrictions imposed by both memory and
-blkio controllers.
-
-Writeback examines both system-wide and per-cgroup dirty memory status
-and enforces the more restrictive of the two.  Also, writeback control
-parameters which are absolute values - vm.dirty_bytes and
-vm.dirty_background_bytes - are distributed across cgroups according
-to their current writeback bandwidth.
-
-There's a peculiarity stemming from the discrepancy in ownership
-granularity between memory controller and writeback.  While memory
-controller tracks ownership per page, writeback operates on inode
-basis.  cgroup writeback bridges the gap by tracking ownership by
-inode but migrating ownership if too many foreign pages, pages which
-don't match the current inode ownership, have been encountered while
-writing back the inode.
-
-This is a conscious design choice as writeback operations are
-inherently tied to inodes making strictly following page ownership
-complicated and inefficient.  The only use case which suffers from
-this compromise is multiple cgroups concurrently dirtying disjoint
-regions of the same inode, which is an unlikely use case and decided
-to be unsupported.  Note that as memory controller assigns page
-ownership on the first use and doesn't update it until the page is
-released, even if cgroup writeback strictly follows page ownership,
-multiple cgroups dirtying overlapping areas wouldn't work as expected.
-In general, write-sharing an inode across multiple cgroups is not well
-supported.
-
-Filesystem support for cgroup writeback
----------------------------------------
-
-A filesystem can make writeback IOs cgroup-aware by updating
-address_space_operations->writepage[s]() to annotate bio's using the
-following two functions.
-
-* wbc_init_bio(@wbc, @bio)
-
-  Should be called for each bio carrying writeback data and associates
-  the bio with the inode's owner cgroup.  Can be called anytime
-  between bio allocation and submission.
-
-* wbc_account_io(@wbc, @page, @bytes)
-
-  Should be called for each data segment being written out.  While
-  this function doesn't care exactly when it's called during the
-  writeback session, it's the easiest and most natural to call it as
-  data segments are added to a bio.
-
-With writeback bio's annotated, cgroup support can be enabled per
-super_block by setting MS_CGROUPWB in ->s_flags.  This allows for
-selective disabling of cgroup writeback support which is helpful when
-certain filesystem features, e.g. journaled data mode, are
-incompatible.
-
-wbc_init_bio() binds the specified bio to its cgroup.  Depending on
-the configuration, the bio may be executed at a lower priority and if
-the writeback session is holding shared resources, e.g. a journal
-entry, may lead to priority inversion.  There is no one easy solution
-for the problem.  Filesystems can try to work around specific problem
-cases by skipping wbc_init_bio() or using bio_associate_blkcg()
-directly.
diff --git a/Documentation/cgroups/cgroups.txt b/Documentation/cgroups/cgroups.txt
deleted file mode 100644 (file)
index c6256ae..0000000
+++ /dev/null
@@ -1,682 +0,0 @@
-                               CGROUPS
-                               -------
-
-Written by Paul Menage <menage@google.com> based on
-Documentation/cgroups/cpusets.txt
-
-Original copyright statements from cpusets.txt:
-Portions Copyright (C) 2004 BULL SA.
-Portions Copyright (c) 2004-2006 Silicon Graphics, Inc.
-Modified by Paul Jackson <pj@sgi.com>
-Modified by Christoph Lameter <clameter@sgi.com>
-
-CONTENTS:
-=========
-
-1. Control Groups
-  1.1 What are cgroups ?
-  1.2 Why are cgroups needed ?
-  1.3 How are cgroups implemented ?
-  1.4 What does notify_on_release do ?
-  1.5 What does clone_children do ?
-  1.6 How do I use cgroups ?
-2. Usage Examples and Syntax
-  2.1 Basic Usage
-  2.2 Attaching processes
-  2.3 Mounting hierarchies by name
-3. Kernel API
-  3.1 Overview
-  3.2 Synchronization
-  3.3 Subsystem API
-4. Extended attributes usage
-5. Questions
-
-1. Control Groups
-=================
-
-1.1 What are cgroups ?
-----------------------
-
-Control Groups provide a mechanism for aggregating/partitioning sets of
-tasks, and all their future children, into hierarchical groups with
-specialized behaviour.
-
-Definitions:
-
-A *cgroup* associates a set of tasks with a set of parameters for one
-or more subsystems.
-
-A *subsystem* is a module that makes use of the task grouping
-facilities provided by cgroups to treat groups of tasks in
-particular ways. A subsystem is typically a "resource controller" that
-schedules a resource or applies per-cgroup limits, but it may be
-anything that wants to act on a group of processes, e.g. a
-virtualization subsystem.
-
-A *hierarchy* is a set of cgroups arranged in a tree, such that
-every task in the system is in exactly one of the cgroups in the
-hierarchy, and a set of subsystems; each subsystem has system-specific
-state attached to each cgroup in the hierarchy.  Each hierarchy has
-an instance of the cgroup virtual filesystem associated with it.
-
-At any one time there may be multiple active hierarchies of task
-cgroups. Each hierarchy is a partition of all tasks in the system.
-
-User-level code may create and destroy cgroups by name in an
-instance of the cgroup virtual file system, specify and query to
-which cgroup a task is assigned, and list the task PIDs assigned to
-a cgroup. Those creations and assignments only affect the hierarchy
-associated with that instance of the cgroup file system.
-
-On their own, the only use for cgroups is for simple job
-tracking. The intention is that other subsystems hook into the generic
-cgroup support to provide new attributes for cgroups, such as
-accounting/limiting the resources which processes in a cgroup can
-access. For example, cpusets (see Documentation/cgroups/cpusets.txt) allow
-you to associate a set of CPUs and a set of memory nodes with the
-tasks in each cgroup.
-
-1.2 Why are cgroups needed ?
-----------------------------
-
-There are multiple efforts to provide process aggregations in the
-Linux kernel, mainly for resource-tracking purposes. Such efforts
-include cpusets, CKRM/ResGroups, UserBeanCounters, and virtual server
-namespaces. These all require the basic notion of a
-grouping/partitioning of processes, with newly forked processes ending
-up in the same group (cgroup) as their parent process.
-
-The kernel cgroup patch provides the minimum essential kernel
-mechanisms required to efficiently implement such groups. It has
-minimal impact on the system fast paths, and provides hooks for
-specific subsystems such as cpusets to provide additional behaviour as
-desired.
-
-Multiple hierarchy support is provided to allow for situations where
-the division of tasks into cgroups is distinctly different for
-different subsystems - having parallel hierarchies allows each
-hierarchy to be a natural division of tasks, without having to handle
-complex combinations of tasks that would be present if several
-unrelated subsystems needed to be forced into the same tree of
-cgroups.
-
-At one extreme, each resource controller or subsystem could be in a
-separate hierarchy; at the other extreme, all subsystems
-would be attached to the same hierarchy.
-
-As an example of a scenario (originally proposed by vatsa@in.ibm.com)
-that can benefit from multiple hierarchies, consider a large
-university server with various users - students, professors, system
-tasks etc. The resource planning for this server could be along the
-following lines:
-
-       CPU :          "Top cpuset"
-                       /       \
-               CPUSet1         CPUSet2
-                  |               |
-               (Professors)    (Students)
-
-               In addition (system tasks) are attached to topcpuset (so
-               that they can run anywhere) with a limit of 20%
-
-       Memory : Professors (50%), Students (30%), system (20%)
-
-       Disk : Professors (50%), Students (30%), system (20%)
-
-       Network : WWW browsing (20%), Network File System (60%), others (20%)
-                               / \
-               Professors (15%)  students (5%)
-
-Browsers like Firefox/Lynx go into the WWW network class, while (k)nfsd goes
-into the NFS network class.
-
-At the same time Firefox/Lynx will share an appropriate CPU/Memory class
-depending on who launched it (prof/student).
-
-With the ability to classify tasks differently for different resources
-(by putting those resource subsystems in different hierarchies),
-the admin can easily set up a script which receives exec notifications
-and depending on who is launching the browser he can
-
-    # echo browser_pid > /sys/fs/cgroup/<restype>/<userclass>/tasks
-
-With only a single hierarchy, he now would potentially have to create
-a separate cgroup for every browser launched and associate it with
-appropriate network and other resource class.  This may lead to
-proliferation of such cgroups.
-
-Also let's say that the administrator would like to give enhanced network
-access temporarily to a student's browser (since it is night and the user
-wants to do online gaming :))  OR give one of the student's simulation
-apps enhanced CPU power.
-
-With ability to write PIDs directly to resource classes, it's just a
-matter of:
-
-       # echo pid > /sys/fs/cgroup/network/<new_class>/tasks
-       (after some time)
-       # echo pid > /sys/fs/cgroup/network/<orig_class>/tasks
-
-Without this ability, the administrator would have to split the cgroup into
-multiple separate ones and then associate the new cgroups with the
-new resource classes.
-
-
-
-1.3 How are cgroups implemented ?
----------------------------------
-
-Control Groups extends the kernel as follows:
-
- - Each task in the system has a reference-counted pointer to a
-   css_set.
-
- - A css_set contains a set of reference-counted pointers to
-   cgroup_subsys_state objects, one for each cgroup subsystem
-   registered in the system. There is no direct link from a task to
-   the cgroup of which it's a member in each hierarchy, but this
-   can be determined by following pointers through the
-   cgroup_subsys_state objects. This is because accessing the
-   subsystem state is something that's expected to happen frequently
-   and in performance-critical code, whereas operations that require a
-   task's actual cgroup assignments (in particular, moving between
-   cgroups) are less common. A linked list runs through the cg_list
-   field of each task_struct using the css_set, anchored at
-   css_set->tasks.
-
- - A cgroup hierarchy filesystem can be mounted for browsing and
-   manipulation from user space.
-
- - You can list all the tasks (by PID) attached to any cgroup.
-
-The implementation of cgroups requires a few, simple hooks
-into the rest of the kernel, none in performance-critical paths:
-
- - in init/main.c, to initialize the root cgroups and initial
-   css_set at system boot.
-
- - in fork and exit, to attach and detach a task from its css_set.
-
-In addition, a new file system of type "cgroup" may be mounted, to
-enable browsing and modifying the cgroups presently known to the
-kernel.  When mounting a cgroup hierarchy, you may specify a
-comma-separated list of subsystems to mount as the filesystem mount
-options.  By default, mounting the cgroup filesystem attempts to
-mount a hierarchy containing all registered subsystems.
-
-If an active hierarchy with exactly the same set of subsystems already
-exists, it will be reused for the new mount. If no existing hierarchy
-matches, and any of the requested subsystems are in use in an existing
-hierarchy, the mount will fail with -EBUSY. Otherwise, a new hierarchy
-is activated, associated with the requested subsystems.
-
-It's not currently possible to bind a new subsystem to an active
-cgroup hierarchy, or to unbind a subsystem from an active cgroup
-hierarchy. This may be possible in future, but is fraught with nasty
-error-recovery issues.
-
-When a cgroup filesystem is unmounted, if there are any
-child cgroups created below the top-level cgroup, that hierarchy
-will remain active even though unmounted; if there are no
-child cgroups then the hierarchy will be deactivated.
-
-No new system calls are added for cgroups - all support for
-querying and modifying cgroups is via this cgroup file system.
-
-Each task under /proc has an added file named 'cgroup' displaying,
-for each active hierarchy, the subsystem names and the cgroup name
-as the path relative to the root of the cgroup file system.
-
-Each cgroup is represented by a directory in the cgroup file system
-containing the following files describing that cgroup:
-
- - tasks: list of tasks (by PID) attached to that cgroup.  This list
-   is not guaranteed to be sorted.  Writing a thread ID into this file
-   moves the thread into this cgroup.
- - cgroup.procs: list of thread group IDs in the cgroup.  This list is
-   not guaranteed to be sorted or free of duplicate TGIDs, and userspace
-   should sort/uniquify the list if this property is required.
-   Writing a thread group ID into this file moves all threads in that
-   group into this cgroup.
- - notify_on_release flag: run the release agent on exit?
- - release_agent: the path to use for release notifications (this file
-   exists in the top cgroup only)
-
-Other subsystems such as cpusets may add additional files in each
-cgroup dir.
-
-New cgroups are created using the mkdir system call or shell
-command.  The properties of a cgroup, such as its flags, are
-modified by writing to the appropriate file in that cgroups
-directory, as listed above.
-
-The named hierarchical structure of nested cgroups allows partitioning
-a large system into nested, dynamically changeable, "soft-partitions".
-
-The attachment of each task, automatically inherited at fork by any
-children of that task, to a cgroup allows organizing the work load
-on a system into related sets of tasks.  A task may be re-attached to
-any other cgroup, if allowed by the permissions on the necessary
-cgroup file system directories.
-
-When a task is moved from one cgroup to another, it gets a new
-css_set pointer - if there's an already existing css_set with the
-desired collection of cgroups then that group is reused, otherwise a new
-css_set is allocated. The appropriate existing css_set is located by
-looking into a hash table.
-
-To allow access from a cgroup to the css_sets (and hence tasks)
-that comprise it, a set of cg_cgroup_link objects form a lattice;
-each cg_cgroup_link is linked into a list of cg_cgroup_links for
-a single cgroup on its cgrp_link_list field, and a list of
-cg_cgroup_links for a single css_set on its cg_link_list.
-
-Thus the set of tasks in a cgroup can be listed by iterating over
-each css_set that references the cgroup, and sub-iterating over
-each css_set's task set.
-
-The use of a Linux virtual file system (vfs) to represent the
-cgroup hierarchy provides for a familiar permission and name space
-for cgroups, with a minimum of additional kernel code.
-
-1.4 What does notify_on_release do ?
-------------------------------------
-
-If the notify_on_release flag is enabled (1) in a cgroup, then
-whenever the last task in the cgroup leaves (exits or attaches to
-some other cgroup) and the last child cgroup of that cgroup
-is removed, then the kernel runs the command specified by the contents
-of the "release_agent" file in that hierarchy's root directory,
-supplying the pathname (relative to the mount point of the cgroup
-file system) of the abandoned cgroup.  This enables automatic
-removal of abandoned cgroups.  The default value of
-notify_on_release in the root cgroup at system boot is disabled
-(0).  The default value of other cgroups at creation is the current
-value of their parents' notify_on_release settings. The default value of
-a cgroup hierarchy's release_agent path is empty.
-
-1.5 What does clone_children do ?
----------------------------------
-
-This flag only affects the cpuset controller. If the clone_children
-flag is enabled (1) in a cgroup, a new cpuset cgroup will copy its
-configuration from the parent during initialization.
-
-1.6 How do I use cgroups ?
---------------------------
-
-To start a new job that is to be contained within a cgroup, using
-the "cpuset" cgroup subsystem, the steps are something like:
-
- 1) mount -t tmpfs cgroup_root /sys/fs/cgroup
- 2) mkdir /sys/fs/cgroup/cpuset
- 3) mount -t cgroup -ocpuset cpuset /sys/fs/cgroup/cpuset
- 4) Create the new cgroup by doing mkdir's and write's (or echo's) in
-    the /sys/fs/cgroup/cpuset virtual file system.
- 5) Start a task that will be the "founding father" of the new job.
- 6) Attach that task to the new cgroup by writing its PID to the
-    /sys/fs/cgroup/cpuset tasks file for that cgroup.
- 7) fork, exec or clone the job tasks from this founding father task.
-
-For example, the following sequence of commands will setup a cgroup
-named "Charlie", containing just CPUs 2 and 3, and Memory Node 1,
-and then start a subshell 'sh' in that cgroup:
-
-  mount -t tmpfs cgroup_root /sys/fs/cgroup
-  mkdir /sys/fs/cgroup/cpuset
-  mount -t cgroup cpuset -ocpuset /sys/fs/cgroup/cpuset
-  cd /sys/fs/cgroup/cpuset
-  mkdir Charlie
-  cd Charlie
-  /bin/echo 2-3 > cpuset.cpus
-  /bin/echo 1 > cpuset.mems
-  /bin/echo $$ > tasks
-  sh
-  # The subshell 'sh' is now running in cgroup Charlie
-  # The next line should display '/Charlie'
-  cat /proc/self/cgroup
-
-2. Usage Examples and Syntax
-============================
-
-2.1 Basic Usage
----------------
-
-Creating, modifying, using cgroups can be done through the cgroup
-virtual filesystem.
-
-To mount a cgroup hierarchy with all available subsystems, type:
-# mount -t cgroup xxx /sys/fs/cgroup
-
-The "xxx" is not interpreted by the cgroup code, but will appear in
-/proc/mounts so may be any useful identifying string that you like.
-
-Note: Some subsystems do not work without some user input first.  For instance,
-if cpusets are enabled the user will have to populate the cpus and mems files
-for each new cgroup created before that group can be used.
-
-As explained in section `1.2 Why are cgroups needed?' you should create
-different hierarchies of cgroups for each single resource or group of
-resources you want to control. Therefore, you should mount a tmpfs on
-/sys/fs/cgroup and create directories for each cgroup resource or resource
-group.
-
-# mount -t tmpfs cgroup_root /sys/fs/cgroup
-# mkdir /sys/fs/cgroup/rg1
-
-To mount a cgroup hierarchy with just the cpuset and memory
-subsystems, type:
-# mount -t cgroup -o cpuset,memory hier1 /sys/fs/cgroup/rg1
-
-While remounting cgroups is currently supported, it is not recommend
-to use it. Remounting allows changing bound subsystems and
-release_agent. Rebinding is hardly useful as it only works when the
-hierarchy is empty and release_agent itself should be replaced with
-conventional fsnotify. The support for remounting will be removed in
-the future.
-
-To Specify a hierarchy's release_agent:
-# mount -t cgroup -o cpuset,release_agent="/sbin/cpuset_release_agent" \
-  xxx /sys/fs/cgroup/rg1
-
-Note that specifying 'release_agent' more than once will return failure.
-
-Note that changing the set of subsystems is currently only supported
-when the hierarchy consists of a single (root) cgroup. Supporting
-the ability to arbitrarily bind/unbind subsystems from an existing
-cgroup hierarchy is intended to be implemented in the future.
-
-Then under /sys/fs/cgroup/rg1 you can find a tree that corresponds to the
-tree of the cgroups in the system. For instance, /sys/fs/cgroup/rg1
-is the cgroup that holds the whole system.
-
-If you want to change the value of release_agent:
-# echo "/sbin/new_release_agent" > /sys/fs/cgroup/rg1/release_agent
-
-It can also be changed via remount.
-
-If you want to create a new cgroup under /sys/fs/cgroup/rg1:
-# cd /sys/fs/cgroup/rg1
-# mkdir my_cgroup
-
-Now you want to do something with this cgroup.
-# cd my_cgroup
-
-In this directory you can find several files:
-# ls
-cgroup.procs notify_on_release tasks
-(plus whatever files added by the attached subsystems)
-
-Now attach your shell to this cgroup:
-# /bin/echo $$ > tasks
-
-You can also create cgroups inside your cgroup by using mkdir in this
-directory.
-# mkdir my_sub_cs
-
-To remove a cgroup, just use rmdir:
-# rmdir my_sub_cs
-
-This will fail if the cgroup is in use (has cgroups inside, or
-has processes attached, or is held alive by other subsystem-specific
-reference).
-
-2.2 Attaching processes
------------------------
-
-# /bin/echo PID > tasks
-
-Note that it is PID, not PIDs. You can only attach ONE task at a time.
-If you have several tasks to attach, you have to do it one after another:
-
-# /bin/echo PID1 > tasks
-# /bin/echo PID2 > tasks
-       ...
-# /bin/echo PIDn > tasks
-
-You can attach the current shell task by echoing 0:
-
-# echo 0 > tasks
-
-You can use the cgroup.procs file instead of the tasks file to move all
-threads in a threadgroup at once. Echoing the PID of any task in a
-threadgroup to cgroup.procs causes all tasks in that threadgroup to be
-attached to the cgroup. Writing 0 to cgroup.procs moves all tasks
-in the writing task's threadgroup.
-
-Note: Since every task is always a member of exactly one cgroup in each
-mounted hierarchy, to remove a task from its current cgroup you must
-move it into a new cgroup (possibly the root cgroup) by writing to the
-new cgroup's tasks file.
-
-Note: Due to some restrictions enforced by some cgroup subsystems, moving
-a process to another cgroup can fail.
-
-2.3 Mounting hierarchies by name
---------------------------------
-
-Passing the name=<x> option when mounting a cgroups hierarchy
-associates the given name with the hierarchy.  This can be used when
-mounting a pre-existing hierarchy, in order to refer to it by name
-rather than by its set of active subsystems.  Each hierarchy is either
-nameless, or has a unique name.
-
-The name should match [\w.-]+
-
-When passing a name=<x> option for a new hierarchy, you need to
-specify subsystems manually; the legacy behaviour of mounting all
-subsystems when none are explicitly specified is not supported when
-you give a subsystem a name.
-
-The name of the subsystem appears as part of the hierarchy description
-in /proc/mounts and /proc/<pid>/cgroups.
-
-
-3. Kernel API
-=============
-
-3.1 Overview
-------------
-
-Each kernel subsystem that wants to hook into the generic cgroup
-system needs to create a cgroup_subsys object. This contains
-various methods, which are callbacks from the cgroup system, along
-with a subsystem ID which will be assigned by the cgroup system.
-
-Other fields in the cgroup_subsys object include:
-
-- subsys_id: a unique array index for the subsystem, indicating which
-  entry in cgroup->subsys[] this subsystem should be managing.
-
-- name: should be initialized to a unique subsystem name. Should be
-  no longer than MAX_CGROUP_TYPE_NAMELEN.
-
-- early_init: indicate if the subsystem needs early initialization
-  at system boot.
-
-Each cgroup object created by the system has an array of pointers,
-indexed by subsystem ID; this pointer is entirely managed by the
-subsystem; the generic cgroup code will never touch this pointer.
-
-3.2 Synchronization
--------------------
-
-There is a global mutex, cgroup_mutex, used by the cgroup
-system. This should be taken by anything that wants to modify a
-cgroup. It may also be taken to prevent cgroups from being
-modified, but more specific locks may be more appropriate in that
-situation.
-
-See kernel/cgroup.c for more details.
-
-Subsystems can take/release the cgroup_mutex via the functions
-cgroup_lock()/cgroup_unlock().
-
-Accessing a task's cgroup pointer may be done in the following ways:
-- while holding cgroup_mutex
-- while holding the task's alloc_lock (via task_lock())
-- inside an rcu_read_lock() section via rcu_dereference()
-
-3.3 Subsystem API
------------------
-
-Each subsystem should:
-
-- add an entry in linux/cgroup_subsys.h
-- define a cgroup_subsys object called <name>_subsys
-
-If a subsystem can be compiled as a module, it should also have in its
-module initcall a call to cgroup_load_subsys(), and in its exitcall a
-call to cgroup_unload_subsys(). It should also set its_subsys.module =
-THIS_MODULE in its .c file.
-
-Each subsystem may export the following methods. The only mandatory
-methods are css_alloc/free. Any others that are null are presumed to
-be successful no-ops.
-
-struct cgroup_subsys_state *css_alloc(struct cgroup *cgrp)
-(cgroup_mutex held by caller)
-
-Called to allocate a subsystem state object for a cgroup. The
-subsystem should allocate its subsystem state object for the passed
-cgroup, returning a pointer to the new object on success or a
-ERR_PTR() value. On success, the subsystem pointer should point to
-a structure of type cgroup_subsys_state (typically embedded in a
-larger subsystem-specific object), which will be initialized by the
-cgroup system. Note that this will be called at initialization to
-create the root subsystem state for this subsystem; this case can be
-identified by the passed cgroup object having a NULL parent (since
-it's the root of the hierarchy) and may be an appropriate place for
-initialization code.
-
-int css_online(struct cgroup *cgrp)
-(cgroup_mutex held by caller)
-
-Called after @cgrp successfully completed all allocations and made
-visible to cgroup_for_each_child/descendant_*() iterators. The
-subsystem may choose to fail creation by returning -errno. This
-callback can be used to implement reliable state sharing and
-propagation along the hierarchy. See the comment on
-cgroup_for_each_descendant_pre() for details.
-
-void css_offline(struct cgroup *cgrp);
-(cgroup_mutex held by caller)
-
-This is the counterpart of css_online() and called iff css_online()
-has succeeded on @cgrp. This signifies the beginning of the end of
-@cgrp. @cgrp is being removed and the subsystem should start dropping
-all references it's holding on @cgrp. When all references are dropped,
-cgroup removal will proceed to the next step - css_free(). After this
-callback, @cgrp should be considered dead to the subsystem.
-
-void css_free(struct cgroup *cgrp)
-(cgroup_mutex held by caller)
-
-The cgroup system is about to free @cgrp; the subsystem should free
-its subsystem state object. By the time this method is called, @cgrp
-is completely unused; @cgrp->parent is still valid. (Note - can also
-be called for a newly-created cgroup if an error occurs after this
-subsystem's create() method has been called for the new cgroup).
-
-int can_attach(struct cgroup *cgrp, struct cgroup_taskset *tset)
-(cgroup_mutex held by caller)
-
-Called prior to moving one or more tasks into a cgroup; if the
-subsystem returns an error, this will abort the attach operation.
-@tset contains the tasks to be attached and is guaranteed to have at
-least one task in it.
-
-If there are multiple tasks in the taskset, then:
-  - it's guaranteed that all are from the same thread group
-  - @tset contains all tasks from the thread group whether or not
-    they're switching cgroups
-  - the first task is the leader
-
-Each @tset entry also contains the task's old cgroup and tasks which
-aren't switching cgroup can be skipped easily using the
-cgroup_taskset_for_each() iterator. Note that this isn't called on a
-fork. If this method returns 0 (success) then this should remain valid
-while the caller holds cgroup_mutex and it is ensured that either
-attach() or cancel_attach() will be called in future.
-
-void css_reset(struct cgroup_subsys_state *css)
-(cgroup_mutex held by caller)
-
-An optional operation which should restore @css's configuration to the
-initial state.  This is currently only used on the unified hierarchy
-when a subsystem is disabled on a cgroup through
-"cgroup.subtree_control" but should remain enabled because other
-subsystems depend on it.  cgroup core makes such a css invisible by
-removing the associated interface files and invokes this callback so
-that the hidden subsystem can return to the initial neutral state.
-This prevents unexpected resource control from a hidden css and
-ensures that the configuration is in the initial state when it is made
-visible again later.
-
-void cancel_attach(struct cgroup *cgrp, struct cgroup_taskset *tset)
-(cgroup_mutex held by caller)
-
-Called when a task attach operation has failed after can_attach() has succeeded.
-A subsystem whose can_attach() has some side-effects should provide this
-function, so that the subsystem can implement a rollback. If not, not necessary.
-This will be called only about subsystems whose can_attach() operation have
-succeeded. The parameters are identical to can_attach().
-
-void attach(struct cgroup *cgrp, struct cgroup_taskset *tset)
-(cgroup_mutex held by caller)
-
-Called after the task has been attached to the cgroup, to allow any
-post-attachment activity that requires memory allocations or blocking.
-The parameters are identical to can_attach().
-
-void fork(struct task_struct *task)
-
-Called when a task is forked into a cgroup.
-
-void exit(struct task_struct *task)
-
-Called during task exit.
-
-void free(struct task_struct *task)
-
-Called when the task_struct is freed.
-
-void bind(struct cgroup *root)
-(cgroup_mutex held by caller)
-
-Called when a cgroup subsystem is rebound to a different hierarchy
-and root cgroup. Currently this will only involve movement between
-the default hierarchy (which never has sub-cgroups) and a hierarchy
-that is being created/destroyed (and hence has no sub-cgroups).
-
-4. Extended attribute usage
-===========================
-
-cgroup filesystem supports certain types of extended attributes in its
-directories and files.  The current supported types are:
-       - Trusted (XATTR_TRUSTED)
-       - Security (XATTR_SECURITY)
-
-Both require CAP_SYS_ADMIN capability to set.
-
-Like in tmpfs, the extended attributes in cgroup filesystem are stored
-using kernel memory and it's advised to keep the usage at minimum.  This
-is the reason why user defined extended attributes are not supported, since
-any user can do it and there's no limit in the value size.
-
-The current known users for this feature are SELinux to limit cgroup usage
-in containers and systemd for assorted meta data like main PID in a cgroup
-(systemd creates a cgroup per service).
-
-5. Questions
-============
-
-Q: what's up with this '/bin/echo' ?
-A: bash's builtin 'echo' command does not check calls to write() against
-   errors. If you use it in the cgroup file system, you won't be
-   able to tell whether a command succeeded or failed.
-
-Q: When I attach processes, only the first of the line gets really attached !
-A: We can only return one error code per call to write(). So you should also
-   put only ONE PID.
-
diff --git a/Documentation/cgroups/cpuacct.txt b/Documentation/cgroups/cpuacct.txt
deleted file mode 100644 (file)
index 9d73cc0..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-CPU Accounting Controller
--------------------------
-
-The CPU accounting controller is used to group tasks using cgroups and
-account the CPU usage of these groups of tasks.
-
-The CPU accounting controller supports multi-hierarchy groups. An accounting
-group accumulates the CPU usage of all of its child groups and the tasks
-directly present in its group.
-
-Accounting groups can be created by first mounting the cgroup filesystem.
-
-# mount -t cgroup -ocpuacct none /sys/fs/cgroup
-
-With the above step, the initial or the parent accounting group becomes
-visible at /sys/fs/cgroup. At bootup, this group includes all the tasks in
-the system. /sys/fs/cgroup/tasks lists the tasks in this cgroup.
-/sys/fs/cgroup/cpuacct.usage gives the CPU time (in nanoseconds) obtained
-by this group which is essentially the CPU time obtained by all the tasks
-in the system.
-
-New accounting groups can be created under the parent group /sys/fs/cgroup.
-
-# cd /sys/fs/cgroup
-# mkdir g1
-# echo $$ > g1/tasks
-
-The above steps create a new group g1 and move the current shell
-process (bash) into it. CPU time consumed by this bash and its children
-can be obtained from g1/cpuacct.usage and the same is accumulated in
-/sys/fs/cgroup/cpuacct.usage also.
-
-cpuacct.stat file lists a few statistics which further divide the
-CPU time obtained by the cgroup into user and system times. Currently
-the following statistics are supported:
-
-user: Time spent by tasks of the cgroup in user mode.
-system: Time spent by tasks of the cgroup in kernel mode.
-
-user and system are in USER_HZ unit.
-
-cpuacct controller uses percpu_counter interface to collect user and
-system times. This has two side effects:
-
-- It is theoretically possible to see wrong values for user and system times.
-  This is because percpu_counter_read() on 32bit systems isn't safe
-  against concurrent writes.
-- It is possible to see slightly outdated values for user and system times
-  due to the batch processing nature of percpu_counter.
diff --git a/Documentation/cgroups/cpusets.txt b/Documentation/cgroups/cpusets.txt
deleted file mode 100644 (file)
index fdf7dff..0000000
+++ /dev/null
@@ -1,839 +0,0 @@
-                               CPUSETS
-                               -------
-
-Copyright (C) 2004 BULL SA.
-Written by Simon.Derr@bull.net
-
-Portions Copyright (c) 2004-2006 Silicon Graphics, Inc.
-Modified by Paul Jackson <pj@sgi.com>
-Modified by Christoph Lameter <clameter@sgi.com>
-Modified by Paul Menage <menage@google.com>
-Modified by Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
-
-CONTENTS:
-=========
-
-1. Cpusets
-  1.1 What are cpusets ?
-  1.2 Why are cpusets needed ?
-  1.3 How are cpusets implemented ?
-  1.4 What are exclusive cpusets ?
-  1.5 What is memory_pressure ?
-  1.6 What is memory spread ?
-  1.7 What is sched_load_balance ?
-  1.8 What is sched_relax_domain_level ?
-  1.9 How do I use cpusets ?
-2. Usage Examples and Syntax
-  2.1 Basic Usage
-  2.2 Adding/removing cpus
-  2.3 Setting flags
-  2.4 Attaching processes
-3. Questions
-4. Contact
-
-1. Cpusets
-==========
-
-1.1 What are cpusets ?
-----------------------
-
-Cpusets provide a mechanism for assigning a set of CPUs and Memory
-Nodes to a set of tasks.   In this document "Memory Node" refers to
-an on-line node that contains memory.
-
-Cpusets constrain the CPU and Memory placement of tasks to only
-the resources within a task's current cpuset.  They form a nested
-hierarchy visible in a virtual file system.  These are the essential
-hooks, beyond what is already present, required to manage dynamic
-job placement on large systems.
-
-Cpusets use the generic cgroup subsystem described in
-Documentation/cgroups/cgroups.txt.
-
-Requests by a task, using the sched_setaffinity(2) system call to
-include CPUs in its CPU affinity mask, and using the mbind(2) and
-set_mempolicy(2) system calls to include Memory Nodes in its memory
-policy, are both filtered through that task's cpuset, filtering out any
-CPUs or Memory Nodes not in that cpuset.  The scheduler will not
-schedule a task on a CPU that is not allowed in its cpus_allowed
-vector, and the kernel page allocator will not allocate a page on a
-node that is not allowed in the requesting task's mems_allowed vector.
-
-User level code may create and destroy cpusets by name in the cgroup
-virtual file system, manage the attributes and permissions of these
-cpusets and which CPUs and Memory Nodes are assigned to each cpuset,
-specify and query to which cpuset a task is assigned, and list the
-task pids assigned to a cpuset.
-
-
-1.2 Why are cpusets needed ?
-----------------------------
-
-The management of large computer systems, with many processors (CPUs),
-complex memory cache hierarchies and multiple Memory Nodes having
-non-uniform access times (NUMA) presents additional challenges for
-the efficient scheduling and memory placement of processes.
-
-Frequently more modest sized systems can be operated with adequate
-efficiency just by letting the operating system automatically share
-the available CPU and Memory resources amongst the requesting tasks.
-
-But larger systems, which benefit more from careful processor and
-memory placement to reduce memory access times and contention,
-and which typically represent a larger investment for the customer,
-can benefit from explicitly placing jobs on properly sized subsets of
-the system.
-
-This can be especially valuable on:
-
-    * Web Servers running multiple instances of the same web application,
-    * Servers running different applications (for instance, a web server
-      and a database), or
-    * NUMA systems running large HPC applications with demanding
-      performance characteristics.
-
-These subsets, or "soft partitions" must be able to be dynamically
-adjusted, as the job mix changes, without impacting other concurrently
-executing jobs. The location of the running jobs pages may also be moved
-when the memory locations are changed.
-
-The kernel cpuset patch provides the minimum essential kernel
-mechanisms required to efficiently implement such subsets.  It
-leverages existing CPU and Memory Placement facilities in the Linux
-kernel to avoid any additional impact on the critical scheduler or
-memory allocator code.
-
-
-1.3 How are cpusets implemented ?
----------------------------------
-
-Cpusets provide a Linux kernel mechanism to constrain which CPUs and
-Memory Nodes are used by a process or set of processes.
-
-The Linux kernel already has a pair of mechanisms to specify on which
-CPUs a task may be scheduled (sched_setaffinity) and on which Memory
-Nodes it may obtain memory (mbind, set_mempolicy).
-
-Cpusets extends these two mechanisms as follows:
-
- - Cpusets are sets of allowed CPUs and Memory Nodes, known to the
-   kernel.
- - Each task in the system is attached to a cpuset, via a pointer
-   in the task structure to a reference counted cgroup structure.
- - Calls to sched_setaffinity are filtered to just those CPUs
-   allowed in that task's cpuset.
- - Calls to mbind and set_mempolicy are filtered to just
-   those Memory Nodes allowed in that task's cpuset.
- - The root cpuset contains all the systems CPUs and Memory
-   Nodes.
- - For any cpuset, one can define child cpusets containing a subset
-   of the parents CPU and Memory Node resources.
- - The hierarchy of cpusets can be mounted at /dev/cpuset, for
-   browsing and manipulation from user space.
- - A cpuset may be marked exclusive, which ensures that no other
-   cpuset (except direct ancestors and descendants) may contain
-   any overlapping CPUs or Memory Nodes.
- - You can list all the tasks (by pid) attached to any cpuset.
-
-The implementation of cpusets requires a few, simple hooks
-into the rest of the kernel, none in performance critical paths:
-
- - in init/main.c, to initialize the root cpuset at system boot.
- - in fork and exit, to attach and detach a task from its cpuset.
- - in sched_setaffinity, to mask the requested CPUs by what's
-   allowed in that task's cpuset.
- - in sched.c migrate_live_tasks(), to keep migrating tasks within
-   the CPUs allowed by their cpuset, if possible.
- - in the mbind and set_mempolicy system calls, to mask the requested
-   Memory Nodes by what's allowed in that task's cpuset.
- - in page_alloc.c, to restrict memory to allowed nodes.
- - in vmscan.c, to restrict page recovery to the current cpuset.
-
-You should mount the "cgroup" filesystem type in order to enable
-browsing and modifying the cpusets presently known to the kernel.  No
-new system calls are added for cpusets - all support for querying and
-modifying cpusets is via this cpuset file system.
-
-The /proc/<pid>/status file for each task has four added lines,
-displaying the task's cpus_allowed (on which CPUs it may be scheduled)
-and mems_allowed (on which Memory Nodes it may obtain memory),
-in the two formats seen in the following example:
-
-  Cpus_allowed:   ffffffff,ffffffff,ffffffff,ffffffff
-  Cpus_allowed_list:      0-127
-  Mems_allowed:   ffffffff,ffffffff
-  Mems_allowed_list:      0-63
-
-Each cpuset is represented by a directory in the cgroup file system
-containing (on top of the standard cgroup files) the following
-files describing that cpuset:
-
- - cpuset.cpus: list of CPUs in that cpuset
- - cpuset.mems: list of Memory Nodes in that cpuset
- - cpuset.memory_migrate flag: if set, move pages to cpusets nodes
- - cpuset.cpu_exclusive flag: is cpu placement exclusive?
- - cpuset.mem_exclusive flag: is memory placement exclusive?
- - cpuset.mem_hardwall flag:  is memory allocation hardwalled
- - cpuset.memory_pressure: measure of how much paging pressure in cpuset
- - cpuset.memory_spread_page flag: if set, spread page cache evenly on allowed nodes
- - cpuset.memory_spread_slab flag: if set, spread slab cache evenly on allowed nodes
- - cpuset.sched_load_balance flag: if set, load balance within CPUs on that cpuset
- - cpuset.sched_relax_domain_level: the searching range when migrating tasks
-
-In addition, only the root cpuset has the following file:
- - cpuset.memory_pressure_enabled flag: compute memory_pressure?
-
-New cpusets are created using the mkdir system call or shell
-command.  The properties of a cpuset, such as its flags, allowed
-CPUs and Memory Nodes, and attached tasks, are modified by writing
-to the appropriate file in that cpusets directory, as listed above.
-
-The named hierarchical structure of nested cpusets allows partitioning
-a large system into nested, dynamically changeable, "soft-partitions".
-
-The attachment of each task, automatically inherited at fork by any
-children of that task, to a cpuset allows organizing the work load
-on a system into related sets of tasks such that each set is constrained
-to using the CPUs and Memory Nodes of a particular cpuset.  A task
-may be re-attached to any other cpuset, if allowed by the permissions
-on the necessary cpuset file system directories.
-
-Such management of a system "in the large" integrates smoothly with
-the detailed placement done on individual tasks and memory regions
-using the sched_setaffinity, mbind and set_mempolicy system calls.
-
-The following rules apply to each cpuset:
-
- - Its CPUs and Memory Nodes must be a subset of its parents.
- - It can't be marked exclusive unless its parent is.
- - If its cpu or memory is exclusive, they may not overlap any sibling.
-
-These rules, and the natural hierarchy of cpusets, enable efficient
-enforcement of the exclusive guarantee, without having to scan all
-cpusets every time any of them change to ensure nothing overlaps a
-exclusive cpuset.  Also, the use of a Linux virtual file system (vfs)
-to represent the cpuset hierarchy provides for a familiar permission
-and name space for cpusets, with a minimum of additional kernel code.
-
-The cpus and mems files in the root (top_cpuset) cpuset are
-read-only.  The cpus file automatically tracks the value of
-cpu_online_mask using a CPU hotplug notifier, and the mems file
-automatically tracks the value of node_states[N_MEMORY]--i.e.,
-nodes with memory--using the cpuset_track_online_nodes() hook.
-
-
-1.4 What are exclusive cpusets ?
---------------------------------
-
-If a cpuset is cpu or mem exclusive, no other cpuset, other than
-a direct ancestor or descendant, may share any of the same CPUs or
-Memory Nodes.
-
-A cpuset that is cpuset.mem_exclusive *or* cpuset.mem_hardwall is "hardwalled",
-i.e. it restricts kernel allocations for page, buffer and other data
-commonly shared by the kernel across multiple users.  All cpusets,
-whether hardwalled or not, restrict allocations of memory for user
-space.  This enables configuring a system so that several independent
-jobs can share common kernel data, such as file system pages, while
-isolating each job's user allocation in its own cpuset.  To do this,
-construct a large mem_exclusive cpuset to hold all the jobs, and
-construct child, non-mem_exclusive cpusets for each individual job.
-Only a small amount of typical kernel memory, such as requests from
-interrupt handlers, is allowed to be taken outside even a
-mem_exclusive cpuset.
-
-
-1.5 What is memory_pressure ?
------------------------------
-The memory_pressure of a cpuset provides a simple per-cpuset metric
-of the rate that the tasks in a cpuset are attempting to free up in
-use memory on the nodes of the cpuset to satisfy additional memory
-requests.
-
-This enables batch managers monitoring jobs running in dedicated
-cpusets to efficiently detect what level of memory pressure that job
-is causing.
-
-This is useful both on tightly managed systems running a wide mix of
-submitted jobs, which may choose to terminate or re-prioritize jobs that
-are trying to use more memory than allowed on the nodes assigned to them,
-and with tightly coupled, long running, massively parallel scientific
-computing jobs that will dramatically fail to meet required performance
-goals if they start to use more memory than allowed to them.
-
-This mechanism provides a very economical way for the batch manager
-to monitor a cpuset for signs of memory pressure.  It's up to the
-batch manager or other user code to decide what to do about it and
-take action.
-
-==> Unless this feature is enabled by writing "1" to the special file
-    /dev/cpuset/memory_pressure_enabled, the hook in the rebalance
-    code of __alloc_pages() for this metric reduces to simply noticing
-    that the cpuset_memory_pressure_enabled flag is zero.  So only
-    systems that enable this feature will compute the metric.
-
-Why a per-cpuset, running average:
-
-    Because this meter is per-cpuset, rather than per-task or mm,
-    the system load imposed by a batch scheduler monitoring this
-    metric is sharply reduced on large systems, because a scan of
-    the tasklist can be avoided on each set of queries.
-
-    Because this meter is a running average, instead of an accumulating
-    counter, a batch scheduler can detect memory pressure with a
-    single read, instead of having to read and accumulate results
-    for a period of time.
-
-    Because this meter is per-cpuset rather than per-task or mm,
-    the batch scheduler can obtain the key information, memory
-    pressure in a cpuset, with a single read, rather than having to
-    query and accumulate results over all the (dynamically changing)
-    set of tasks in the cpuset.
-
-A per-cpuset simple digital filter (requires a spinlock and 3 words
-of data per-cpuset) is kept, and updated by any task attached to that
-cpuset, if it enters the synchronous (direct) page reclaim code.
-
-A per-cpuset file provides an integer number representing the recent
-(half-life of 10 seconds) rate of direct page reclaims caused by
-the tasks in the cpuset, in units of reclaims attempted per second,
-times 1000.
-
-
-1.6 What is memory spread ?
----------------------------
-There are two boolean flag files per cpuset that control where the
-kernel allocates pages for the file system buffers and related in
-kernel data structures.  They are called 'cpuset.memory_spread_page' and
-'cpuset.memory_spread_slab'.
-
-If the per-cpuset boolean flag file 'cpuset.memory_spread_page' is set, then
-the kernel will spread the file system buffers (page cache) evenly
-over all the nodes that the faulting task is allowed to use, instead
-of preferring to put those pages on the node where the task is running.
-
-If the per-cpuset boolean flag file 'cpuset.memory_spread_slab' is set,
-then the kernel will spread some file system related slab caches,
-such as for inodes and dentries evenly over all the nodes that the
-faulting task is allowed to use, instead of preferring to put those
-pages on the node where the task is running.
-
-The setting of these flags does not affect anonymous data segment or
-stack segment pages of a task.
-
-By default, both kinds of memory spreading are off, and memory
-pages are allocated on the node local to where the task is running,
-except perhaps as modified by the task's NUMA mempolicy or cpuset
-configuration, so long as sufficient free memory pages are available.
-
-When new cpusets are created, they inherit the memory spread settings
-of their parent.
-
-Setting memory spreading causes allocations for the affected page
-or slab caches to ignore the task's NUMA mempolicy and be spread
-instead.    Tasks using mbind() or set_mempolicy() calls to set NUMA
-mempolicies will not notice any change in these calls as a result of
-their containing task's memory spread settings.  If memory spreading
-is turned off, then the currently specified NUMA mempolicy once again
-applies to memory page allocations.
-
-Both 'cpuset.memory_spread_page' and 'cpuset.memory_spread_slab' are boolean flag
-files.  By default they contain "0", meaning that the feature is off
-for that cpuset.  If a "1" is written to that file, then that turns
-the named feature on.
-
-The implementation is simple.
-
-Setting the flag 'cpuset.memory_spread_page' turns on a per-process flag
-PFA_SPREAD_PAGE for each task that is in that cpuset or subsequently
-joins that cpuset.  The page allocation calls for the page cache
-is modified to perform an inline check for this PFA_SPREAD_PAGE task
-flag, and if set, a call to a new routine cpuset_mem_spread_node()
-returns the node to prefer for the allocation.
-
-Similarly, setting 'cpuset.memory_spread_slab' turns on the flag
-PFA_SPREAD_SLAB, and appropriately marked slab caches will allocate
-pages from the node returned by cpuset_mem_spread_node().
-
-The cpuset_mem_spread_node() routine is also simple.  It uses the
-value of a per-task rotor cpuset_mem_spread_rotor to select the next
-node in the current task's mems_allowed to prefer for the allocation.
-
-This memory placement policy is also known (in other contexts) as
-round-robin or interleave.
-
-This policy can provide substantial improvements for jobs that need
-to place thread local data on the corresponding node, but that need
-to access large file system data sets that need to be spread across
-the several nodes in the jobs cpuset in order to fit.  Without this
-policy, especially for jobs that might have one thread reading in the
-data set, the memory allocation across the nodes in the jobs cpuset
-can become very uneven.
-
-1.7 What is sched_load_balance ?
---------------------------------
-
-The kernel scheduler (kernel/sched/core.c) automatically load balances
-tasks.  If one CPU is underutilized, kernel code running on that
-CPU will look for tasks on other more overloaded CPUs and move those
-tasks to itself, within the constraints of such placement mechanisms
-as cpusets and sched_setaffinity.
-
-The algorithmic cost of load balancing and its impact on key shared
-kernel data structures such as the task list increases more than
-linearly with the number of CPUs being balanced.  So the scheduler
-has support to partition the systems CPUs into a number of sched
-domains such that it only load balances within each sched domain.
-Each sched domain covers some subset of the CPUs in the system;
-no two sched domains overlap; some CPUs might not be in any sched
-domain and hence won't be load balanced.
-
-Put simply, it costs less to balance between two smaller sched domains
-than one big one, but doing so means that overloads in one of the
-two domains won't be load balanced to the other one.
-
-By default, there is one sched domain covering all CPUs, including those
-marked isolated using the kernel boot time "isolcpus=" argument. However,
-the isolated CPUs will not participate in load balancing, and will not
-have tasks running on them unless explicitly assigned.
-
-This default load balancing across all CPUs is not well suited for
-the following two situations:
- 1) On large systems, load balancing across many CPUs is expensive.
-    If the system is managed using cpusets to place independent jobs
-    on separate sets of CPUs, full load balancing is unnecessary.
- 2) Systems supporting realtime on some CPUs need to minimize
-    system overhead on those CPUs, including avoiding task load
-    balancing if that is not needed.
-
-When the per-cpuset flag "cpuset.sched_load_balance" is enabled (the default
-setting), it requests that all the CPUs in that cpusets allowed 'cpuset.cpus'
-be contained in a single sched domain, ensuring that load balancing
-can move a task (not otherwised pinned, as by sched_setaffinity)
-from any CPU in that cpuset to any other.
-
-When the per-cpuset flag "cpuset.sched_load_balance" is disabled, then the
-scheduler will avoid load balancing across the CPUs in that cpuset,
---except-- in so far as is necessary because some overlapping cpuset
-has "sched_load_balance" enabled.
-
-So, for example, if the top cpuset has the flag "cpuset.sched_load_balance"
-enabled, then the scheduler will have one sched domain covering all
-CPUs, and the setting of the "cpuset.sched_load_balance" flag in any other
-cpusets won't matter, as we're already fully load balancing.
-
-Therefore in the above two situations, the top cpuset flag
-"cpuset.sched_load_balance" should be disabled, and only some of the smaller,
-child cpusets have this flag enabled.
-
-When doing this, you don't usually want to leave any unpinned tasks in
-the top cpuset that might use non-trivial amounts of CPU, as such tasks
-may be artificially constrained to some subset of CPUs, depending on
-the particulars of this flag setting in descendant cpusets.  Even if
-such a task could use spare CPU cycles in some other CPUs, the kernel
-scheduler might not consider the possibility of load balancing that
-task to that underused CPU.
-
-Of course, tasks pinned to a particular CPU can be left in a cpuset
-that disables "cpuset.sched_load_balance" as those tasks aren't going anywhere
-else anyway.
-
-There is an impedance mismatch here, between cpusets and sched domains.
-Cpusets are hierarchical and nest.  Sched domains are flat; they don't
-overlap and each CPU is in at most one sched domain.
-
-It is necessary for sched domains to be flat because load balancing
-across partially overlapping sets of CPUs would risk unstable dynamics
-that would be beyond our understanding.  So if each of two partially
-overlapping cpusets enables the flag 'cpuset.sched_load_balance', then we
-form a single sched domain that is a superset of both.  We won't move
-a task to a CPU outside its cpuset, but the scheduler load balancing
-code might waste some compute cycles considering that possibility.
-
-This mismatch is why there is not a simple one-to-one relation
-between which cpusets have the flag "cpuset.sched_load_balance" enabled,
-and the sched domain configuration.  If a cpuset enables the flag, it
-will get balancing across all its CPUs, but if it disables the flag,
-it will only be assured of no load balancing if no other overlapping
-cpuset enables the flag.
-
-If two cpusets have partially overlapping 'cpuset.cpus' allowed, and only
-one of them has this flag enabled, then the other may find its
-tasks only partially load balanced, just on the overlapping CPUs.
-This is just the general case of the top_cpuset example given a few
-paragraphs above.  In the general case, as in the top cpuset case,
-don't leave tasks that might use non-trivial amounts of CPU in
-such partially load balanced cpusets, as they may be artificially
-constrained to some subset of the CPUs allowed to them, for lack of
-load balancing to the other CPUs.
-
-CPUs in "cpuset.isolcpus" were excluded from load balancing by the
-isolcpus= kernel boot option, and will never be load balanced regardless
-of the value of "cpuset.sched_load_balance" in any cpuset.
-
-1.7.1 sched_load_balance implementation details.
-------------------------------------------------
-
-The per-cpuset flag 'cpuset.sched_load_balance' defaults to enabled (contrary
-to most cpuset flags.)  When enabled for a cpuset, the kernel will
-ensure that it can load balance across all the CPUs in that cpuset
-(makes sure that all the CPUs in the cpus_allowed of that cpuset are
-in the same sched domain.)
-
-If two overlapping cpusets both have 'cpuset.sched_load_balance' enabled,
-then they will be (must be) both in the same sched domain.
-
-If, as is the default, the top cpuset has 'cpuset.sched_load_balance' enabled,
-then by the above that means there is a single sched domain covering
-the whole system, regardless of any other cpuset settings.
-
-The kernel commits to user space that it will avoid load balancing
-where it can.  It will pick as fine a granularity partition of sched
-domains as it can while still providing load balancing for any set
-of CPUs allowed to a cpuset having 'cpuset.sched_load_balance' enabled.
-
-The internal kernel cpuset to scheduler interface passes from the
-cpuset code to the scheduler code a partition of the load balanced
-CPUs in the system. This partition is a set of subsets (represented
-as an array of struct cpumask) of CPUs, pairwise disjoint, that cover
-all the CPUs that must be load balanced.
-
-The cpuset code builds a new such partition and passes it to the
-scheduler sched domain setup code, to have the sched domains rebuilt
-as necessary, whenever:
- - the 'cpuset.sched_load_balance' flag of a cpuset with non-empty CPUs changes,
- - or CPUs come or go from a cpuset with this flag enabled,
- - or 'cpuset.sched_relax_domain_level' value of a cpuset with non-empty CPUs
-   and with this flag enabled changes,
- - or a cpuset with non-empty CPUs and with this flag enabled is removed,
- - or a cpu is offlined/onlined.
-
-This partition exactly defines what sched domains the scheduler should
-setup - one sched domain for each element (struct cpumask) in the
-partition.
-
-The scheduler remembers the currently active sched domain partitions.
-When the scheduler routine partition_sched_domains() is invoked from
-the cpuset code to update these sched domains, it compares the new
-partition requested with the current, and updates its sched domains,
-removing the old and adding the new, for each change.
-
-
-1.8 What is sched_relax_domain_level ?
---------------------------------------
-
-In sched domain, the scheduler migrates tasks in 2 ways; periodic load
-balance on tick, and at time of some schedule events.
-
-When a task is woken up, scheduler try to move the task on idle CPU.
-For example, if a task A running on CPU X activates another task B
-on the same CPU X, and if CPU Y is X's sibling and performing idle,
-then scheduler migrate task B to CPU Y so that task B can start on
-CPU Y without waiting task A on CPU X.
-
-And if a CPU run out of tasks in its runqueue, the CPU try to pull
-extra tasks from other busy CPUs to help them before it is going to
-be idle.
-
-Of course it takes some searching cost to find movable tasks and/or
-idle CPUs, the scheduler might not search all CPUs in the domain
-every time.  In fact, in some architectures, the searching ranges on
-events are limited in the same socket or node where the CPU locates,
-while the load balance on tick searches all.
-
-For example, assume CPU Z is relatively far from CPU X.  Even if CPU Z
-is idle while CPU X and the siblings are busy, scheduler can't migrate
-woken task B from X to Z since it is out of its searching range.
-As the result, task B on CPU X need to wait task A or wait load balance
-on the next tick.  For some applications in special situation, waiting
-1 tick may be too long.
-
-The 'cpuset.sched_relax_domain_level' file allows you to request changing
-this searching range as you like.  This file takes int value which
-indicates size of searching range in levels ideally as follows,
-otherwise initial value -1 that indicates the cpuset has no request.
-
-  -1  : no request. use system default or follow request of others.
-   0  : no search.
-   1  : search siblings (hyperthreads in a core).
-   2  : search cores in a package.
-   3  : search cpus in a node [= system wide on non-NUMA system]
-   4  : search nodes in a chunk of node [on NUMA system]
-   5  : search system wide [on NUMA system]
-
-The system default is architecture dependent.  The system default
-can be changed using the relax_domain_level= boot parameter.
-
-This file is per-cpuset and affect the sched domain where the cpuset
-belongs to.  Therefore if the flag 'cpuset.sched_load_balance' of a cpuset
-is disabled, then 'cpuset.sched_relax_domain_level' have no effect since
-there is no sched domain belonging the cpuset.
-
-If multiple cpusets are overlapping and hence they form a single sched
-domain, the largest value among those is used.  Be careful, if one
-requests 0 and others are -1 then 0 is used.
-
-Note that modifying this file will have both good and bad effects,
-and whether it is acceptable or not depends on your situation.
-Don't modify this file if you are not sure.
-
-If your situation is:
- - The migration costs between each cpu can be assumed considerably
-   small(for you) due to your special application's behavior or
-   special hardware support for CPU cache etc.
- - The searching cost doesn't have impact(for you) or you can make
-   the searching cost enough small by managing cpuset to compact etc.
- - The latency is required even it sacrifices cache hit rate etc.
-then increasing 'sched_relax_domain_level' would benefit you.
-
-
-1.9 How do I use cpusets ?
---------------------------
-
-In order to minimize the impact of cpusets on critical kernel
-code, such as the scheduler, and due to the fact that the kernel
-does not support one task updating the memory placement of another
-task directly, the impact on a task of changing its cpuset CPU
-or Memory Node placement, or of changing to which cpuset a task
-is attached, is subtle.
-
-If a cpuset has its Memory Nodes modified, then for each task attached
-to that cpuset, the next time that the kernel attempts to allocate
-a page of memory for that task, the kernel will notice the change
-in the task's cpuset, and update its per-task memory placement to
-remain within the new cpusets memory placement.  If the task was using
-mempolicy MPOL_BIND, and the nodes to which it was bound overlap with
-its new cpuset, then the task will continue to use whatever subset
-of MPOL_BIND nodes are still allowed in the new cpuset.  If the task
-was using MPOL_BIND and now none of its MPOL_BIND nodes are allowed
-in the new cpuset, then the task will be essentially treated as if it
-was MPOL_BIND bound to the new cpuset (even though its NUMA placement,
-as queried by get_mempolicy(), doesn't change).  If a task is moved
-from one cpuset to another, then the kernel will adjust the task's
-memory placement, as above, the next time that the kernel attempts
-to allocate a page of memory for that task.
-
-If a cpuset has its 'cpuset.cpus' modified, then each task in that cpuset
-will have its allowed CPU placement changed immediately.  Similarly,
-if a task's pid is written to another cpusets 'cpuset.tasks' file, then its
-allowed CPU placement is changed immediately.  If such a task had been
-bound to some subset of its cpuset using the sched_setaffinity() call,
-the task will be allowed to run on any CPU allowed in its new cpuset,
-negating the effect of the prior sched_setaffinity() call.
-
-In summary, the memory placement of a task whose cpuset is changed is
-updated by the kernel, on the next allocation of a page for that task,
-and the processor placement is updated immediately.
-
-Normally, once a page is allocated (given a physical page
-of main memory) then that page stays on whatever node it
-was allocated, so long as it remains allocated, even if the
-cpusets memory placement policy 'cpuset.mems' subsequently changes.
-If the cpuset flag file 'cpuset.memory_migrate' is set true, then when
-tasks are attached to that cpuset, any pages that task had
-allocated to it on nodes in its previous cpuset are migrated
-to the task's new cpuset. The relative placement of the page within
-the cpuset is preserved during these migration operations if possible.
-For example if the page was on the second valid node of the prior cpuset
-then the page will be placed on the second valid node of the new cpuset.
-
-Also if 'cpuset.memory_migrate' is set true, then if that cpuset's
-'cpuset.mems' file is modified, pages allocated to tasks in that
-cpuset, that were on nodes in the previous setting of 'cpuset.mems',
-will be moved to nodes in the new setting of 'mems.'
-Pages that were not in the task's prior cpuset, or in the cpuset's
-prior 'cpuset.mems' setting, will not be moved.
-
-There is an exception to the above.  If hotplug functionality is used
-to remove all the CPUs that are currently assigned to a cpuset,
-then all the tasks in that cpuset will be moved to the nearest ancestor
-with non-empty cpus.  But the moving of some (or all) tasks might fail if
-cpuset is bound with another cgroup subsystem which has some restrictions
-on task attaching.  In this failing case, those tasks will stay
-in the original cpuset, and the kernel will automatically update
-their cpus_allowed to allow all online CPUs.  When memory hotplug
-functionality for removing Memory Nodes is available, a similar exception
-is expected to apply there as well.  In general, the kernel prefers to
-violate cpuset placement, over starving a task that has had all
-its allowed CPUs or Memory Nodes taken offline.
-
-There is a second exception to the above.  GFP_ATOMIC requests are
-kernel internal allocations that must be satisfied, immediately.
-The kernel may drop some request, in rare cases even panic, if a
-GFP_ATOMIC alloc fails.  If the request cannot be satisfied within
-the current task's cpuset, then we relax the cpuset, and look for
-memory anywhere we can find it.  It's better to violate the cpuset
-than stress the kernel.
-
-To start a new job that is to be contained within a cpuset, the steps are:
-
- 1) mkdir /sys/fs/cgroup/cpuset
- 2) mount -t cgroup -ocpuset cpuset /sys/fs/cgroup/cpuset
- 3) Create the new cpuset by doing mkdir's and write's (or echo's) in
-    the /sys/fs/cgroup/cpuset virtual file system.
- 4) Start a task that will be the "founding father" of the new job.
- 5) Attach that task to the new cpuset by writing its pid to the
-    /sys/fs/cgroup/cpuset tasks file for that cpuset.
- 6) fork, exec or clone the job tasks from this founding father task.
-
-For example, the following sequence of commands will setup a cpuset
-named "Charlie", containing just CPUs 2 and 3, and Memory Node 1,
-and then start a subshell 'sh' in that cpuset:
-
-  mount -t cgroup -ocpuset cpuset /sys/fs/cgroup/cpuset
-  cd /sys/fs/cgroup/cpuset
-  mkdir Charlie
-  cd Charlie
-  /bin/echo 2-3 > cpuset.cpus
-  /bin/echo 1 > cpuset.mems
-  /bin/echo $$ > tasks
-  sh
-  # The subshell 'sh' is now running in cpuset Charlie
-  # The next line should display '/Charlie'
-  cat /proc/self/cpuset
-
-There are ways to query or modify cpusets:
- - via the cpuset file system directly, using the various cd, mkdir, echo,
-   cat, rmdir commands from the shell, or their equivalent from C.
- - via the C library libcpuset.
- - via the C library libcgroup.
-   (http://sourceforge.net/projects/libcg/)
- - via the python application cset.
-   (http://code.google.com/p/cpuset/)
-
-The sched_setaffinity calls can also be done at the shell prompt using
-SGI's runon or Robert Love's taskset.  The mbind and set_mempolicy
-calls can be done at the shell prompt using the numactl command
-(part of Andi Kleen's numa package).
-
-2. Usage Examples and Syntax
-============================
-
-2.1 Basic Usage
----------------
-
-Creating, modifying, using the cpusets can be done through the cpuset
-virtual filesystem.
-
-To mount it, type:
-# mount -t cgroup -o cpuset cpuset /sys/fs/cgroup/cpuset
-
-Then under /sys/fs/cgroup/cpuset you can find a tree that corresponds to the
-tree of the cpusets in the system. For instance, /sys/fs/cgroup/cpuset
-is the cpuset that holds the whole system.
-
-If you want to create a new cpuset under /sys/fs/cgroup/cpuset:
-# cd /sys/fs/cgroup/cpuset
-# mkdir my_cpuset
-
-Now you want to do something with this cpuset.
-# cd my_cpuset
-
-In this directory you can find several files:
-# ls
-cgroup.clone_children  cpuset.memory_pressure
-cgroup.event_control   cpuset.memory_spread_page
-cgroup.procs           cpuset.memory_spread_slab
-cpuset.cpu_exclusive   cpuset.mems
-cpuset.cpus            cpuset.sched_load_balance
-cpuset.mem_exclusive   cpuset.sched_relax_domain_level
-cpuset.mem_hardwall    notify_on_release
-cpuset.memory_migrate  tasks
-
-Reading them will give you information about the state of this cpuset:
-the CPUs and Memory Nodes it can use, the processes that are using
-it, its properties.  By writing to these files you can manipulate
-the cpuset.
-
-Set some flags:
-# /bin/echo 1 > cpuset.cpu_exclusive
-
-Add some cpus:
-# /bin/echo 0-7 > cpuset.cpus
-
-Add some mems:
-# /bin/echo 0-7 > cpuset.mems
-
-Now attach your shell to this cpuset:
-# /bin/echo $$ > tasks
-
-You can also create cpusets inside your cpuset by using mkdir in this
-directory.
-# mkdir my_sub_cs
-
-To remove a cpuset, just use rmdir:
-# rmdir my_sub_cs
-This will fail if the cpuset is in use (has cpusets inside, or has
-processes attached).
-
-Note that for legacy reasons, the "cpuset" filesystem exists as a
-wrapper around the cgroup filesystem.
-
-The command
-
-mount -t cpuset X /sys/fs/cgroup/cpuset
-
-is equivalent to
-
-mount -t cgroup -ocpuset,noprefix X /sys/fs/cgroup/cpuset
-echo "/sbin/cpuset_release_agent" > /sys/fs/cgroup/cpuset/release_agent
-
-2.2 Adding/removing cpus
-------------------------
-
-This is the syntax to use when writing in the cpus or mems files
-in cpuset directories:
-
-# /bin/echo 1-4 > cpuset.cpus          -> set cpus list to cpus 1,2,3,4
-# /bin/echo 1,2,3,4 > cpuset.cpus      -> set cpus list to cpus 1,2,3,4
-
-To add a CPU to a cpuset, write the new list of CPUs including the
-CPU to be added. To add 6 to the above cpuset:
-
-# /bin/echo 1-4,6 > cpuset.cpus        -> set cpus list to cpus 1,2,3,4,6
-
-Similarly to remove a CPU from a cpuset, write the new list of CPUs
-without the CPU to be removed.
-
-To remove all the CPUs:
-
-# /bin/echo "" > cpuset.cpus           -> clear cpus list
-
-2.3 Setting flags
------------------
-
-The syntax is very simple:
-
-# /bin/echo 1 > cpuset.cpu_exclusive   -> set flag 'cpuset.cpu_exclusive'
-# /bin/echo 0 > cpuset.cpu_exclusive   -> unset flag 'cpuset.cpu_exclusive'
-
-2.4 Attaching processes
------------------------
-
-# /bin/echo PID > tasks
-
-Note that it is PID, not PIDs. You can only attach ONE task at a time.
-If you have several tasks to attach, you have to do it one after another:
-
-# /bin/echo PID1 > tasks
-# /bin/echo PID2 > tasks
-       ...
-# /bin/echo PIDn > tasks
-
-
-3. Questions
-============
-
-Q: what's up with this '/bin/echo' ?
-A: bash's builtin 'echo' command does not check calls to write() against
-   errors. If you use it in the cpuset file system, you won't be
-   able to tell whether a command succeeded or failed.
-
-Q: When I attach processes, only the first of the line gets really attached !
-A: We can only return one error code per call to write(). So you should also
-   put only ONE pid.
-
-4. Contact
-==========
-
-Web: http://www.bullopensource.org/cpuset
diff --git a/Documentation/cgroups/devices.txt b/Documentation/cgroups/devices.txt
deleted file mode 100644 (file)
index 3c1095c..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-Device Whitelist Controller
-
-1. Description:
-
-Implement a cgroup to track and enforce open and mknod restrictions
-on device files.  A device cgroup associates a device access
-whitelist with each cgroup.  A whitelist entry has 4 fields.
-'type' is a (all), c (char), or b (block).  'all' means it applies
-to all types and all major and minor numbers.  Major and minor are
-either an integer or * for all.  Access is a composition of r
-(read), w (write), and m (mknod).
-
-The root device cgroup starts with rwm to 'all'.  A child device
-cgroup gets a copy of the parent.  Administrators can then remove
-devices from the whitelist or add new entries.  A child cgroup can
-never receive a device access which is denied by its parent.
-
-2. User Interface
-
-An entry is added using devices.allow, and removed using
-devices.deny.  For instance
-
-       echo 'c 1:3 mr' > /sys/fs/cgroup/1/devices.allow
-
-allows cgroup 1 to read and mknod the device usually known as
-/dev/null.  Doing
-
-       echo a > /sys/fs/cgroup/1/devices.deny
-
-will remove the default 'a *:* rwm' entry. Doing
-
-       echo a > /sys/fs/cgroup/1/devices.allow
-
-will add the 'a *:* rwm' entry to the whitelist.
-
-3. Security
-
-Any task can move itself between cgroups.  This clearly won't
-suffice, but we can decide the best way to adequately restrict
-movement as people get some experience with this.  We may just want
-to require CAP_SYS_ADMIN, which at least is a separate bit from
-CAP_MKNOD.  We may want to just refuse moving to a cgroup which
-isn't a descendant of the current one.  Or we may want to use
-CAP_MAC_ADMIN, since we really are trying to lock down root.
-
-CAP_SYS_ADMIN is needed to modify the whitelist or move another
-task to a new cgroup.  (Again we'll probably want to change that).
-
-A cgroup may not be granted more permissions than the cgroup's
-parent has.
-
-4. Hierarchy
-
-device cgroups maintain hierarchy by making sure a cgroup never has more
-access permissions than its parent.  Every time an entry is written to
-a cgroup's devices.deny file, all its children will have that entry removed
-from their whitelist and all the locally set whitelist entries will be
-re-evaluated.  In case one of the locally set whitelist entries would provide
-more access than the cgroup's parent, it'll be removed from the whitelist.
-
-Example:
-      A
-     / \
-        B
-
-    group        behavior      exceptions
-    A            allow         "b 8:* rwm", "c 116:1 rw"
-    B            deny          "c 1:3 rwm", "c 116:2 rwm", "b 3:* rwm"
-
-If a device is denied in group A:
-       # echo "c 116:* r" > A/devices.deny
-it'll propagate down and after revalidating B's entries, the whitelist entry
-"c 116:2 rwm" will be removed:
-
-    group        whitelist entries                        denied devices
-    A            all                                      "b 8:* rwm", "c 116:* rw"
-    B            "c 1:3 rwm", "b 3:* rwm"                 all the rest
-
-In case parent's exceptions change and local exceptions are not allowed
-anymore, they'll be deleted.
-
-Notice that new whitelist entries will not be propagated:
-      A
-     / \
-        B
-
-    group        whitelist entries                        denied devices
-    A            "c 1:3 rwm", "c 1:5 r"                   all the rest
-    B            "c 1:3 rwm", "c 1:5 r"                   all the rest
-
-when adding "c *:3 rwm":
-       # echo "c *:3 rwm" >A/devices.allow
-
-the result:
-    group        whitelist entries                        denied devices
-    A            "c *:3 rwm", "c 1:5 r"                   all the rest
-    B            "c 1:3 rwm", "c 1:5 r"                   all the rest
-
-but now it'll be possible to add new entries to B:
-       # echo "c 2:3 rwm" >B/devices.allow
-       # echo "c 50:3 r" >B/devices.allow
-or even
-       # echo "c *:3 rwm" >B/devices.allow
-
-Allowing or denying all by writing 'a' to devices.allow or devices.deny will
-not be possible once the device cgroups has children.
-
-4.1 Hierarchy (internal implementation)
-
-device cgroups is implemented internally using a behavior (ALLOW, DENY) and a
-list of exceptions.  The internal state is controlled using the same user
-interface to preserve compatibility with the previous whitelist-only
-implementation.  Removal or addition of exceptions that will reduce the access
-to devices will be propagated down the hierarchy.
-For every propagated exception, the effective rules will be re-evaluated based
-on current parent's access rules.
diff --git a/Documentation/cgroups/freezer-subsystem.txt b/Documentation/cgroups/freezer-subsystem.txt
deleted file mode 100644 (file)
index e831cb2..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-The cgroup freezer is useful to batch job management system which start
-and stop sets of tasks in order to schedule the resources of a machine
-according to the desires of a system administrator. This sort of program
-is often used on HPC clusters to schedule access to the cluster as a
-whole. The cgroup freezer uses cgroups to describe the set of tasks to
-be started/stopped by the batch job management system. It also provides
-a means to start and stop the tasks composing the job.
-
-The cgroup freezer will also be useful for checkpointing running groups
-of tasks. The freezer allows the checkpoint code to obtain a consistent
-image of the tasks by attempting to force the tasks in a cgroup into a
-quiescent state. Once the tasks are quiescent another task can
-walk /proc or invoke a kernel interface to gather information about the
-quiesced tasks. Checkpointed tasks can be restarted later should a
-recoverable error occur. This also allows the checkpointed tasks to be
-migrated between nodes in a cluster by copying the gathered information
-to another node and restarting the tasks there.
-
-Sequences of SIGSTOP and SIGCONT are not always sufficient for stopping
-and resuming tasks in userspace. Both of these signals are observable
-from within the tasks we wish to freeze. While SIGSTOP cannot be caught,
-blocked, or ignored it can be seen by waiting or ptracing parent tasks.
-SIGCONT is especially unsuitable since it can be caught by the task. Any
-programs designed to watch for SIGSTOP and SIGCONT could be broken by
-attempting to use SIGSTOP and SIGCONT to stop and resume tasks. We can
-demonstrate this problem using nested bash shells:
-
-       $ echo $$
-       16644
-       $ bash
-       $ echo $$
-       16690
-
-       From a second, unrelated bash shell:
-       $ kill -SIGSTOP 16690
-       $ kill -SIGCONT 16690
-
-       <at this point 16690 exits and causes 16644 to exit too>
-
-This happens because bash can observe both signals and choose how it
-responds to them.
-
-Another example of a program which catches and responds to these
-signals is gdb. In fact any program designed to use ptrace is likely to
-have a problem with this method of stopping and resuming tasks.
-
-In contrast, the cgroup freezer uses the kernel freezer code to
-prevent the freeze/unfreeze cycle from becoming visible to the tasks
-being frozen. This allows the bash example above and gdb to run as
-expected.
-
-The cgroup freezer is hierarchical. Freezing a cgroup freezes all
-tasks belonging to the cgroup and all its descendant cgroups. Each
-cgroup has its own state (self-state) and the state inherited from the
-parent (parent-state). Iff both states are THAWED, the cgroup is
-THAWED.
-
-The following cgroupfs files are created by cgroup freezer.
-
-* freezer.state: Read-write.
-
-  When read, returns the effective state of the cgroup - "THAWED",
-  "FREEZING" or "FROZEN". This is the combined self and parent-states.
-  If any is freezing, the cgroup is freezing (FREEZING or FROZEN).
-
-  FREEZING cgroup transitions into FROZEN state when all tasks
-  belonging to the cgroup and its descendants become frozen. Note that
-  a cgroup reverts to FREEZING from FROZEN after a new task is added
-  to the cgroup or one of its descendant cgroups until the new task is
-  frozen.
-
-  When written, sets the self-state of the cgroup. Two values are
-  allowed - "FROZEN" and "THAWED". If FROZEN is written, the cgroup,
-  if not already freezing, enters FREEZING state along with all its
-  descendant cgroups.
-
-  If THAWED is written, the self-state of the cgroup is changed to
-  THAWED.  Note that the effective state may not change to THAWED if
-  the parent-state is still freezing. If a cgroup's effective state
-  becomes THAWED, all its descendants which are freezing because of
-  the cgroup also leave the freezing state.
-
-* freezer.self_freezing: Read only.
-
-  Shows the self-state. 0 if the self-state is THAWED; otherwise, 1.
-  This value is 1 iff the last write to freezer.state was "FROZEN".
-
-* freezer.parent_freezing: Read only.
-
-  Shows the parent-state.  0 if none of the cgroup's ancestors is
-  frozen; otherwise, 1.
-
-The root cgroup is non-freezable and the above interface files don't
-exist.
-
-* Examples of usage :
-
-   # mkdir /sys/fs/cgroup/freezer
-   # mount -t cgroup -ofreezer freezer /sys/fs/cgroup/freezer
-   # mkdir /sys/fs/cgroup/freezer/0
-   # echo $some_pid > /sys/fs/cgroup/freezer/0/tasks
-
-to get status of the freezer subsystem :
-
-   # cat /sys/fs/cgroup/freezer/0/freezer.state
-   THAWED
-
-to freeze all tasks in the container :
-
-   # echo FROZEN > /sys/fs/cgroup/freezer/0/freezer.state
-   # cat /sys/fs/cgroup/freezer/0/freezer.state
-   FREEZING
-   # cat /sys/fs/cgroup/freezer/0/freezer.state
-   FROZEN
-
-to unfreeze all tasks in the container :
-
-   # echo THAWED > /sys/fs/cgroup/freezer/0/freezer.state
-   # cat /sys/fs/cgroup/freezer/0/freezer.state
-   THAWED
-
-This is the basic mechanism which should do the right thing for user space task
-in a simple scenario.
diff --git a/Documentation/cgroups/hugetlb.txt b/Documentation/cgroups/hugetlb.txt
deleted file mode 100644 (file)
index 106245c..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-HugeTLB Controller
--------------------
-
-The HugeTLB controller allows to limit the HugeTLB usage per control group and
-enforces the controller limit during page fault. Since HugeTLB doesn't
-support page reclaim, enforcing the limit at page fault time implies that,
-the application will get SIGBUS signal if it tries to access HugeTLB pages
-beyond its limit. This requires the application to know beforehand how much
-HugeTLB pages it would require for its use.
-
-HugeTLB controller can be created by first mounting the cgroup filesystem.
-
-# mount -t cgroup -o hugetlb none /sys/fs/cgroup
-
-With the above step, the initial or the parent HugeTLB group becomes
-visible at /sys/fs/cgroup. At bootup, this group includes all the tasks in
-the system. /sys/fs/cgroup/tasks lists the tasks in this cgroup.
-
-New groups can be created under the parent group /sys/fs/cgroup.
-
-# cd /sys/fs/cgroup
-# mkdir g1
-# echo $$ > g1/tasks
-
-The above steps create a new group g1 and move the current shell
-process (bash) into it.
-
-Brief summary of control files
-
- hugetlb.<hugepagesize>.limit_in_bytes     # set/show limit of "hugepagesize" hugetlb usage
- hugetlb.<hugepagesize>.max_usage_in_bytes # show max "hugepagesize" hugetlb  usage recorded
- hugetlb.<hugepagesize>.usage_in_bytes     # show current usage for "hugepagesize" hugetlb
- hugetlb.<hugepagesize>.failcnt                   # show the number of allocation failure due to HugeTLB limit
-
-For a system supporting two hugepage size (16M and 16G) the control
-files include:
-
-hugetlb.16GB.limit_in_bytes
-hugetlb.16GB.max_usage_in_bytes
-hugetlb.16GB.usage_in_bytes
-hugetlb.16GB.failcnt
-hugetlb.16MB.limit_in_bytes
-hugetlb.16MB.max_usage_in_bytes
-hugetlb.16MB.usage_in_bytes
-hugetlb.16MB.failcnt
diff --git a/Documentation/cgroups/memcg_test.txt b/Documentation/cgroups/memcg_test.txt
deleted file mode 100644 (file)
index 8870b02..0000000
+++ /dev/null
@@ -1,280 +0,0 @@
-Memory Resource Controller(Memcg)  Implementation Memo.
-Last Updated: 2010/2
-Base Kernel Version: based on 2.6.33-rc7-mm(candidate for 34).
-
-Because VM is getting complex (one of reasons is memcg...), memcg's behavior
-is complex. This is a document for memcg's internal behavior.
-Please note that implementation details can be changed.
-
-(*) Topics on API should be in Documentation/cgroups/memory.txt)
-
-0. How to record usage ?
-   2 objects are used.
-
-   page_cgroup ....an object per page.
-       Allocated at boot or memory hotplug. Freed at memory hot removal.
-
-   swap_cgroup ... an entry per swp_entry.
-       Allocated at swapon(). Freed at swapoff().
-
-   The page_cgroup has USED bit and double count against a page_cgroup never
-   occurs. swap_cgroup is used only when a charged page is swapped-out.
-
-1. Charge
-
-   a page/swp_entry may be charged (usage += PAGE_SIZE) at
-
-       mem_cgroup_try_charge()
-
-2. Uncharge
-  a page/swp_entry may be uncharged (usage -= PAGE_SIZE) by
-
-       mem_cgroup_uncharge()
-         Called when a page's refcount goes down to 0.
-
-       mem_cgroup_uncharge_swap()
-         Called when swp_entry's refcnt goes down to 0. A charge against swap
-         disappears.
-
-3. charge-commit-cancel
-       Memcg pages are charged in two steps:
-               mem_cgroup_try_charge()
-               mem_cgroup_commit_charge() or mem_cgroup_cancel_charge()
-
-       At try_charge(), there are no flags to say "this page is charged".
-       at this point, usage += PAGE_SIZE.
-
-       At commit(), the page is associated with the memcg.
-
-       At cancel(), simply usage -= PAGE_SIZE.
-
-Under below explanation, we assume CONFIG_MEM_RES_CTRL_SWAP=y.
-
-4. Anonymous
-       Anonymous page is newly allocated at
-                 - page fault into MAP_ANONYMOUS mapping.
-                 - Copy-On-Write.
-
-       4.1 Swap-in.
-       At swap-in, the page is taken from swap-cache. There are 2 cases.
-
-       (a) If the SwapCache is newly allocated and read, it has no charges.
-       (b) If the SwapCache has been mapped by processes, it has been
-           charged already.
-
-       4.2 Swap-out.
-       At swap-out, typical state transition is below.
-
-       (a) add to swap cache. (marked as SwapCache)
-           swp_entry's refcnt += 1.
-       (b) fully unmapped.
-           swp_entry's refcnt += # of ptes.
-       (c) write back to swap.
-       (d) delete from swap cache. (remove from SwapCache)
-           swp_entry's refcnt -= 1.
-
-
-       Finally, at task exit,
-       (e) zap_pte() is called and swp_entry's refcnt -=1 -> 0.
-
-5. Page Cache
-       Page Cache is charged at
-       - add_to_page_cache_locked().
-
-       The logic is very clear. (About migration, see below)
-       Note: __remove_from_page_cache() is called by remove_from_page_cache()
-       and __remove_mapping().
-
-6. Shmem(tmpfs) Page Cache
-       The best way to understand shmem's page state transition is to read
-       mm/shmem.c.
-       But brief explanation of the behavior of memcg around shmem will be
-       helpful to understand the logic.
-
-       Shmem's page (just leaf page, not direct/indirect block) can be on
-               - radix-tree of shmem's inode.
-               - SwapCache.
-               - Both on radix-tree and SwapCache. This happens at swap-in
-                 and swap-out,
-
-       It's charged when...
-       - A new page is added to shmem's radix-tree.
-       - A swp page is read. (move a charge from swap_cgroup to page_cgroup)
-
-7. Page Migration
-
-       mem_cgroup_migrate()
-
-8. LRU
-        Each memcg has its own private LRU. Now, its handling is under global
-       VM's control (means that it's handled under global zone->lru_lock).
-       Almost all routines around memcg's LRU is called by global LRU's
-       list management functions under zone->lru_lock().
-
-       A special function is mem_cgroup_isolate_pages(). This scans
-       memcg's private LRU and call __isolate_lru_page() to extract a page
-       from LRU.
-       (By __isolate_lru_page(), the page is removed from both of global and
-        private LRU.)
-
-
-9. Typical Tests.
-
- Tests for racy cases.
-
- 9.1 Small limit to memcg.
-       When you do test to do racy case, it's good test to set memcg's limit
-       to be very small rather than GB. Many races found in the test under
-       xKB or xxMB limits.
-       (Memory behavior under GB and Memory behavior under MB shows very
-        different situation.)
-
- 9.2 Shmem
-       Historically, memcg's shmem handling was poor and we saw some amount
-       of troubles here. This is because shmem is page-cache but can be
-       SwapCache. Test with shmem/tmpfs is always good test.
-
- 9.3 Migration
-       For NUMA, migration is an another special case. To do easy test, cpuset
-       is useful. Following is a sample script to do migration.
-
-       mount -t cgroup -o cpuset none /opt/cpuset
-
-       mkdir /opt/cpuset/01
-       echo 1 > /opt/cpuset/01/cpuset.cpus
-       echo 0 > /opt/cpuset/01/cpuset.mems
-       echo 1 > /opt/cpuset/01/cpuset.memory_migrate
-       mkdir /opt/cpuset/02
-       echo 1 > /opt/cpuset/02/cpuset.cpus
-       echo 1 > /opt/cpuset/02/cpuset.mems
-       echo 1 > /opt/cpuset/02/cpuset.memory_migrate
-
-       In above set, when you moves a task from 01 to 02, page migration to
-       node 0 to node 1 will occur. Following is a script to migrate all
-       under cpuset.
-       --
-       move_task()
-       {
-       for pid in $1
-        do
-                /bin/echo $pid >$2/tasks 2>/dev/null
-               echo -n $pid
-               echo -n " "
-        done
-       echo END
-       }
-
-       G1_TASK=`cat ${G1}/tasks`
-       G2_TASK=`cat ${G2}/tasks`
-       move_task "${G1_TASK}" ${G2} &
-       --
- 9.4 Memory hotplug.
-       memory hotplug test is one of good test.
-       to offline memory, do following.
-       # echo offline > /sys/devices/system/memory/memoryXXX/state
-       (XXX is the place of memory)
-       This is an easy way to test page migration, too.
-
- 9.5 mkdir/rmdir
-       When using hierarchy, mkdir/rmdir test should be done.
-       Use tests like the following.
-
-       echo 1 >/opt/cgroup/01/memory/use_hierarchy
-       mkdir /opt/cgroup/01/child_a
-       mkdir /opt/cgroup/01/child_b
-
-       set limit to 01.
-       add limit to 01/child_b
-       run jobs under child_a and child_b
-
-       create/delete following groups at random while jobs are running.
-       /opt/cgroup/01/child_a/child_aa
-       /opt/cgroup/01/child_b/child_bb
-       /opt/cgroup/01/child_c
-
-       running new jobs in new group is also good.
-
- 9.6 Mount with other subsystems.
-       Mounting with other subsystems is a good test because there is a
-       race and lock dependency with other cgroup subsystems.
-
-       example)
-       # mount -t cgroup none /cgroup -o cpuset,memory,cpu,devices
-
-       and do task move, mkdir, rmdir etc...under this.
-
- 9.7 swapoff.
-       Besides management of swap is one of complicated parts of memcg,
-       call path of swap-in at swapoff is not same as usual swap-in path..
-       It's worth to be tested explicitly.
-
-       For example, test like following is good.
-       (Shell-A)
-       # mount -t cgroup none /cgroup -o memory
-       # mkdir /cgroup/test
-       # echo 40M > /cgroup/test/memory.limit_in_bytes
-       # echo 0 > /cgroup/test/tasks
-       Run malloc(100M) program under this. You'll see 60M of swaps.
-       (Shell-B)
-       # move all tasks in /cgroup/test to /cgroup
-       # /sbin/swapoff -a
-       # rmdir /cgroup/test
-       # kill malloc task.
-
-       Of course, tmpfs v.s. swapoff test should be tested, too.
-
- 9.8 OOM-Killer
-       Out-of-memory caused by memcg's limit will kill tasks under
-       the memcg. When hierarchy is used, a task under hierarchy
-       will be killed by the kernel.
-       In this case, panic_on_oom shouldn't be invoked and tasks
-       in other groups shouldn't be killed.
-
-       It's not difficult to cause OOM under memcg as following.
-       Case A) when you can swapoff
-       #swapoff -a
-       #echo 50M > /memory.limit_in_bytes
-       run 51M of malloc
-
-       Case B) when you use mem+swap limitation.
-       #echo 50M > memory.limit_in_bytes
-       #echo 50M > memory.memsw.limit_in_bytes
-       run 51M of malloc
-
- 9.9 Move charges at task migration
-       Charges associated with a task can be moved along with task migration.
-
-       (Shell-A)
-       #mkdir /cgroup/A
-       #echo $$ >/cgroup/A/tasks
-       run some programs which uses some amount of memory in /cgroup/A.
-
-       (Shell-B)
-       #mkdir /cgroup/B
-       #echo 1 >/cgroup/B/memory.move_charge_at_immigrate
-       #echo "pid of the program running in group A" >/cgroup/B/tasks
-
-       You can see charges have been moved by reading *.usage_in_bytes or
-       memory.stat of both A and B.
-       See 8.2 of Documentation/cgroups/memory.txt to see what value should be
-       written to move_charge_at_immigrate.
-
- 9.10 Memory thresholds
-       Memory controller implements memory thresholds using cgroups notification
-       API. You can use tools/cgroup/cgroup_event_listener.c to test it.
-
-       (Shell-A) Create cgroup and run event listener
-       # mkdir /cgroup/A
-       # ./cgroup_event_listener /cgroup/A/memory.usage_in_bytes 5M
-
-       (Shell-B) Add task to cgroup and try to allocate and free memory
-       # echo $$ >/cgroup/A/tasks
-       # a="$(dd if=/dev/zero bs=1M count=10)"
-       # a=
-
-       You will see message from cgroup_event_listener every time you cross
-       the thresholds.
-
-       Use /cgroup/A/memory.memsw.usage_in_bytes to test memsw thresholds.
-
-       It's good idea to test root cgroup as well.
diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt
deleted file mode 100644 (file)
index ff71e16..0000000
+++ /dev/null
@@ -1,876 +0,0 @@
-Memory Resource Controller
-
-NOTE: This document is hopelessly outdated and it asks for a complete
-      rewrite. It still contains a useful information so we are keeping it
-      here but make sure to check the current code if you need a deeper
-      understanding.
-
-NOTE: The Memory Resource Controller has generically been referred to as the
-      memory controller in this document. Do not confuse memory controller
-      used here with the memory controller that is used in hardware.
-
-(For editors)
-In this document:
-      When we mention a cgroup (cgroupfs's directory) with memory controller,
-      we call it "memory cgroup". When you see git-log and source code, you'll
-      see patch's title and function names tend to use "memcg".
-      In this document, we avoid using it.
-
-Benefits and Purpose of the memory controller
-
-The memory controller isolates the memory behaviour of a group of tasks
-from the rest of the system. The article on LWN [12] mentions some probable
-uses of the memory controller. The memory controller can be used to
-
-a. Isolate an application or a group of applications
-   Memory-hungry applications can be isolated and limited to a smaller
-   amount of memory.
-b. Create a cgroup with a limited amount of memory; this can be used
-   as a good alternative to booting with mem=XXXX.
-c. Virtualization solutions can control the amount of memory they want
-   to assign to a virtual machine instance.
-d. A CD/DVD burner could control the amount of memory used by the
-   rest of the system to ensure that burning does not fail due to lack
-   of available memory.
-e. There are several other use cases; find one or use the controller just
-   for fun (to learn and hack on the VM subsystem).
-
-Current Status: linux-2.6.34-mmotm(development version of 2010/April)
-
-Features:
- - accounting anonymous pages, file caches, swap caches usage and limiting them.
- - pages are linked to per-memcg LRU exclusively, and there is no global LRU.
- - optionally, memory+swap usage can be accounted and limited.
- - hierarchical accounting
- - soft limit
- - moving (recharging) account at moving a task is selectable.
- - usage threshold notifier
- - memory pressure notifier
- - oom-killer disable knob and oom-notifier
- - Root cgroup has no limit controls.
-
- Kernel memory support is a work in progress, and the current version provides
- basically functionality. (See Section 2.7)
-
-Brief summary of control files.
-
- tasks                          # attach a task(thread) and show list of threads
- cgroup.procs                   # show list of processes
- cgroup.event_control           # an interface for event_fd()
- memory.usage_in_bytes          # show current usage for memory
-                                (See 5.5 for details)
- memory.memsw.usage_in_bytes    # show current usage for memory+Swap
-                                (See 5.5 for details)
- memory.limit_in_bytes          # set/show limit of memory usage
- memory.memsw.limit_in_bytes    # set/show limit of memory+Swap usage
- memory.failcnt                         # show the number of memory usage hits limits
- memory.memsw.failcnt           # show the number of memory+Swap hits limits
- memory.max_usage_in_bytes      # show max memory usage recorded
- memory.memsw.max_usage_in_bytes # show max memory+Swap usage recorded
- memory.soft_limit_in_bytes     # set/show soft limit of memory usage
- memory.stat                    # show various statistics
- memory.use_hierarchy           # set/show hierarchical account enabled
- memory.force_empty             # trigger forced move charge to parent
- memory.pressure_level          # set memory pressure notifications
- memory.swappiness              # set/show swappiness parameter of vmscan
-                                (See sysctl's vm.swappiness)
- memory.move_charge_at_immigrate # set/show controls of moving charges
- memory.oom_control             # set/show oom controls.
- memory.numa_stat               # show the number of memory usage per numa node
-
- memory.kmem.limit_in_bytes      # set/show hard limit for kernel memory
- memory.kmem.usage_in_bytes      # show current kernel memory allocation
- memory.kmem.failcnt             # show the number of kernel memory usage hits limits
- memory.kmem.max_usage_in_bytes  # show max kernel memory usage recorded
-
- memory.kmem.tcp.limit_in_bytes  # set/show hard limit for tcp buf memory
- memory.kmem.tcp.usage_in_bytes  # show current tcp buf memory allocation
- memory.kmem.tcp.failcnt            # show the number of tcp buf memory usage hits limits
- memory.kmem.tcp.max_usage_in_bytes # show max tcp buf memory usage recorded
-
-1. History
-
-The memory controller has a long history. A request for comments for the memory
-controller was posted by Balbir Singh [1]. At the time the RFC was posted
-there were several implementations for memory control. The goal of the
-RFC was to build consensus and agreement for the minimal features required
-for memory control. The first RSS controller was posted by Balbir Singh[2]
-in Feb 2007. Pavel Emelianov [3][4][5] has since posted three versions of the
-RSS controller. At OLS, at the resource management BoF, everyone suggested
-that we handle both page cache and RSS together. Another request was raised
-to allow user space handling of OOM. The current memory controller is
-at version 6; it combines both mapped (RSS) and unmapped Page
-Cache Control [11].
-
-2. Memory Control
-
-Memory is a unique resource in the sense that it is present in a limited
-amount. If a task requires a lot of CPU processing, the task can spread
-its processing over a period of hours, days, months or years, but with
-memory, the same physical memory needs to be reused to accomplish the task.
-
-The memory controller implementation has been divided into phases. These
-are:
-
-1. Memory controller
-2. mlock(2) controller
-3. Kernel user memory accounting and slab control
-4. user mappings length controller
-
-The memory controller is the first controller developed.
-
-2.1. Design
-
-The core of the design is a counter called the page_counter. The
-page_counter tracks the current memory usage and limit of the group of
-processes associated with the controller. Each cgroup has a memory controller
-specific data structure (mem_cgroup) associated with it.
-
-2.2. Accounting
-
-               +--------------------+
-               |  mem_cgroup        |
-               |  (page_counter)    |
-               +--------------------+
-                /            ^      \
-               /             |       \
-           +---------------+  |        +---------------+
-           | mm_struct     |  |....    | mm_struct     |
-           |               |  |        |               |
-           +---------------+  |        +---------------+
-                              |
-                              + --------------+
-                                              |
-           +---------------+           +------+--------+
-           | page          +---------->  page_cgroup|
-           |               |           |               |
-           +---------------+           +---------------+
-
-             (Figure 1: Hierarchy of Accounting)
-
-
-Figure 1 shows the important aspects of the controller
-
-1. Accounting happens per cgroup
-2. Each mm_struct knows about which cgroup it belongs to
-3. Each page has a pointer to the page_cgroup, which in turn knows the
-   cgroup it belongs to
-
-The accounting is done as follows: mem_cgroup_charge_common() is invoked to
-set up the necessary data structures and check if the cgroup that is being
-charged is over its limit. If it is, then reclaim is invoked on the cgroup.
-More details can be found in the reclaim section of this document.
-If everything goes well, a page meta-data-structure called page_cgroup is
-updated. page_cgroup has its own LRU on cgroup.
-(*) page_cgroup structure is allocated at boot/memory-hotplug time.
-
-2.2.1 Accounting details
-
-All mapped anon pages (RSS) and cache pages (Page Cache) are accounted.
-Some pages which are never reclaimable and will not be on the LRU
-are not accounted. We just account pages under usual VM management.
-
-RSS pages are accounted at page_fault unless they've already been accounted
-for earlier. A file page will be accounted for as Page Cache when it's
-inserted into inode (radix-tree). While it's mapped into the page tables of
-processes, duplicate accounting is carefully avoided.
-
-An RSS page is unaccounted when it's fully unmapped. A PageCache page is
-unaccounted when it's removed from radix-tree. Even if RSS pages are fully
-unmapped (by kswapd), they may exist as SwapCache in the system until they
-are really freed. Such SwapCaches are also accounted.
-A swapped-in page is not accounted until it's mapped.
-
-Note: The kernel does swapin-readahead and reads multiple swaps at once.
-This means swapped-in pages may contain pages for other tasks than a task
-causing page fault. So, we avoid accounting at swap-in I/O.
-
-At page migration, accounting information is kept.
-
-Note: we just account pages-on-LRU because our purpose is to control amount
-of used pages; not-on-LRU pages tend to be out-of-control from VM view.
-
-2.3 Shared Page Accounting
-
-Shared pages are accounted on the basis of the first touch approach. The
-cgroup that first touches a page is accounted for the page. The principle
-behind this approach is that a cgroup that aggressively uses a shared
-page will eventually get charged for it (once it is uncharged from
-the cgroup that brought it in -- this will happen on memory pressure).
-
-But see section 8.2: when moving a task to another cgroup, its pages may
-be recharged to the new cgroup, if move_charge_at_immigrate has been chosen.
-
-Exception: If CONFIG_MEMCG_SWAP is not used.
-When you do swapoff and make swapped-out pages of shmem(tmpfs) to
-be backed into memory in force, charges for pages are accounted against the
-caller of swapoff rather than the users of shmem.
-
-2.4 Swap Extension (CONFIG_MEMCG_SWAP)
-
-Swap Extension allows you to record charge for swap. A swapped-in page is
-charged back to original page allocator if possible.
-
-When swap is accounted, following files are added.
- - memory.memsw.usage_in_bytes.
- - memory.memsw.limit_in_bytes.
-
-memsw means memory+swap. Usage of memory+swap is limited by
-memsw.limit_in_bytes.
-
-Example: Assume a system with 4G of swap. A task which allocates 6G of memory
-(by mistake) under 2G memory limitation will use all swap.
-In this case, setting memsw.limit_in_bytes=3G will prevent bad use of swap.
-By using the memsw limit, you can avoid system OOM which can be caused by swap
-shortage.
-
-* why 'memory+swap' rather than swap.
-The global LRU(kswapd) can swap out arbitrary pages. Swap-out means
-to move account from memory to swap...there is no change in usage of
-memory+swap. In other words, when we want to limit the usage of swap without
-affecting global LRU, memory+swap limit is better than just limiting swap from
-an OS point of view.
-
-* What happens when a cgroup hits memory.memsw.limit_in_bytes
-When a cgroup hits memory.memsw.limit_in_bytes, it's useless to do swap-out
-in this cgroup. Then, swap-out will not be done by cgroup routine and file
-caches are dropped. But as mentioned above, global LRU can do swapout memory
-from it for sanity of the system's memory management state. You can't forbid
-it by cgroup.
-
-2.5 Reclaim
-
-Each cgroup maintains a per cgroup LRU which has the same structure as
-global VM. When a cgroup goes over its limit, we first try
-to reclaim memory from the cgroup so as to make space for the new
-pages that the cgroup has touched. If the reclaim is unsuccessful,
-an OOM routine is invoked to select and kill the bulkiest task in the
-cgroup. (See 10. OOM Control below.)
-
-The reclaim algorithm has not been modified for cgroups, except that
-pages that are selected for reclaiming come from the per-cgroup LRU
-list.
-
-NOTE: Reclaim does not work for the root cgroup, since we cannot set any
-limits on the root cgroup.
-
-Note2: When panic_on_oom is set to "2", the whole system will panic.
-
-When oom event notifier is registered, event will be delivered.
-(See oom_control section)
-
-2.6 Locking
-
-   lock_page_cgroup()/unlock_page_cgroup() should not be called under
-   mapping->tree_lock.
-
-   Other lock order is following:
-   PG_locked.
-   mm->page_table_lock
-       zone->lru_lock
-         lock_page_cgroup.
-  In many cases, just lock_page_cgroup() is called.
-  per-zone-per-cgroup LRU (cgroup's private LRU) is just guarded by
-  zone->lru_lock, it has no lock of its own.
-
-2.7 Kernel Memory Extension (CONFIG_MEMCG_KMEM)
-
-With the Kernel memory extension, the Memory Controller is able to limit
-the amount of kernel memory used by the system. Kernel memory is fundamentally
-different than user memory, since it can't be swapped out, which makes it
-possible to DoS the system by consuming too much of this precious resource.
-
-Kernel memory won't be accounted at all until limit on a group is set. This
-allows for existing setups to continue working without disruption.  The limit
-cannot be set if the cgroup have children, or if there are already tasks in the
-cgroup. Attempting to set the limit under those conditions will return -EBUSY.
-When use_hierarchy == 1 and a group is accounted, its children will
-automatically be accounted regardless of their limit value.
-
-After a group is first limited, it will be kept being accounted until it
-is removed. The memory limitation itself, can of course be removed by writing
--1 to memory.kmem.limit_in_bytes. In this case, kmem will be accounted, but not
-limited.
-
-Kernel memory limits are not imposed for the root cgroup. Usage for the root
-cgroup may or may not be accounted. The memory used is accumulated into
-memory.kmem.usage_in_bytes, or in a separate counter when it makes sense.
-(currently only for tcp).
-The main "kmem" counter is fed into the main counter, so kmem charges will
-also be visible from the user counter.
-
-Currently no soft limit is implemented for kernel memory. It is future work
-to trigger slab reclaim when those limits are reached.
-
-2.7.1 Current Kernel Memory resources accounted
-
-* stack pages: every process consumes some stack pages. By accounting into
-kernel memory, we prevent new processes from being created when the kernel
-memory usage is too high.
-
-* slab pages: pages allocated by the SLAB or SLUB allocator are tracked. A copy
-of each kmem_cache is created every time the cache is touched by the first time
-from inside the memcg. The creation is done lazily, so some objects can still be
-skipped while the cache is being created. All objects in a slab page should
-belong to the same memcg. This only fails to hold when a task is migrated to a
-different memcg during the page allocation by the cache.
-
-* sockets memory pressure: some sockets protocols have memory pressure
-thresholds. The Memory Controller allows them to be controlled individually
-per cgroup, instead of globally.
-
-* tcp memory pressure: sockets memory pressure for the tcp protocol.
-
-2.7.2 Common use cases
-
-Because the "kmem" counter is fed to the main user counter, kernel memory can
-never be limited completely independently of user memory. Say "U" is the user
-limit, and "K" the kernel limit. There are three possible ways limits can be
-set:
-
-    U != 0, K = unlimited:
-    This is the standard memcg limitation mechanism already present before kmem
-    accounting. Kernel memory is completely ignored.
-
-    U != 0, K < U:
-    Kernel memory is a subset of the user memory. This setup is useful in
-    deployments where the total amount of memory per-cgroup is overcommited.
-    Overcommiting kernel memory limits is definitely not recommended, since the
-    box can still run out of non-reclaimable memory.
-    In this case, the admin could set up K so that the sum of all groups is
-    never greater than the total memory, and freely set U at the cost of his
-    QoS.
-    WARNING: In the current implementation, memory reclaim will NOT be
-    triggered for a cgroup when it hits K while staying below U, which makes
-    this setup impractical.
-
-    U != 0, K >= U:
-    Since kmem charges will also be fed to the user counter and reclaim will be
-    triggered for the cgroup for both kinds of memory. This setup gives the
-    admin a unified view of memory, and it is also useful for people who just
-    want to track kernel memory usage.
-
-3. User Interface
-
-3.0. Configuration
-
-a. Enable CONFIG_CGROUPS
-b. Enable CONFIG_MEMCG
-c. Enable CONFIG_MEMCG_SWAP (to use swap extension)
-d. Enable CONFIG_MEMCG_KMEM (to use kmem extension)
-
-3.1. Prepare the cgroups (see cgroups.txt, Why are cgroups needed?)
-# mount -t tmpfs none /sys/fs/cgroup
-# mkdir /sys/fs/cgroup/memory
-# mount -t cgroup none /sys/fs/cgroup/memory -o memory
-
-3.2. Make the new group and move bash into it
-# mkdir /sys/fs/cgroup/memory/0
-# echo $$ > /sys/fs/cgroup/memory/0/tasks
-
-Since now we're in the 0 cgroup, we can alter the memory limit:
-# echo 4M > /sys/fs/cgroup/memory/0/memory.limit_in_bytes
-
-NOTE: We can use a suffix (k, K, m, M, g or G) to indicate values in kilo,
-mega or gigabytes. (Here, Kilo, Mega, Giga are Kibibytes, Mebibytes, Gibibytes.)
-
-NOTE: We can write "-1" to reset the *.limit_in_bytes(unlimited).
-NOTE: We cannot set limits on the root cgroup any more.
-
-# cat /sys/fs/cgroup/memory/0/memory.limit_in_bytes
-4194304
-
-We can check the usage:
-# cat /sys/fs/cgroup/memory/0/memory.usage_in_bytes
-1216512
-
-A successful write to this file does not guarantee a successful setting of
-this limit to the value written into the file. This can be due to a
-number of factors, such as rounding up to page boundaries or the total
-availability of memory on the system. The user is required to re-read
-this file after a write to guarantee the value committed by the kernel.
-
-# echo 1 > memory.limit_in_bytes
-# cat memory.limit_in_bytes
-4096
-
-The memory.failcnt field gives the number of times that the cgroup limit was
-exceeded.
-
-The memory.stat file gives accounting information. Now, the number of
-caches, RSS and Active pages/Inactive pages are shown.
-
-4. Testing
-
-For testing features and implementation, see memcg_test.txt.
-
-Performance test is also important. To see pure memory controller's overhead,
-testing on tmpfs will give you good numbers of small overheads.
-Example: do kernel make on tmpfs.
-
-Page-fault scalability is also important. At measuring parallel
-page fault test, multi-process test may be better than multi-thread
-test because it has noise of shared objects/status.
-
-But the above two are testing extreme situations.
-Trying usual test under memory controller is always helpful.
-
-4.1 Troubleshooting
-
-Sometimes a user might find that the application under a cgroup is
-terminated by the OOM killer. There are several causes for this:
-
-1. The cgroup limit is too low (just too low to do anything useful)
-2. The user is using anonymous memory and swap is turned off or too low
-
-A sync followed by echo 1 > /proc/sys/vm/drop_caches will help get rid of
-some of the pages cached in the cgroup (page cache pages).
-
-To know what happens, disabling OOM_Kill as per "10. OOM Control" (below) and
-seeing what happens will be helpful.
-
-4.2 Task migration
-
-When a task migrates from one cgroup to another, its charge is not
-carried forward by default. The pages allocated from the original cgroup still
-remain charged to it, the charge is dropped when the page is freed or
-reclaimed.
-
-You can move charges of a task along with task migration.
-See 8. "Move charges at task migration"
-
-4.3 Removing a cgroup
-
-A cgroup can be removed by rmdir, but as discussed in sections 4.1 and 4.2, a
-cgroup might have some charge associated with it, even though all
-tasks have migrated away from it. (because we charge against pages, not
-against tasks.)
-
-We move the stats to root (if use_hierarchy==0) or parent (if
-use_hierarchy==1), and no change on the charge except uncharging
-from the child.
-
-Charges recorded in swap information is not updated at removal of cgroup.
-Recorded information is discarded and a cgroup which uses swap (swapcache)
-will be charged as a new owner of it.
-
-About use_hierarchy, see Section 6.
-
-5. Misc. interfaces.
-
-5.1 force_empty
-  memory.force_empty interface is provided to make cgroup's memory usage empty.
-  When writing anything to this
-
-  # echo 0 > memory.force_empty
-
-  the cgroup will be reclaimed and as many pages reclaimed as possible.
-
-  The typical use case for this interface is before calling rmdir().
-  Because rmdir() moves all pages to parent, some out-of-use page caches can be
-  moved to the parent. If you want to avoid that, force_empty will be useful.
-
-  Also, note that when memory.kmem.limit_in_bytes is set the charges due to
-  kernel pages will still be seen. This is not considered a failure and the
-  write will still return success. In this case, it is expected that
-  memory.kmem.usage_in_bytes == memory.usage_in_bytes.
-
-  About use_hierarchy, see Section 6.
-
-5.2 stat file
-
-memory.stat file includes following statistics
-
-# per-memory cgroup local status
-cache          - # of bytes of page cache memory.
-rss            - # of bytes of anonymous and swap cache memory (includes
-               transparent hugepages).
-rss_huge       - # of bytes of anonymous transparent hugepages.
-mapped_file    - # of bytes of mapped file (includes tmpfs/shmem)
-pgpgin         - # of charging events to the memory cgroup. The charging
-               event happens each time a page is accounted as either mapped
-               anon page(RSS) or cache page(Page Cache) to the cgroup.
-pgpgout                - # of uncharging events to the memory cgroup. The uncharging
-               event happens each time a page is unaccounted from the cgroup.
-swap           - # of bytes of swap usage
-dirty          - # of bytes that are waiting to get written back to the disk.
-writeback      - # of bytes of file/anon cache that are queued for syncing to
-               disk.
-inactive_anon  - # of bytes of anonymous and swap cache memory on inactive
-               LRU list.
-active_anon    - # of bytes of anonymous and swap cache memory on active
-               LRU list.
-inactive_file  - # of bytes of file-backed memory on inactive LRU list.
-active_file    - # of bytes of file-backed memory on active LRU list.
-unevictable    - # of bytes of memory that cannot be reclaimed (mlocked etc).
-
-# status considering hierarchy (see memory.use_hierarchy settings)
-
-hierarchical_memory_limit - # of bytes of memory limit with regard to hierarchy
-                       under which the memory cgroup is
-hierarchical_memsw_limit - # of bytes of memory+swap limit with regard to
-                       hierarchy under which memory cgroup is.
-
-total_<counter>                - # hierarchical version of <counter>, which in
-                       addition to the cgroup's own value includes the
-                       sum of all hierarchical children's values of
-                       <counter>, i.e. total_cache
-
-# The following additional stats are dependent on CONFIG_DEBUG_VM.
-
-recent_rotated_anon    - VM internal parameter. (see mm/vmscan.c)
-recent_rotated_file    - VM internal parameter. (see mm/vmscan.c)
-recent_scanned_anon    - VM internal parameter. (see mm/vmscan.c)
-recent_scanned_file    - VM internal parameter. (see mm/vmscan.c)
-
-Memo:
-       recent_rotated means recent frequency of LRU rotation.
-       recent_scanned means recent # of scans to LRU.
-       showing for better debug please see the code for meanings.
-
-Note:
-       Only anonymous and swap cache memory is listed as part of 'rss' stat.
-       This should not be confused with the true 'resident set size' or the
-       amount of physical memory used by the cgroup.
-       'rss + file_mapped" will give you resident set size of cgroup.
-       (Note: file and shmem may be shared among other cgroups. In that case,
-        file_mapped is accounted only when the memory cgroup is owner of page
-        cache.)
-
-5.3 swappiness
-
-Overrides /proc/sys/vm/swappiness for the particular group. The tunable
-in the root cgroup corresponds to the global swappiness setting.
-
-Please note that unlike during the global reclaim, limit reclaim
-enforces that 0 swappiness really prevents from any swapping even if
-there is a swap storage available. This might lead to memcg OOM killer
-if there are no file pages to reclaim.
-
-5.4 failcnt
-
-A memory cgroup provides memory.failcnt and memory.memsw.failcnt files.
-This failcnt(== failure count) shows the number of times that a usage counter
-hit its limit. When a memory cgroup hits a limit, failcnt increases and
-memory under it will be reclaimed.
-
-You can reset failcnt by writing 0 to failcnt file.
-# echo 0 > .../memory.failcnt
-
-5.5 usage_in_bytes
-
-For efficiency, as other kernel components, memory cgroup uses some optimization
-to avoid unnecessary cacheline false sharing. usage_in_bytes is affected by the
-method and doesn't show 'exact' value of memory (and swap) usage, it's a fuzz
-value for efficient access. (Of course, when necessary, it's synchronized.)
-If you want to know more exact memory usage, you should use RSS+CACHE(+SWAP)
-value in memory.stat(see 5.2).
-
-5.6 numa_stat
-
-This is similar to numa_maps but operates on a per-memcg basis.  This is
-useful for providing visibility into the numa locality information within
-an memcg since the pages are allowed to be allocated from any physical
-node.  One of the use cases is evaluating application performance by
-combining this information with the application's CPU allocation.
-
-Each memcg's numa_stat file includes "total", "file", "anon" and "unevictable"
-per-node page counts including "hierarchical_<counter>" which sums up all
-hierarchical children's values in addition to the memcg's own value.
-
-The output format of memory.numa_stat is:
-
-total=<total pages> N0=<node 0 pages> N1=<node 1 pages> ...
-file=<total file pages> N0=<node 0 pages> N1=<node 1 pages> ...
-anon=<total anon pages> N0=<node 0 pages> N1=<node 1 pages> ...
-unevictable=<total anon pages> N0=<node 0 pages> N1=<node 1 pages> ...
-hierarchical_<counter>=<counter pages> N0=<node 0 pages> N1=<node 1 pages> ...
-
-The "total" count is sum of file + anon + unevictable.
-
-6. Hierarchy support
-
-The memory controller supports a deep hierarchy and hierarchical accounting.
-The hierarchy is created by creating the appropriate cgroups in the
-cgroup filesystem. Consider for example, the following cgroup filesystem
-hierarchy
-
-              root
-            /  |   \
-            /  |    \
-          a    b     c
-                     | \
-                     |  \
-                     d   e
-
-In the diagram above, with hierarchical accounting enabled, all memory
-usage of e, is accounted to its ancestors up until the root (i.e, c and root),
-that has memory.use_hierarchy enabled. If one of the ancestors goes over its
-limit, the reclaim algorithm reclaims from the tasks in the ancestor and the
-children of the ancestor.
-
-6.1 Enabling hierarchical accounting and reclaim
-
-A memory cgroup by default disables the hierarchy feature. Support
-can be enabled by writing 1 to memory.use_hierarchy file of the root cgroup
-
-# echo 1 > memory.use_hierarchy
-
-The feature can be disabled by
-
-# echo 0 > memory.use_hierarchy
-
-NOTE1: Enabling/disabling will fail if either the cgroup already has other
-       cgroups created below it, or if the parent cgroup has use_hierarchy
-       enabled.
-
-NOTE2: When panic_on_oom is set to "2", the whole system will panic in
-       case of an OOM event in any cgroup.
-
-7. Soft limits
-
-Soft limits allow for greater sharing of memory. The idea behind soft limits
-is to allow control groups to use as much of the memory as needed, provided
-
-a. There is no memory contention
-b. They do not exceed their hard limit
-
-When the system detects memory contention or low memory, control groups
-are pushed back to their soft limits. If the soft limit of each control
-group is very high, they are pushed back as much as possible to make
-sure that one control group does not starve the others of memory.
-
-Please note that soft limits is a best-effort feature; it comes with
-no guarantees, but it does its best to make sure that when memory is
-heavily contended for, memory is allocated based on the soft limit
-hints/setup. Currently soft limit based reclaim is set up such that
-it gets invoked from balance_pgdat (kswapd).
-
-7.1 Interface
-
-Soft limits can be setup by using the following commands (in this example we
-assume a soft limit of 256 MiB)
-
-# echo 256M > memory.soft_limit_in_bytes
-
-If we want to change this to 1G, we can at any time use
-
-# echo 1G > memory.soft_limit_in_bytes
-
-NOTE1: Soft limits take effect over a long period of time, since they involve
-       reclaiming memory for balancing between memory cgroups
-NOTE2: It is recommended to set the soft limit always below the hard limit,
-       otherwise the hard limit will take precedence.
-
-8. Move charges at task migration
-
-Users can move charges associated with a task along with task migration, that
-is, uncharge task's pages from the old cgroup and charge them to the new cgroup.
-This feature is not supported in !CONFIG_MMU environments because of lack of
-page tables.
-
-8.1 Interface
-
-This feature is disabled by default. It can be enabled (and disabled again) by
-writing to memory.move_charge_at_immigrate of the destination cgroup.
-
-If you want to enable it:
-
-# echo (some positive value) > memory.move_charge_at_immigrate
-
-Note: Each bits of move_charge_at_immigrate has its own meaning about what type
-      of charges should be moved. See 8.2 for details.
-Note: Charges are moved only when you move mm->owner, in other words,
-      a leader of a thread group.
-Note: If we cannot find enough space for the task in the destination cgroup, we
-      try to make space by reclaiming memory. Task migration may fail if we
-      cannot make enough space.
-Note: It can take several seconds if you move charges much.
-
-And if you want disable it again:
-
-# echo 0 > memory.move_charge_at_immigrate
-
-8.2 Type of charges which can be moved
-
-Each bit in move_charge_at_immigrate has its own meaning about what type of
-charges should be moved. But in any case, it must be noted that an account of
-a page or a swap can be moved only when it is charged to the task's current
-(old) memory cgroup.
-
-  bit | what type of charges would be moved ?
- -----+------------------------------------------------------------------------
-   0  | A charge of an anonymous page (or swap of it) used by the target task.
-      | You must enable Swap Extension (see 2.4) to enable move of swap charges.
- -----+------------------------------------------------------------------------
-   1  | A charge of file pages (normal file, tmpfs file (e.g. ipc shared memory)
-      | and swaps of tmpfs file) mmapped by the target task. Unlike the case of
-      | anonymous pages, file pages (and swaps) in the range mmapped by the task
-      | will be moved even if the task hasn't done page fault, i.e. they might
-      | not be the task's "RSS", but other task's "RSS" that maps the same file.
-      | And mapcount of the page is ignored (the page can be moved even if
-      | page_mapcount(page) > 1). You must enable Swap Extension (see 2.4) to
-      | enable move of swap charges.
-
-8.3 TODO
-
-- All of moving charge operations are done under cgroup_mutex. It's not good
-  behavior to hold the mutex too long, so we may need some trick.
-
-9. Memory thresholds
-
-Memory cgroup implements memory thresholds using the cgroups notification
-API (see cgroups.txt). It allows to register multiple memory and memsw
-thresholds and gets notifications when it crosses.
-
-To register a threshold, an application must:
-- create an eventfd using eventfd(2);
-- open memory.usage_in_bytes or memory.memsw.usage_in_bytes;
-- write string like "<event_fd> <fd of memory.usage_in_bytes> <threshold>" to
-  cgroup.event_control.
-
-Application will be notified through eventfd when memory usage crosses
-threshold in any direction.
-
-It's applicable for root and non-root cgroup.
-
-10. OOM Control
-
-memory.oom_control file is for OOM notification and other controls.
-
-Memory cgroup implements OOM notifier using the cgroup notification
-API (See cgroups.txt). It allows to register multiple OOM notification
-delivery and gets notification when OOM happens.
-
-To register a notifier, an application must:
- - create an eventfd using eventfd(2)
- - open memory.oom_control file
- - write string like "<event_fd> <fd of memory.oom_control>" to
-   cgroup.event_control
-
-The application will be notified through eventfd when OOM happens.
-OOM notification doesn't work for the root cgroup.
-
-You can disable the OOM-killer by writing "1" to memory.oom_control file, as:
-
-       #echo 1 > memory.oom_control
-
-If OOM-killer is disabled, tasks under cgroup will hang/sleep
-in memory cgroup's OOM-waitqueue when they request accountable memory.
-
-For running them, you have to relax the memory cgroup's OOM status by
-       * enlarge limit or reduce usage.
-To reduce usage,
-       * kill some tasks.
-       * move some tasks to other group with account migration.
-       * remove some files (on tmpfs?)
-
-Then, stopped tasks will work again.
-
-At reading, current status of OOM is shown.
-       oom_kill_disable 0 or 1 (if 1, oom-killer is disabled)
-       under_oom        0 or 1 (if 1, the memory cgroup is under OOM, tasks may
-                                be stopped.)
-
-11. Memory Pressure
-
-The pressure level notifications can be used to monitor the memory
-allocation cost; based on the pressure, applications can implement
-different strategies of managing their memory resources. The pressure
-levels are defined as following:
-
-The "low" level means that the system is reclaiming memory for new
-allocations. Monitoring this reclaiming activity might be useful for
-maintaining cache level. Upon notification, the program (typically
-"Activity Manager") might analyze vmstat and act in advance (i.e.
-prematurely shutdown unimportant services).
-
-The "medium" level means that the system is experiencing medium memory
-pressure, the system might be making swap, paging out active file caches,
-etc. Upon this event applications may decide to further analyze
-vmstat/zoneinfo/memcg or internal memory usage statistics and free any
-resources that can be easily reconstructed or re-read from a disk.
-
-The "critical" level means that the system is actively thrashing, it is
-about to out of memory (OOM) or even the in-kernel OOM killer is on its
-way to trigger. Applications should do whatever they can to help the
-system. It might be too late to consult with vmstat or any other
-statistics, so it's advisable to take an immediate action.
-
-The events are propagated upward until the event is handled, i.e. the
-events are not pass-through. Here is what this means: for example you have
-three cgroups: A->B->C. Now you set up an event listener on cgroups A, B
-and C, and suppose group C experiences some pressure. In this situation,
-only group C will receive the notification, i.e. groups A and B will not
-receive it. This is done to avoid excessive "broadcasting" of messages,
-which disturbs the system and which is especially bad if we are low on
-memory or thrashing. So, organize the cgroups wisely, or propagate the
-events manually (or, ask us to implement the pass-through events,
-explaining why would you need them.)
-
-The file memory.pressure_level is only used to setup an eventfd. To
-register a notification, an application must:
-
-- create an eventfd using eventfd(2);
-- open memory.pressure_level;
-- write string like "<event_fd> <fd of memory.pressure_level> <level>"
-  to cgroup.event_control.
-
-Application will be notified through eventfd when memory pressure is at
-the specific level (or higher). Read/write operations to
-memory.pressure_level are no implemented.
-
-Test:
-
-   Here is a small script example that makes a new cgroup, sets up a
-   memory limit, sets up a notification in the cgroup and then makes child
-   cgroup experience a critical pressure:
-
-   # cd /sys/fs/cgroup/memory/
-   # mkdir foo
-   # cd foo
-   # cgroup_event_listener memory.pressure_level low &
-   # echo 8000000 > memory.limit_in_bytes
-   # echo 8000000 > memory.memsw.limit_in_bytes
-   # echo $$ > tasks
-   # dd if=/dev/zero | read x
-
-   (Expect a bunch of notifications, and eventually, the oom-killer will
-   trigger.)
-
-12. TODO
-
-1. Make per-cgroup scanner reclaim not-shared pages first
-2. Teach controller to account for shared-pages
-3. Start reclamation in the background when the limit is
-   not yet hit but the usage is getting closer
-
-Summary
-
-Overall, the memory controller has been a stable controller and has been
-commented and discussed quite extensively in the community.
-
-References
-
-1. Singh, Balbir. RFC: Memory Controller, http://lwn.net/Articles/206697/
-2. Singh, Balbir. Memory Controller (RSS Control),
-   http://lwn.net/Articles/222762/
-3. Emelianov, Pavel. Resource controllers based on process cgroups
-   http://lkml.org/lkml/2007/3/6/198
-4. Emelianov, Pavel. RSS controller based on process cgroups (v2)
-   http://lkml.org/lkml/2007/4/9/78
-5. Emelianov, Pavel. RSS controller based on process cgroups (v3)
-   http://lkml.org/lkml/2007/5/30/244
-6. Menage, Paul. Control Groups v10, http://lwn.net/Articles/236032/
-7. Vaidyanathan, Srinivasan, Control Groups: Pagecache accounting and control
-   subsystem (v3), http://lwn.net/Articles/235534/
-8. Singh, Balbir. RSS controller v2 test results (lmbench),
-   http://lkml.org/lkml/2007/5/17/232
-9. Singh, Balbir. RSS controller v2 AIM9 results
-   http://lkml.org/lkml/2007/5/18/1
-10. Singh, Balbir. Memory controller v6 test results,
-    http://lkml.org/lkml/2007/8/19/36
-11. Singh, Balbir. Memory controller introduction (v6),
-    http://lkml.org/lkml/2007/8/17/69
-12. Corbet, Jonathan, Controlling memory use in cgroups,
-    http://lwn.net/Articles/243795/
diff --git a/Documentation/cgroups/net_cls.txt b/Documentation/cgroups/net_cls.txt
deleted file mode 100644 (file)
index ec18234..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-Network classifier cgroup
--------------------------
-
-The Network classifier cgroup provides an interface to
-tag network packets with a class identifier (classid).
-
-The Traffic Controller (tc) can be used to assign
-different priorities to packets from different cgroups.
-Also, Netfilter (iptables) can use this tag to perform
-actions on such packets.
-
-Creating a net_cls cgroups instance creates a net_cls.classid file.
-This net_cls.classid value is initialized to 0.
-
-You can write hexadecimal values to net_cls.classid; the format for these
-values is 0xAAAABBBB; AAAA is the major handle number and BBBB
-is the minor handle number.
-Reading net_cls.classid yields a decimal result.
-
-Example:
-mkdir /sys/fs/cgroup/net_cls
-mount -t cgroup -onet_cls net_cls /sys/fs/cgroup/net_cls
-mkdir /sys/fs/cgroup/net_cls/0
-echo 0x100001 >  /sys/fs/cgroup/net_cls/0/net_cls.classid
-       - setting a 10:1 handle.
-
-cat /sys/fs/cgroup/net_cls/0/net_cls.classid
-1048577
-
-configuring tc:
-tc qdisc add dev eth0 root handle 10: htb
-
-tc class add dev eth0 parent 10: classid 10:1 htb rate 40mbit
- - creating traffic class 10:1
-
-tc filter add dev eth0 parent 10: protocol ip prio 10 handle 1: cgroup
-
-configuring iptables, basic example:
-iptables -A OUTPUT -m cgroup ! --cgroup 0x100001 -j DROP
diff --git a/Documentation/cgroups/net_prio.txt b/Documentation/cgroups/net_prio.txt
deleted file mode 100644 (file)
index a82cbd2..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-Network priority cgroup
--------------------------
-
-The Network priority cgroup provides an interface to allow an administrator to
-dynamically set the priority of network traffic generated by various
-applications
-
-Nominally, an application would set the priority of its traffic via the
-SO_PRIORITY socket option.  This however, is not always possible because:
-
-1) The application may not have been coded to set this value
-2) The priority of application traffic is often a site-specific administrative
-   decision rather than an application defined one.
-
-This cgroup allows an administrator to assign a process to a group which defines
-the priority of egress traffic on a given interface. Network priority groups can
-be created by first mounting the cgroup filesystem.
-
-# mount -t cgroup -onet_prio none /sys/fs/cgroup/net_prio
-
-With the above step, the initial group acting as the parent accounting group
-becomes visible at '/sys/fs/cgroup/net_prio'.  This group includes all tasks in
-the system. '/sys/fs/cgroup/net_prio/tasks' lists the tasks in this cgroup.
-
-Each net_prio cgroup contains two files that are subsystem specific
-
-net_prio.prioidx
-This file is read-only, and is simply informative.  It contains a unique integer
-value that the kernel uses as an internal representation of this cgroup.
-
-net_prio.ifpriomap
-This file contains a map of the priorities assigned to traffic originating from
-processes in this group and egressing the system on various interfaces. It
-contains a list of tuples in the form <ifname priority>.  Contents of this file
-can be modified by echoing a string into the file using the same tuple format.
-for example:
-
-echo "eth0 5" > /sys/fs/cgroups/net_prio/iscsi/net_prio.ifpriomap
-
-This command would force any traffic originating from processes belonging to the
-iscsi net_prio cgroup and egressing on interface eth0 to have the priority of
-said traffic set to the value 5. The parent accounting group also has a
-writeable 'net_prio.ifpriomap' file that can be used to set a system default
-priority.
-
-Priorities are set immediately prior to queueing a frame to the device
-queueing discipline (qdisc) so priorities will be assigned prior to the hardware
-queue selection being made.
-
-One usage for the net_prio cgroup is with mqprio qdisc allowing application
-traffic to be steered to hardware/driver based traffic classes. These mappings
-can then be managed by administrators or other networking protocols such as
-DCBX.
-
-A new net_prio cgroup inherits the parent's configuration.
diff --git a/Documentation/cgroups/pids.txt b/Documentation/cgroups/pids.txt
deleted file mode 100644 (file)
index 1a078b5..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-                                                  Process Number Controller
-                                                  =========================
-
-Abstract
---------
-
-The process number controller is used to allow a cgroup hierarchy to stop any
-new tasks from being fork()'d or clone()'d after a certain limit is reached.
-
-Since it is trivial to hit the task limit without hitting any kmemcg limits in
-place, PIDs are a fundamental resource. As such, PID exhaustion must be
-preventable in the scope of a cgroup hierarchy by allowing resource limiting of
-the number of tasks in a cgroup.
-
-Usage
------
-
-In order to use the `pids` controller, set the maximum number of tasks in
-pids.max (this is not available in the root cgroup for obvious reasons). The
-number of processes currently in the cgroup is given by pids.current.
-
-Organisational operations are not blocked by cgroup policies, so it is possible
-to have pids.current > pids.max. This can be done by either setting the limit to
-be smaller than pids.current, or attaching enough processes to the cgroup such
-that pids.current > pids.max. However, it is not possible to violate a cgroup
-policy through fork() or clone(). fork() and clone() will return -EAGAIN if the
-creation of a new process would cause a cgroup policy to be violated.
-
-To set a cgroup to have no limit, set pids.max to "max". This is the default for
-all new cgroups (N.B. that PID limits are hierarchical, so the most stringent
-limit in the hierarchy is followed).
-
-pids.current tracks all child cgroup hierarchies, so parent/pids.current is a
-superset of parent/child/pids.current.
-
-Example
--------
-
-First, we mount the pids controller:
-# mkdir -p /sys/fs/cgroup/pids
-# mount -t cgroup -o pids none /sys/fs/cgroup/pids
-
-Then we create a hierarchy, set limits and attach processes to it:
-# mkdir -p /sys/fs/cgroup/pids/parent/child
-# echo 2 > /sys/fs/cgroup/pids/parent/pids.max
-# echo $$ > /sys/fs/cgroup/pids/parent/cgroup.procs
-# cat /sys/fs/cgroup/pids/parent/pids.current
-2
-#
-
-It should be noted that attempts to overcome the set limit (2 in this case) will
-fail:
-
-# cat /sys/fs/cgroup/pids/parent/pids.current
-2
-# ( /bin/echo "Here's some processes for you." | cat )
-sh: fork: Resource temporary unavailable
-#
-
-Even if we migrate to a child cgroup (which doesn't have a set limit), we will
-not be able to overcome the most stringent limit in the hierarchy (in this case,
-parent's):
-
-# echo $$ > /sys/fs/cgroup/pids/parent/child/cgroup.procs
-# cat /sys/fs/cgroup/pids/parent/pids.current
-2
-# cat /sys/fs/cgroup/pids/parent/child/pids.current
-2
-# cat /sys/fs/cgroup/pids/parent/child/pids.max
-max
-# ( /bin/echo "Here's some processes for you." | cat )
-sh: fork: Resource temporary unavailable
-#
-
-We can set a limit that is smaller than pids.current, which will stop any new
-processes from being forked at all (note that the shell itself counts towards
-pids.current):
-
-# echo 1 > /sys/fs/cgroup/pids/parent/pids.max
-# /bin/echo "We can't even spawn a single process now."
-sh: fork: Resource temporary unavailable
-# echo 0 > /sys/fs/cgroup/pids/parent/pids.max
-# /bin/echo "We can't even spawn a single process now."
-sh: fork: Resource temporary unavailable
-#
diff --git a/Documentation/cgroups/unified-hierarchy.txt b/Documentation/cgroups/unified-hierarchy.txt
deleted file mode 100644 (file)
index 781b1d4..0000000
+++ /dev/null
@@ -1,647 +0,0 @@
-
-Cgroup unified hierarchy
-
-April, 2014            Tejun Heo <tj@kernel.org>
-
-This document describes the changes made by unified hierarchy and
-their rationales.  It will eventually be merged into the main cgroup
-documentation.
-
-CONTENTS
-
-1. Background
-2. Basic Operation
-  2-1. Mounting
-  2-2. cgroup.subtree_control
-  2-3. cgroup.controllers
-3. Structural Constraints
-  3-1. Top-down
-  3-2. No internal tasks
-4. Delegation
-  4-1. Model of delegation
-  4-2. Common ancestor rule
-5. Other Changes
-  5-1. [Un]populated Notification
-  5-2. Other Core Changes
-  5-3. Controller File Conventions
-    5-3-1. Format
-    5-3-2. Control Knobs
-  5-4. Per-Controller Changes
-    5-4-1. io
-    5-4-2. cpuset
-    5-4-3. memory
-6. Planned Changes
-  6-1. CAP for resource control
-
-
-1. Background
-
-cgroup allows an arbitrary number of hierarchies and each hierarchy
-can host any number of controllers.  While this seems to provide a
-high level of flexibility, it isn't quite useful in practice.
-
-For example, as there is only one instance of each controller, utility
-type controllers such as freezer which can be useful in all
-hierarchies can only be used in one.  The issue is exacerbated by the
-fact that controllers can't be moved around once hierarchies are
-populated.  Another issue is that all controllers bound to a hierarchy
-are forced to have exactly the same view of the hierarchy.  It isn't
-possible to vary the granularity depending on the specific controller.
-
-In practice, these issues heavily limit which controllers can be put
-on the same hierarchy and most configurations resort to putting each
-controller on its own hierarchy.  Only closely related ones, such as
-the cpu and cpuacct controllers, make sense to put on the same
-hierarchy.  This often means that userland ends up managing multiple
-similar hierarchies repeating the same steps on each hierarchy
-whenever a hierarchy management operation is necessary.
-
-Unfortunately, support for multiple hierarchies comes at a steep cost.
-Internal implementation in cgroup core proper is dazzlingly
-complicated but more importantly the support for multiple hierarchies
-restricts how cgroup is used in general and what controllers can do.
-
-There's no limit on how many hierarchies there may be, which means
-that a task's cgroup membership can't be described in finite length.
-The key may contain any varying number of entries and is unlimited in
-length, which makes it highly awkward to handle and leads to addition
-of controllers which exist only to identify membership, which in turn
-exacerbates the original problem.
-
-Also, as a controller can't have any expectation regarding what shape
-of hierarchies other controllers would be on, each controller has to
-assume that all other controllers are operating on completely
-orthogonal hierarchies.  This makes it impossible, or at least very
-cumbersome, for controllers to cooperate with each other.
-
-In most use cases, putting controllers on hierarchies which are
-completely orthogonal to each other isn't necessary.  What usually is
-called for is the ability to have differing levels of granularity
-depending on the specific controller.  In other words, hierarchy may
-be collapsed from leaf towards root when viewed from specific
-controllers.  For example, a given configuration might not care about
-how memory is distributed beyond a certain level while still wanting
-to control how CPU cycles are distributed.
-
-Unified hierarchy is the next version of cgroup interface.  It aims to
-address the aforementioned issues by having more structure while
-retaining enough flexibility for most use cases.  Various other
-general and controller-specific interface issues are also addressed in
-the process.
-
-
-2. Basic Operation
-
-2-1. Mounting
-
-Currently, unified hierarchy can be mounted with the following mount
-command.  Note that this is still under development and scheduled to
-change soon.
-
- mount -t cgroup -o __DEVEL__sane_behavior cgroup $MOUNT_POINT
-
-All controllers which support the unified hierarchy and are not bound
-to other hierarchies are automatically bound to unified hierarchy and
-show up at the root of it.  Controllers which are enabled only in the
-root of unified hierarchy can be bound to other hierarchies.  This
-allows mixing unified hierarchy with the traditional multiple
-hierarchies in a fully backward compatible way.
-
-A controller can be moved across hierarchies only after the controller
-is no longer referenced in its current hierarchy.  Because per-cgroup
-controller states are destroyed asynchronously and controllers may
-have lingering references, a controller may not show up immediately on
-the unified hierarchy after the final umount of the previous
-hierarchy.  Similarly, a controller should be fully disabled to be
-moved out of the unified hierarchy and it may take some time for the
-disabled controller to become available for other hierarchies;
-furthermore, due to dependencies among controllers, other controllers
-may need to be disabled too.
-
-While useful for development and manual configurations, dynamically
-moving controllers between the unified and other hierarchies is
-strongly discouraged for production use.  It is recommended to decide
-the hierarchies and controller associations before starting using the
-controllers.
-
-
-2-2. cgroup.subtree_control
-
-All cgroups on unified hierarchy have a "cgroup.subtree_control" file
-which governs which controllers are enabled on the children of the
-cgroup.  Let's assume a hierarchy like the following.
-
-  root - A - B - C
-               \ D
-
-root's "cgroup.subtree_control" file determines which controllers are
-enabled on A.  A's on B.  B's on C and D.  This coincides with the
-fact that controllers on the immediate sub-level are used to
-distribute the resources of the parent.  In fact, it's natural to
-assume that resource control knobs of a child belong to its parent.
-Enabling a controller in a "cgroup.subtree_control" file declares that
-distribution of the respective resources of the cgroup will be
-controlled.  Note that this means that controller enable states are
-shared among siblings.
-
-When read, the file contains a space-separated list of currently
-enabled controllers.  A write to the file should contain a
-space-separated list of controllers with '+' or '-' prefixed (without
-the quotes).  Controllers prefixed with '+' are enabled and '-'
-disabled.  If a controller is listed multiple times, the last entry
-wins.  The specific operations are executed atomically - either all
-succeed or fail.
-
-
-2-3. cgroup.controllers
-
-Read-only "cgroup.controllers" file contains a space-separated list of
-controllers which can be enabled in the cgroup's
-"cgroup.subtree_control" file.
-
-In the root cgroup, this lists controllers which are not bound to
-other hierarchies and the content changes as controllers are bound to
-and unbound from other hierarchies.
-
-In non-root cgroups, the content of this file equals that of the
-parent's "cgroup.subtree_control" file as only controllers enabled
-from the parent can be used in its children.
-
-
-3. Structural Constraints
-
-3-1. Top-down
-
-As it doesn't make sense to nest control of an uncontrolled resource,
-all non-root "cgroup.subtree_control" files can only contain
-controllers which are enabled in the parent's "cgroup.subtree_control"
-file.  A controller can be enabled only if the parent has the
-controller enabled and a controller can't be disabled if one or more
-children have it enabled.
-
-
-3-2. No internal tasks
-
-One long-standing issue that cgroup faces is the competition between
-tasks belonging to the parent cgroup and its children cgroups.  This
-is inherently nasty as two different types of entities compete and
-there is no agreed-upon obvious way to handle it.  Different
-controllers are doing different things.
-
-The cpu controller considers tasks and cgroups as equivalents and maps
-nice levels to cgroup weights.  This works for some cases but falls
-flat when children should be allocated specific ratios of CPU cycles
-and the number of internal tasks fluctuates - the ratios constantly
-change as the number of competing entities fluctuates.  There also are
-other issues.  The mapping from nice level to weight isn't obvious or
-universal, and there are various other knobs which simply aren't
-available for tasks.
-
-The io controller implicitly creates a hidden leaf node for each
-cgroup to host the tasks.  The hidden leaf has its own copies of all
-the knobs with "leaf_" prefixed.  While this allows equivalent control
-over internal tasks, it's with serious drawbacks.  It always adds an
-extra layer of nesting which may not be necessary, makes the interface
-messy and significantly complicates the implementation.
-
-The memory controller currently doesn't have a way to control what
-happens between internal tasks and child cgroups and the behavior is
-not clearly defined.  There have been attempts to add ad-hoc behaviors
-and knobs to tailor the behavior to specific workloads.  Continuing
-this direction will lead to problems which will be extremely difficult
-to resolve in the long term.
-
-Multiple controllers struggle with internal tasks and came up with
-different ways to deal with it; unfortunately, all the approaches in
-use now are severely flawed and, furthermore, the widely different
-behaviors make cgroup as whole highly inconsistent.
-
-It is clear that this is something which needs to be addressed from
-cgroup core proper in a uniform way so that controllers don't need to
-worry about it and cgroup as a whole shows a consistent and logical
-behavior.  To achieve that, unified hierarchy enforces the following
-structural constraint:
-
- Except for the root, only cgroups which don't contain any task may
- have controllers enabled in their "cgroup.subtree_control" files.
-
-Combined with other properties, this guarantees that, when a
-controller is looking at the part of the hierarchy which has it
-enabled, tasks are always only on the leaves.  This rules out
-situations where child cgroups compete against internal tasks of the
-parent.
-
-There are two things to note.  Firstly, the root cgroup is exempt from
-the restriction.  Root contains tasks and anonymous resource
-consumption which can't be associated with any other cgroup and
-requires special treatment from most controllers.  How resource
-consumption in the root cgroup is governed is up to each controller.
-
-Secondly, the restriction doesn't take effect if there is no enabled
-controller in the cgroup's "cgroup.subtree_control" file.  This is
-important as otherwise it wouldn't be possible to create children of a
-populated cgroup.  To control resource distribution of a cgroup, the
-cgroup must create children and transfer all its tasks to the children
-before enabling controllers in its "cgroup.subtree_control" file.
-
-
-4. Delegation
-
-4-1. Model of delegation
-
-A cgroup can be delegated to a less privileged user by granting write
-access of the directory and its "cgroup.procs" file to the user.  Note
-that the resource control knobs in a given directory concern the
-resources of the parent and thus must not be delegated along with the
-directory.
-
-Once delegated, the user can build sub-hierarchy under the directory,
-organize processes as it sees fit and further distribute the resources
-it got from the parent.  The limits and other settings of all resource
-controllers are hierarchical and regardless of what happens in the
-delegated sub-hierarchy, nothing can escape the resource restrictions
-imposed by the parent.
-
-Currently, cgroup doesn't impose any restrictions on the number of
-cgroups in or nesting depth of a delegated sub-hierarchy; however,
-this may in the future be limited explicitly.
-
-
-4-2. Common ancestor rule
-
-On the unified hierarchy, to write to a "cgroup.procs" file, in
-addition to the usual write permission to the file and uid match, the
-writer must also have write access to the "cgroup.procs" file of the
-common ancestor of the source and destination cgroups.  This prevents
-delegatees from smuggling processes across disjoint sub-hierarchies.
-
-Let's say cgroups C0 and C1 have been delegated to user U0 who created
-C00, C01 under C0 and C10 under C1 as follows.
-
- ~~~~~~~~~~~~~ - C0 - C00
- ~ cgroup    ~      \ C01
- ~ hierarchy ~
- ~~~~~~~~~~~~~ - C1 - C10
-
-C0 and C1 are separate entities in terms of resource distribution
-regardless of their relative positions in the hierarchy.  The
-resources the processes under C0 are entitled to are controlled by
-C0's ancestors and may be completely different from C1.  It's clear
-that the intention of delegating C0 to U0 is allowing U0 to organize
-the processes under C0 and further control the distribution of C0's
-resources.
-
-On traditional hierarchies, if a task has write access to "tasks" or
-"cgroup.procs" file of a cgroup and its uid agrees with the target, it
-can move the target to the cgroup.  In the above example, U0 will not
-only be able to move processes in each sub-hierarchy but also across
-the two sub-hierarchies, effectively allowing it to violate the
-organizational and resource restrictions implied by the hierarchical
-structure above C0 and C1.
-
-On the unified hierarchy, let's say U0 wants to write the pid of a
-process which has a matching uid and is currently in C10 into
-"C00/cgroup.procs".  U0 obviously has write access to the file and
-migration permission on the process; however, the common ancestor of
-the source cgroup C10 and the destination cgroup C00 is above the
-points of delegation and U0 would not have write access to its
-"cgroup.procs" and thus be denied with -EACCES.
-
-
-5. Other Changes
-
-5-1. [Un]populated Notification
-
-cgroup users often need a way to determine when a cgroup's
-subhierarchy becomes empty so that it can be cleaned up.  cgroup
-currently provides release_agent for it; unfortunately, this mechanism
-is riddled with issues.
-
-- It delivers events by forking and execing a userland binary
-  specified as the release_agent.  This is a long deprecated method of
-  notification delivery.  It's extremely heavy, slow and cumbersome to
-  integrate with larger infrastructure.
-
-- There is single monitoring point at the root.  There's no way to
-  delegate management of a subtree.
-
-- The event isn't recursive.  It triggers when a cgroup doesn't have
-  any tasks or child cgroups.  Events for internal nodes trigger only
-  after all children are removed.  This again makes it impossible to
-  delegate management of a subtree.
-
-- Events are filtered from the kernel side.  A "notify_on_release"
-  file is used to subscribe to or suppress release events.  This is
-  unnecessarily complicated and probably done this way because event
-  delivery itself was expensive.
-
-Unified hierarchy implements "populated" field in "cgroup.events"
-interface file which can be used to monitor whether the cgroup's
-subhierarchy has tasks in it or not.  Its value is 0 if there is no
-task in the cgroup and its descendants; otherwise, 1.  poll and
-[id]notify events are triggered when the value changes.
-
-This is significantly lighter and simpler and trivially allows
-delegating management of subhierarchy - subhierarchy monitoring can
-block further propagation simply by putting itself or another process
-in the subhierarchy and monitor events that it's interested in from
-there without interfering with monitoring higher in the tree.
-
-In unified hierarchy, the release_agent mechanism is no longer
-supported and the interface files "release_agent" and
-"notify_on_release" do not exist.
-
-
-5-2. Other Core Changes
-
-- None of the mount options is allowed.
-
-- remount is disallowed.
-
-- rename(2) is disallowed.
-
-- The "tasks" file is removed.  Everything should at process
-  granularity.  Use the "cgroup.procs" file instead.
-
-- The "cgroup.procs" file is not sorted.  pids will be unique unless
-  they got recycled in-between reads.
-
-- The "cgroup.clone_children" file is removed.
-
-- /proc/PID/cgroup keeps reporting the cgroup that a zombie belonged
-  to before exiting.  If the cgroup is removed before the zombie is
-  reaped, " (deleted)" is appeneded to the path.
-
-
-5-3. Controller File Conventions
-
-5-3-1. Format
-
-In general, all controller files should be in one of the following
-formats whenever possible.
-
-- Values only files
-
-  VAL0 VAL1...\n
-
-- Flat keyed files
-
-  KEY0 VAL0\n
-  KEY1 VAL1\n
-  ...
-
-- Nested keyed files
-
-  KEY0 SUB_KEY0=VAL00 SUB_KEY1=VAL01...
-  KEY1 SUB_KEY0=VAL10 SUB_KEY1=VAL11...
-  ...
-
-For a writeable file, the format for writing should generally match
-reading; however, controllers may allow omitting later fields or
-implement restricted shortcuts for most common use cases.
-
-For both flat and nested keyed files, only the values for a single key
-can be written at a time.  For nested keyed files, the sub key pairs
-may be specified in any order and not all pairs have to be specified.
-
-
-5-3-2. Control Knobs
-
-- Settings for a single feature should generally be implemented in a
-  single file.
-
-- In general, the root cgroup should be exempt from resource control
-  and thus shouldn't have resource control knobs.
-
-- If a controller implements ratio based resource distribution, the
-  control knob should be named "weight" and have the range [1, 10000]
-  and 100 should be the default value.  The values are chosen to allow
-  enough and symmetric bias in both directions while keeping it
-  intuitive (the default is 100%).
-
-- If a controller implements an absolute resource guarantee and/or
-  limit, the control knobs should be named "min" and "max"
-  respectively.  If a controller implements best effort resource
-  gurantee and/or limit, the control knobs should be named "low" and
-  "high" respectively.
-
-  In the above four control files, the special token "max" should be
-  used to represent upward infinity for both reading and writing.
-
-- If a setting has configurable default value and specific overrides,
-  the default settings should be keyed with "default" and appear as
-  the first entry in the file.  Specific entries can use "default" as
-  its value to indicate inheritance of the default value.
-
-- For events which are not very high frequency, an interface file
-  "events" should be created which lists event key value pairs.
-  Whenever a notifiable event happens, file modified event should be
-  generated on the file.
-
-
-5-4. Per-Controller Changes
-
-5-4-1. io
-
-- blkio is renamed to io.  The interface is overhauled anyway.  The
-  new name is more in line with the other two major controllers, cpu
-  and memory, and better suited given that it may be used for cgroup
-  writeback without involving block layer.
-
-- Everything including stat is always hierarchical making separate
-  recursive stat files pointless and, as no internal node can have
-  tasks, leaf weights are meaningless.  The operation model is
-  simplified and the interface is overhauled accordingly.
-
-  io.stat
-
-       The stat file.  The reported stats are from the point where
-       bio's are issued to request_queue.  The stats are counted
-       independent of which policies are enabled.  Each line in the
-       file follows the following format.  More fields may later be
-       added at the end.
-
-         $MAJ:$MIN rbytes=$RBYTES wbytes=$WBYTES rios=$RIOS wrios=$WIOS
-
-  io.weight
-
-       The weight setting, currently only available and effective if
-       cfq-iosched is in use for the target device.  The weight is
-       between 1 and 10000 and defaults to 100.  The first line
-       always contains the default weight in the following format to
-       use when per-device setting is missing.
-
-         default $WEIGHT
-
-       Subsequent lines list per-device weights of the following
-       format.
-
-         $MAJ:$MIN $WEIGHT
-
-       Writing "$WEIGHT" or "default $WEIGHT" changes the default
-       setting.  Writing "$MAJ:$MIN $WEIGHT" sets per-device weight
-       while "$MAJ:$MIN default" clears it.
-
-       This file is available only on non-root cgroups.
-
-  io.max
-
-       The maximum bandwidth and/or iops setting, only available if
-       blk-throttle is enabled.  The file is of the following format.
-
-         $MAJ:$MIN rbps=$RBPS wbps=$WBPS riops=$RIOPS wiops=$WIOPS
-
-       ${R|W}BPS are read/write bytes per second and ${R|W}IOPS are
-       read/write IOs per second.  "max" indicates no limit.  Writing
-       to the file follows the same format but the individual
-       settings may be omitted or specified in any order.
-
-       This file is available only on non-root cgroups.
-
-
-5-4-2. cpuset
-
-- Tasks are kept in empty cpusets after hotplug and take on the masks
-  of the nearest non-empty ancestor, instead of being moved to it.
-
-- A task can be moved into an empty cpuset, and again it takes on the
-  masks of the nearest non-empty ancestor.
-
-
-5-4-3. memory
-
-- use_hierarchy is on by default and the cgroup file for the flag is
-  not created.
-
-- The original lower boundary, the soft limit, is defined as a limit
-  that is per default unset.  As a result, the set of cgroups that
-  global reclaim prefers is opt-in, rather than opt-out.  The costs
-  for optimizing these mostly negative lookups are so high that the
-  implementation, despite its enormous size, does not even provide the
-  basic desirable behavior.  First off, the soft limit has no
-  hierarchical meaning.  All configured groups are organized in a
-  global rbtree and treated like equal peers, regardless where they
-  are located in the hierarchy.  This makes subtree delegation
-  impossible.  Second, the soft limit reclaim pass is so aggressive
-  that it not just introduces high allocation latencies into the
-  system, but also impacts system performance due to overreclaim, to
-  the point where the feature becomes self-defeating.
-
-  The memory.low boundary on the other hand is a top-down allocated
-  reserve.  A cgroup enjoys reclaim protection when it and all its
-  ancestors are below their low boundaries, which makes delegation of
-  subtrees possible.  Secondly, new cgroups have no reserve per
-  default and in the common case most cgroups are eligible for the
-  preferred reclaim pass.  This allows the new low boundary to be
-  efficiently implemented with just a minor addition to the generic
-  reclaim code, without the need for out-of-band data structures and
-  reclaim passes.  Because the generic reclaim code considers all
-  cgroups except for the ones running low in the preferred first
-  reclaim pass, overreclaim of individual groups is eliminated as
-  well, resulting in much better overall workload performance.
-
-- The original high boundary, the hard limit, is defined as a strict
-  limit that can not budge, even if the OOM killer has to be called.
-  But this generally goes against the goal of making the most out of
-  the available memory.  The memory consumption of workloads varies
-  during runtime, and that requires users to overcommit.  But doing
-  that with a strict upper limit requires either a fairly accurate
-  prediction of the working set size or adding slack to the limit.
-  Since working set size estimation is hard and error prone, and
-  getting it wrong results in OOM kills, most users tend to err on the
-  side of a looser limit and end up wasting precious resources.
-
-  The memory.high boundary on the other hand can be set much more
-  conservatively.  When hit, it throttles allocations by forcing them
-  into direct reclaim to work off the excess, but it never invokes the
-  OOM killer.  As a result, a high boundary that is chosen too
-  aggressively will not terminate the processes, but instead it will
-  lead to gradual performance degradation.  The user can monitor this
-  and make corrections until the minimal memory footprint that still
-  gives acceptable performance is found.
-
-  In extreme cases, with many concurrent allocations and a complete
-  breakdown of reclaim progress within the group, the high boundary
-  can be exceeded.  But even then it's mostly better to satisfy the
-  allocation from the slack available in other groups or the rest of
-  the system than killing the group.  Otherwise, memory.max is there
-  to limit this type of spillover and ultimately contain buggy or even
-  malicious applications.
-
-- The original control file names are unwieldy and inconsistent in
-  many different ways.  For example, the upper boundary hit count is
-  exported in the memory.failcnt file, but an OOM event count has to
-  be manually counted by listening to memory.oom_control events, and
-  lower boundary / soft limit events have to be counted by first
-  setting a threshold for that value and then counting those events.
-  Also, usage and limit files encode their units in the filename.
-  That makes the filenames very long, even though this is not
-  information that a user needs to be reminded of every time they type
-  out those names.
-
-  To address these naming issues, as well as to signal clearly that
-  the new interface carries a new configuration model, the naming
-  conventions in it necessarily differ from the old interface.
-
-- The original limit files indicate the state of an unset limit with a
-  Very High Number, and a configured limit can be unset by echoing -1
-  into those files.  But that very high number is implementation and
-  architecture dependent and not very descriptive.  And while -1 can
-  be understood as an underflow into the highest possible value, -2 or
-  -10M etc. do not work, so it's not consistent.
-
-  memory.low, memory.high, and memory.max will use the string "max" to
-  indicate and set the highest possible value.
-
-6. Planned Changes
-
-6-1. CAP for resource control
-
-Unified hierarchy will require one of the capabilities(7), which is
-yet to be decided, for all resource control related knobs.  Process
-organization operations - creation of sub-cgroups and migration of
-processes in sub-hierarchies may be delegated by changing the
-ownership and/or permissions on the cgroup directory and
-"cgroup.procs" interface file; however, all operations which affect
-resource control - writes to a "cgroup.subtree_control" file or any
-controller-specific knobs - will require an explicit CAP privilege.
-
-This, in part, is to prevent the cgroup interface from being
-inadvertently promoted to programmable API used by non-privileged
-binaries.  cgroup exposes various aspects of the system in ways which
-aren't properly abstracted for direct consumption by regular programs.
-This is an administration interface much closer to sysctl knobs than
-system calls.  Even the basic access model, being filesystem path
-based, isn't suitable for direct consumption.  There's no way to
-access "my cgroup" in a race-free way or make multiple operations
-atomic against migration to another cgroup.
-
-Another aspect is that, for better or for worse, the cgroup interface
-goes through far less scrutiny than regular interfaces for
-unprivileged userland.  The upside is that cgroup is able to expose
-useful features which may not be suitable for general consumption in a
-reasonable time frame.  It provides a relatively short path between
-internal details and userland-visible interface.  Of course, this
-shortcut comes with high risk.  We go through what we go through for
-general kernel APIs for good reasons.  It may end up leaking internal
-details in a way which can exert significant pain by locking the
-kernel into a contract that can't be maintained in a reasonable
-manner.
-
-Also, due to the specific nature, cgroup and its controllers don't
-tend to attract attention from a wide scope of developers.  cgroup's
-short history is already fraught with severely mis-designed
-interfaces, unnecessary commitments to and exposing of internal
-details, broken and dangerous implementations of various features.
-
-Keeping cgroup as an administration interface is both advantageous for
-its role and imperative given its nature.  Some of the cgroup features
-may make sense for unprivileged access.  If deemed justified, those
-must be further abstracted and implemented as a different interface,
-be it a system call or process-private filesystem, and survive through
-the scrutiny that any interface for general consumption is required to
-go through.
-
-Requiring CAP is not a complete solution but should serve as a
-significant deterrent against spraying cgroup usages in non-privileged
-programs.
index be8d4006bf767d37b7b1882ba962363abb1f81d3..f7b12c071d5356ceed76231a07b4e49f59e9f8d8 100644 (file)
-Intel P-state driver
+Intel P-State driver
 --------------------
 
-This driver provides an interface to control the P state selection for
-SandyBridge+ Intel processors.  The driver can operate two different
-modes based on the processor model, legacy mode and Hardware P state (HWP)
-mode.
-
-In legacy mode, the Intel P-state implements two internal governors,
-performance and powersave, that differ from the general cpufreq governors of
-the same name (the general cpufreq governors implement target(), whereas the
-internal Intel P-state governors implement setpolicy()).  The internal
-performance governor sets the max_perf_pct and min_perf_pct to 100; that is,
-the governor selects the highest available P state to maximize the performance
-of the core.  The internal powersave governor selects the appropriate P state
-based on the current load on the CPU.
-
-In HWP mode P state selection is implemented in the processor
-itself. The driver provides the interfaces between the cpufreq core and
-the processor to control P state selection based on user preferences
-and reporting frequency to the cpufreq core.  In this mode the
-internal Intel P-state governor code is disabled.
-
-In addition to the interfaces provided by the cpufreq core for
-controlling frequency the driver provides sysfs files for
-controlling P state selection. These files have been added to
-/sys/devices/system/cpu/intel_pstate/
-
-      max_perf_pct: limits the maximum P state that will be requested by
-      the driver stated as a percentage of the available performance. The
-      available (P states) performance may be reduced by the no_turbo
+This driver provides an interface to control the P-State selection for the
+SandyBridge+ Intel processors.
+
+The following document explains P-States:
+http://events.linuxfoundation.org/sites/events/files/slides/LinuxConEurope_2015.pdf
+As stated in the document, P-State doesn’t exactly mean a frequency. However, for
+the sake of the relationship with cpufreq, P-State and frequency are used
+interchangeably.
+
+Understanding the cpufreq core governors and policies are important before
+discussing more details about the Intel P-State driver. Based on what callbacks
+a cpufreq driver provides to the cpufreq core, it can support two types of
+drivers:
+- with target_index() callback: In this mode, the drivers using cpufreq core
+simply provide the minimum and maximum frequency limits and an additional
+interface target_index() to set the current frequency. The cpufreq subsystem
+has a number of scaling governors ("performance", "powersave", "ondemand",
+etc.). Depending on which governor is in use, cpufreq core will call for
+transitions to a specific frequency using target_index() callback.
+- setpolicy() callback: In this mode, drivers do not provide target_index()
+callback, so cpufreq core can't request a transition to a specific frequency.
+The driver provides minimum and maximum frequency limits and callbacks to set a
+policy. The policy in cpufreq sysfs is referred to as the "scaling governor".
+The cpufreq core can request the driver to operate in any of the two policies:
+"performance: and "powersave". The driver decides which frequency to use based
+on the above policy selection considering minimum and maximum frequency limits.
+
+The Intel P-State driver falls under the latter category, which implements the
+setpolicy() callback. This driver decides what P-State to use based on the
+requested policy from the cpufreq core. If the processor is capable of
+selecting its next P-State internally, then the driver will offload this
+responsibility to the processor (aka HWP: Hardware P-States). If not, the
+driver implements algorithms to select the next P-State.
+
+Since these policies are implemented in the driver, they are not same as the
+cpufreq scaling governors implementation, even if they have the same name in
+the cpufreq sysfs (scaling_governors). For example the "performance" policy is
+similar to cpufreq’s "performance" governor, but "powersave" is completely
+different than the cpufreq "powersave" governor. The strategy here is similar
+to cpufreq "ondemand", where the requested P-State is related to the system load.
+
+Sysfs Interface
+
+In addition to the frequency-controlling interfaces provided by the cpufreq
+core, the driver provides its own sysfs files to control the P-State selection.
+These files have been added to /sys/devices/system/cpu/intel_pstate/.
+Any changes made to these files are applicable to all CPUs (even in a
+multi-package system).
+
+      max_perf_pct: Limits the maximum P-State that will be requested by
+      the driver. It states it as a percentage of the available performance. The
+      available (P-State) performance may be reduced by the no_turbo
       setting described below.
 
-      min_perf_pct: limits the minimum P state that will be  requested by
-      the driver stated as a percentage of the max (non-turbo)
+      min_perf_pct: Limits the minimum P-State that will be requested by
+      the driver. It states it as a percentage of the max (non-turbo)
       performance level.
 
-      no_turbo: limits the driver to selecting P states below the turbo
+      no_turbo: Limits the driver to selecting P-State below the turbo
       frequency range.
 
-      turbo_pct: displays the percentage of the total performance that
-      is supported by hardware that is in the turbo range.  This number
+      turbo_pct: Displays the percentage of the total performance that
+      is supported by hardware that is in the turbo range. This number
       is independent of whether turbo has been disabled or not.
 
-      num_pstates: displays the number of pstates that are supported
-      by hardware.  This number is independent of whether turbo has
+      num_pstates: Displays the number of P-States that are supported
+      by hardware. This number is independent of whether turbo has
       been disabled or not.
 
+For example, if a system has these parameters:
+       Max 1 core turbo ratio: 0x21 (Max 1 core ratio is the maximum P-State)
+       Max non turbo ratio: 0x17
+       Minimum ratio : 0x08 (Here the ratio is called max efficiency ratio)
+
+Sysfs will show :
+       max_perf_pct:100, which corresponds to 1 core ratio
+       min_perf_pct:24, max_efficiency_ratio / max 1 Core ratio
+       no_turbo:0, turbo is not disabled
+       num_pstates:26 = (max 1 Core ratio - Max Efficiency Ratio + 1)
+       turbo_pct:39 = (max 1 core ratio - max non turbo ratio) / num_pstates
+
+Refer to "Intel® 64 and IA-32 Architectures Software Developer’s Manual
+Volume 3: System Programming Guide" to understand ratios.
+
+cpufreq sysfs for Intel P-State
+
+Since this driver registers with cpufreq, cpufreq sysfs is also presented.
+There are some important differences, which need to be considered.
+
+scaling_cur_freq: This displays the real frequency which was used during
+the last sample period instead of what is requested. Some other cpufreq driver,
+like acpi-cpufreq, displays what is requested (Some changes are on the
+way to fix this for acpi-cpufreq driver). The same is true for frequencies
+displayed at /proc/cpuinfo.
+
+scaling_governor: This displays current active policy. Since each CPU has a
+cpufreq sysfs, it is possible to set a scaling governor to each CPU. But this
+is not possible with Intel P-States, as there is one common policy for all
+CPUs. Here, the last requested policy will be applicable to all CPUs. It is
+suggested that one use the cpupower utility to change policy to all CPUs at the
+same time.
+
+scaling_setspeed: This attribute can never be used with Intel P-State.
+
+scaling_max_freq/scaling_min_freq: This interface can be used similarly to
+the max_perf_pct/min_perf_pct of Intel P-State sysfs. However since frequencies
+are converted to nearest possible P-State, this is prone to rounding errors.
+This method is not preferred to limit performance.
+
+affected_cpus: Not used
+related_cpus: Not used
+
 For contemporary Intel processors, the frequency is controlled by the
-processor itself and the P-states exposed to software are related to
+processor itself and the P-State exposed to software is related to
 performance levels.  The idea that frequency can be set to a single
-frequency is fiction for Intel Core processors. Even if the scaling
-driver selects a single P state the actual frequency the processor
+frequency is fictional for Intel Core processors. Even if the scaling
+driver selects a single P-State, the actual frequency the processor
 will run at is selected by the processor itself.
 
-For legacy mode debugfs files have also been added to allow tuning of
-the internal governor algorythm. These files are located at
-/sys/kernel/debug/pstate_snb/ These files are NOT present in HWP mode.
+Tuning Intel P-State driver
+
+When HWP mode is not used, debugfs files have also been added to allow the
+tuning of the internal governor algorithm. These files are located at
+/sys/kernel/debug/pstate_snb/. The algorithm uses a PID (Proportional
+Integral Derivative) controller. The PID tunable parameters are:
 
       deadband
       d_gain_pct
@@ -63,3 +133,90 @@ the internal governor algorythm. These files are located at
       p_gain_pct
       sample_rate_ms
       setpoint
+
+To adjust these parameters, some understanding of driver implementation is
+necessary. There are some tweeks described here, but be very careful. Adjusting
+them requires expert level understanding of power and performance relationship.
+These limits are only useful when the "powersave" policy is active.
+
+-To make the system more responsive to load changes, sample_rate_ms can
+be adjusted  (current default is 10ms).
+-To make the system use higher performance, even if the load is lower, setpoint
+can be adjusted to a lower number. This will also lead to faster ramp up time
+to reach the maximum P-State.
+If there are no derivative and integral coefficients, The next P-State will be
+equal to:
+       current P-State - ((setpoint - current cpu load) * p_gain_pct)
+
+For example, if the current PID parameters are (Which are defaults for the core
+processors like SandyBridge):
+      deadband = 0
+      d_gain_pct = 0
+      i_gain_pct = 0
+      p_gain_pct = 20
+      sample_rate_ms = 10
+      setpoint = 97
+
+If the current P-State = 0x08 and current load = 100, this will result in the
+next P-State = 0x08 - ((97 - 100) * 0.2) = 8.6 (rounded to 9). Here the P-State
+goes up by only 1. If during next sample interval the current load doesn't
+change and still 100, then P-State goes up by one again. This process will
+continue as long as the load is more than the setpoint until the maximum P-State
+is reached.
+
+For the same load at setpoint = 60, this will result in the next P-State
+= 0x08 - ((60 - 100) * 0.2) = 16
+So by changing the setpoint from 97 to 60, there is an increase of the
+next P-State from 9 to 16. So this will make processor execute at higher
+P-State for the same CPU load. If the load continues to be more than the
+setpoint during next sample intervals, then P-State will go up again till the
+maximum P-State is reached. But the ramp up time to reach the maximum P-State
+will be much faster when the setpoint is 60 compared to 97.
+
+Debugging Intel P-State driver
+
+Event tracing
+To debug P-State transition, the Linux event tracing interface can be used.
+There are two specific events, which can be enabled (Provided the kernel
+configs related to event tracing are enabled).
+
+# cd /sys/kernel/debug/tracing/
+# echo 1 > events/power/pstate_sample/enable
+# echo 1 > events/power/cpu_frequency/enable
+# cat trace
+gnome-terminal--4510  [001] ..s.  1177.680733: pstate_sample: core_busy=107
+       scaled=94 from=26 to=26 mperf=1143818 aperf=1230607 tsc=29838618
+               freq=2474476
+cat-5235  [002] ..s.  1177.681723: cpu_frequency: state=2900000 cpu_id=2
+
+
+Using ftrace
+
+If function level tracing is required, the Linux ftrace interface can be used.
+For example if we want to check how often a function to set a P-State is
+called, we can set ftrace filter to intel_pstate_set_pstate.
+
+# cd /sys/kernel/debug/tracing/
+# cat available_filter_functions | grep -i pstate
+intel_pstate_set_pstate
+intel_pstate_cpu_init
+...
+
+# echo intel_pstate_set_pstate > set_ftrace_filter
+# echo function > current_tracer
+# cat trace | head -15
+# tracer: function
+#
+# entries-in-buffer/entries-written: 80/80   #P:4
+#
+#                              _-----=> irqs-off
+#                             / _----=> need-resched
+#                            | / _---=> hardirq/softirq
+#                            || / _--=> preempt-depth
+#                            ||| /     delay
+#           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
+#              | |       |   ||||       |         |
+            Xorg-3129  [000] ..s.  2537.644844: intel_pstate_set_pstate <-intel_pstate_timer_func
+ gnome-terminal--4510  [002] ..s.  2537.649844: intel_pstate_set_pstate <-intel_pstate_timer_func
+     gnome-shell-3409  [001] ..s.  2537.650850: intel_pstate_set_pstate <-intel_pstate_timer_func
+          <idle>-0     [000] ..s.  2537.654843: intel_pstate_set_pstate <-intel_pstate_timer_func
index 9e3c3b33514c688dc253861af1c11b650af361de..0a94224ad2965bff7c25e2137c3834ea3d132c72 100644 (file)
@@ -159,8 +159,8 @@ to be strictly associated with a P-state.
 
 2.2 cpuinfo_transition_latency:
 -------------------------------
-The cpuinfo_transition_latency field is 0. The PCC specification does
-not include a field to expose this value currently.
+The cpuinfo_transition_latency field is CPUFREQ_ETERNAL. The PCC specification
+does not include a field to expose this value currently.
 
 2.3 cpuinfo_cur_freq:
 ---------------------
index 3a07a87fef2087550cb24f0c4aff5f8e2fecab21..6aca64f289b614e3c482d30e4d82af5e84967ce8 100644 (file)
@@ -242,6 +242,23 @@ nodes to be present and contain the properties described below.
                Definition: Specifies the syscon node controlling the cpu core
                            power domains.
 
+       - dynamic-power-coefficient
+               Usage: optional
+               Value type: <prop-encoded-array>
+               Definition: A u32 value that represents the running time dynamic
+                           power coefficient in units of mW/MHz/uVolt^2. The
+                           coefficient can either be calculated from power
+                           measurements or derived by analysis.
+
+                           The dynamic power consumption of the CPU  is
+                           proportional to the square of the Voltage (V) and
+                           the clock frequency (f). The coefficient is used to
+                           calculate the dynamic power as below -
+
+                           Pdyn = dynamic-power-coefficient * V^2 * f
+
+                           where voltage is in uV, frequency is in MHz.
+
 Example 1 (dual-cluster big.LITTLE system 32-bit):
 
        cpus {
diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-st.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-st.txt
new file mode 100644 (file)
index 0000000..d91a02a
--- /dev/null
@@ -0,0 +1,91 @@
+Binding for ST's CPUFreq driver
+===============================
+
+ST's CPUFreq driver attempts to read 'process' and 'version' attributes
+from the SoC, then supplies the OPP framework with 'prop' and 'supported
+hardware' information respectively.  The framework is then able to read
+the DT and operate in the usual way.
+
+For more information about the expected DT format [See: ../opp/opp.txt].
+
+Frequency Scaling only
+----------------------
+
+No vendor specific driver required for this.
+
+Located in CPU's node:
+
+- operating-points             : [See: ../power/opp.txt]
+
+Example [safe]
+--------------
+
+cpus {
+       cpu@0 {
+                                /* kHz     uV   */
+               operating-points = <1500000 0
+                                   1200000 0
+                                   800000  0
+                                   500000  0>;
+       };
+};
+
+Dynamic Voltage and Frequency Scaling (DVFS)
+--------------------------------------------
+
+This requires the ST CPUFreq driver to supply 'process' and 'version' info.
+
+Located in CPU's node:
+
+- operating-points-v2          : [See ../power/opp.txt]
+
+Example [unsafe]
+----------------
+
+cpus {
+       cpu@0 {
+               operating-points-v2     = <&cpu0_opp_table>;
+       };
+};
+
+cpu0_opp_table: opp_table {
+       compatible = "operating-points-v2";
+
+       /* ############################################################### */
+       /* # WARNING: Do not attempt to copy/replicate these nodes,      # */
+       /* #          they are only to be supplied by the bootloader !!! # */
+       /* ############################################################### */
+       opp0 {
+               /*                         Major       Minor       Substrate */
+               /*                         2           all         all       */
+               opp-supported-hw        = <0x00000004  0xffffffff  0xffffffff>;
+               opp-hz                  = /bits/ 64 <1500000000>;
+               clock-latency-ns        = <10000000>;
+
+               opp-microvolt-pcode0    = <1200000>;
+               opp-microvolt-pcode1    = <1200000>;
+               opp-microvolt-pcode2    = <1200000>;
+               opp-microvolt-pcode3    = <1200000>;
+               opp-microvolt-pcode4    = <1170000>;
+               opp-microvolt-pcode5    = <1140000>;
+               opp-microvolt-pcode6    = <1100000>;
+               opp-microvolt-pcode7    = <1070000>;
+       };
+
+       opp1 {
+               /*                         Major       Minor       Substrate */
+               /*                         all         all         all       */
+               opp-supported-hw        = <0xffffffff  0xffffffff  0xffffffff>;
+               opp-hz                  = /bits/ 64 <1200000000>;
+               clock-latency-ns        = <10000000>;
+
+               opp-microvolt-pcode0    = <1110000>;
+               opp-microvolt-pcode1    = <1150000>;
+               opp-microvolt-pcode2    = <1100000>;
+               opp-microvolt-pcode3    = <1080000>;
+               opp-microvolt-pcode4    = <1040000>;
+               opp-microvolt-pcode5    = <1020000>;
+               opp-microvolt-pcode6    = <980000>;
+               opp-microvolt-pcode7    = <930000>;
+       };
+};
index 0cb44dc21f97ca7cfde5056ce7d44941d3439546..601256fe8c0dd99d2df3ff5a77b2cee23a852e5d 100644 (file)
@@ -45,21 +45,10 @@ Devices supporting OPPs must set their "operating-points-v2" property with
 phandle to a OPP table in their DT node. The OPP core will use this phandle to
 find the operating points for the device.
 
-Devices may want to choose OPP tables at runtime and so can provide a list of
-phandles here. But only *one* of them should be chosen at runtime. This must be
-accompanied by a corresponding "operating-points-names" property, to uniquely
-identify the OPP tables.
-
 If required, this can be extended for SoC vendor specfic bindings. Such bindings
 should be documented as Documentation/devicetree/bindings/power/<vendor>-opp.txt
 and should have a compatible description like: "operating-points-v2-<vendor>".
 
-Optional properties:
-- operating-points-names: Names of OPP tables (required if multiple OPP
-  tables are present), to uniquely identify them. The same list must be present
-  for all the CPUs which are sharing clock/voltage rails and hence the OPP
-  tables.
-
 * OPP Table Node
 
 This describes the OPPs belonging to a device. This node can have following
@@ -100,6 +89,14 @@ Optional properties:
   Entries for multiple regulators must be present in the same order as
   regulators are specified in device's DT node.
 
+- opp-microvolt-<name>: Named opp-microvolt property. This is exactly similar to
+  the above opp-microvolt property, but allows multiple voltage ranges to be
+  provided for the same OPP. At runtime, the platform can pick a <name> and
+  matching opp-microvolt-<name> property will be enabled for all OPPs. If the
+  platform doesn't pick a specific <name> or the <name> doesn't match with any
+  opp-microvolt-<name> properties, then opp-microvolt property shall be used, if
+  present.
+
 - opp-microamp: The maximum current drawn by the device in microamperes
   considering system specific parameters (such as transients, process, aging,
   maximum operating temperature range etc.) as necessary. This may be used to
@@ -112,6 +109,9 @@ Optional properties:
   for few regulators, then this should be marked as zero for them. If it isn't
   required for any regulator, then this property need not be present.
 
+- opp-microamp-<name>: Named opp-microamp property. Similar to
+  opp-microvolt-<name> property, but for microamp instead.
+
 - clock-latency-ns: Specifies the maximum possible transition latency (in
   nanoseconds) for switching to this OPP from any other OPP.
 
@@ -123,6 +123,26 @@ Optional properties:
 - opp-suspend: Marks the OPP to be used during device suspend. Only one OPP in
   the table should have this.
 
+- opp-supported-hw: This enables us to select only a subset of OPPs from the
+  larger OPP table, based on what version of the hardware we are running on. We
+  still can't have multiple nodes with the same opp-hz value in OPP table.
+
+  It's an user defined array containing a hierarchy of hardware version numbers,
+  supported by the OPP. For example: a platform with hierarchy of three levels
+  of versions (A, B and C), this field should be like <X Y Z>, where X
+  corresponds to Version hierarchy A, Y corresponds to version hierarchy B and Z
+  corresponds to version hierarchy C.
+
+  Each level of hierarchy is represented by a 32 bit value, and so there can be
+  only 32 different supported version per hierarchy. i.e. 1 bit per version. A
+  value of 0xFFFFFFFF will enable the OPP for all versions for that hierarchy
+  level. And a value of 0x00000000 will disable the OPP completely, and so we
+  never want that to happen.
+
+  If 32 values aren't sufficient for a version hierarchy, than that version
+  hierarchy can be contained in multiple 32 bit values. i.e. <X Y Z1 Z2> in the
+  above example, Z1 & Z2 refer to the version hierarchy Z.
+
 - status: Marks the node enabled/disabled.
 
 Example 1: Single cluster Dual-core ARM cortex A9, switch DVFS states together.
@@ -157,20 +177,20 @@ Example 1: Single cluster Dual-core ARM cortex A9, switch DVFS states together.
                compatible = "operating-points-v2";
                opp-shared;
 
-               opp00 {
+               opp@1000000000 {
                        opp-hz = /bits/ 64 <1000000000>;
                        opp-microvolt = <970000 975000 985000>;
                        opp-microamp = <70000>;
                        clock-latency-ns = <300000>;
                        opp-suspend;
                };
-               opp01 {
+               opp@1100000000 {
                        opp-hz = /bits/ 64 <1100000000>;
                        opp-microvolt = <980000 1000000 1010000>;
                        opp-microamp = <80000>;
                        clock-latency-ns = <310000>;
                };
-               opp02 {
+               opp@1200000000 {
                        opp-hz = /bits/ 64 <1200000000>;
                        opp-microvolt = <1025000>;
                        clock-latency-ns = <290000>;
@@ -236,20 +256,20 @@ independently.
                 * independently.
                 */
 
-               opp00 {
+               opp@1000000000 {
                        opp-hz = /bits/ 64 <1000000000>;
                        opp-microvolt = <970000 975000 985000>;
                        opp-microamp = <70000>;
                        clock-latency-ns = <300000>;
                        opp-suspend;
                };
-               opp01 {
+               opp@1100000000 {
                        opp-hz = /bits/ 64 <1100000000>;
                        opp-microvolt = <980000 1000000 1010000>;
                        opp-microamp = <80000>;
                        clock-latency-ns = <310000>;
                };
-               opp02 {
+               opp@1200000000 {
                        opp-hz = /bits/ 64 <1200000000>;
                        opp-microvolt = <1025000>;
                        opp-microamp = <90000;
@@ -312,20 +332,20 @@ DVFS state together.
                compatible = "operating-points-v2";
                opp-shared;
 
-               opp00 {
+               opp@1000000000 {
                        opp-hz = /bits/ 64 <1000000000>;
                        opp-microvolt = <970000 975000 985000>;
                        opp-microamp = <70000>;
                        clock-latency-ns = <300000>;
                        opp-suspend;
                };
-               opp01 {
+               opp@1100000000 {
                        opp-hz = /bits/ 64 <1100000000>;
                        opp-microvolt = <980000 1000000 1010000>;
                        opp-microamp = <80000>;
                        clock-latency-ns = <310000>;
                };
-               opp02 {
+               opp@1200000000 {
                        opp-hz = /bits/ 64 <1200000000>;
                        opp-microvolt = <1025000>;
                        opp-microamp = <90000>;
@@ -338,20 +358,20 @@ DVFS state together.
                compatible = "operating-points-v2";
                opp-shared;
 
-               opp10 {
+               opp@1300000000 {
                        opp-hz = /bits/ 64 <1300000000>;
                        opp-microvolt = <1045000 1050000 1055000>;
                        opp-microamp = <95000>;
                        clock-latency-ns = <400000>;
                        opp-suspend;
                };
-               opp11 {
+               opp@1400000000 {
                        opp-hz = /bits/ 64 <1400000000>;
                        opp-microvolt = <1075000>;
                        opp-microamp = <100000>;
                        clock-latency-ns = <400000>;
                };
-               opp12 {
+               opp@1500000000 {
                        opp-hz = /bits/ 64 <1500000000>;
                        opp-microvolt = <1010000 1100000 1110000>;
                        opp-microamp = <95000>;
@@ -378,7 +398,7 @@ Example 4: Handling multiple regulators
                compatible = "operating-points-v2";
                opp-shared;
 
-               opp00 {
+               opp@1000000000 {
                        opp-hz = /bits/ 64 <1000000000>;
                        opp-microvolt = <970000>, /* Supply 0 */
                                        <960000>, /* Supply 1 */
@@ -391,7 +411,7 @@ Example 4: Handling multiple regulators
 
                /* OR */
 
-               opp00 {
+               opp@1000000000 {
                        opp-hz = /bits/ 64 <1000000000>;
                        opp-microvolt = <970000 975000 985000>, /* Supply 0 */
                                        <960000 965000 975000>, /* Supply 1 */
@@ -404,7 +424,7 @@ Example 4: Handling multiple regulators
 
                /* OR */
 
-               opp00 {
+               opp@1000000000 {
                        opp-hz = /bits/ 64 <1000000000>;
                        opp-microvolt = <970000 975000 985000>, /* Supply 0 */
                                        <960000 965000 975000>, /* Supply 1 */
@@ -417,7 +437,8 @@ Example 4: Handling multiple regulators
        };
 };
 
-Example 5: Multiple OPP tables
+Example 5: opp-supported-hw
+(example: three level hierarchy of versions: cuts, substrate and process)
 
 / {
        cpus {
@@ -426,40 +447,73 @@ Example 5: Multiple OPP tables
                        ...
 
                        cpu-supply = <&cpu_supply>
-                       operating-points-v2 = <&cpu0_opp_table_slow>, <&cpu0_opp_table_fast>;
-                       operating-points-names = "slow", "fast";
+                       operating-points-v2 = <&cpu0_opp_table_slow>;
                };
        };
 
-       cpu0_opp_table_slow: opp_table_slow {
+       opp_table {
                compatible = "operating-points-v2";
                status = "okay";
                opp-shared;
 
-               opp00 {
+               opp@600000000 {
+                       /*
+                        * Supports all substrate and process versions for 0xF
+                        * cuts, i.e. only first four cuts.
+                        */
+                       opp-supported-hw = <0xF 0xFFFFFFFF 0xFFFFFFFF>
                        opp-hz = /bits/ 64 <600000000>;
+                       opp-microvolt = <900000 915000 925000>;
                        ...
                };
 
-               opp01 {
+               opp@800000000 {
+                       /*
+                        * Supports:
+                        * - cuts: only one, 6th cut (represented by 6th bit).
+                        * - substrate: supports 16 different substrate versions
+                        * - process: supports 9 different process versions
+                        */
+                       opp-supported-hw = <0x20 0xff0000ff 0x0000f4f0>
                        opp-hz = /bits/ 64 <800000000>;
+                       opp-microvolt = <900000 915000 925000>;
                        ...
                };
        };
+};
+
+Example 6: opp-microvolt-<name>, opp-microamp-<name>:
+(example: device with two possible microvolt ranges: slow and fast)
 
-       cpu0_opp_table_fast: opp_table_fast {
+/ {
+       cpus {
+               cpu@0 {
+                       compatible = "arm,cortex-a7";
+                       ...
+
+                       operating-points-v2 = <&cpu0_opp_table>;
+               };
+       };
+
+       cpu0_opp_table: opp_table0 {
                compatible = "operating-points-v2";
-               status = "okay";
                opp-shared;
 
-               opp10 {
+               opp@1000000000 {
                        opp-hz = /bits/ 64 <1000000000>;
-                       ...
+                       opp-microvolt-slow = <900000 915000 925000>;
+                       opp-microvolt-fast = <970000 975000 985000>;
+                       opp-microamp-slow =  <70000>;
+                       opp-microamp-fast =  <71000>;
                };
 
-               opp11 {
-                       opp-hz = /bits/ 64 <1100000000>;
-                       ...
+               opp@1200000000 {
+                       opp-hz = /bits/ 64 <1200000000>;
+                       opp-microvolt-slow = <900000 915000 925000>, /* Supply vcc0 */
+                                             <910000 925000 935000>; /* Supply vcc1 */
+                       opp-microvolt-fast = <970000 975000 985000>, /* Supply vcc0 */
+                                            <960000 965000 975000>; /* Supply vcc1 */
+                       opp-microamp =  <70000>; /* Will be used for both slow/fast */
                };
        };
 };
index 3a930072b161fd51b3b1d007daac673526609dc2..ec8f934c2eb240f93a54b0044faadd913e7855f8 100644 (file)
@@ -28,6 +28,23 @@ radiotap headers and used to control injection:
    IEEE80211_RADIOTAP_F_TX_NOACK: frame should be sent without waiting for
                                  an ACK even if it is a unicast frame
 
+ * IEEE80211_RADIOTAP_RATE
+
+   legacy rate for the transmission (only for devices without own rate control)
+
+ * IEEE80211_RADIOTAP_MCS
+
+   HT rate for the transmission (only for devices without own rate control).
+   Also some flags are parsed
+
+   IEEE80211_TX_RC_SHORT_GI: use short guard interval
+   IEEE80211_TX_RC_40_MHZ_WIDTH: send in HT40 mode
+
+ * IEEE80211_RADIOTAP_DATA_RETRIES
+
+   number of retries when either IEEE80211_RADIOTAP_RATE or
+   IEEE80211_RADIOTAP_MCS was used
+
 The injection code can also skip all other currently defined radiotap fields
 facilitating replay of captured radiotap headers directly.
 
index b0e911e0e8f50ad749686961e494377a1a49db45..44558882aa602816f3b1579ac94b3894562ac2b9 100644 (file)
@@ -999,7 +999,7 @@ from its probe routine to make runtime PM work for the device.
 
 It is important to remember that the driver's runtime_suspend() callback
 may be executed right after the usage counter has been decremented, because
-user space may already have cuased the pm_runtime_allow() helper function
+user space may already have caused the pm_runtime_allow() helper function
 unblocking the runtime PM of the device to run via sysfs, so the driver must
 be prepared to cope with that.
 
index 0784bc3a2ab51bd2d624644d6ea5a41e44529307..7328cf85236c2b2bc5a4c078dc9f81f2e3febd11 100644 (file)
@@ -371,6 +371,12 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
     - increment the device's usage counter, run pm_runtime_resume(dev) and
       return its result
 
+  int pm_runtime_get_if_in_use(struct device *dev);
+    - return -EINVAL if 'power.disable_depth' is nonzero; otherwise, if the
+      runtime PM status is RPM_ACTIVE and the runtime PM usage counter is
+      nonzero, increment the counter and return 1; otherwise return 0 without
+      changing the counter
+
   void pm_runtime_put_noidle(struct device *dev);
     - decrement the device's usage counter
 
index 2ee6ef9a6554d600088ae572b3256ffe44e51d08..1f0c27049340d9603ec90fa1694d4e0e14dbb5c7 100644 (file)
@@ -83,6 +83,8 @@ rfkill drivers that control devices that can be hard-blocked unless they also
 assign the poll_hw_block() callback (then the rfkill core will poll the
 device). Don't do this unless you cannot get the event in any other way.
 
+RFKill provides per-switch LED triggers, which can be used to drive LEDs
+according to the switch state (LED_FULL when blocked, LED_OFF otherwise).
 
 
 5. Userspace support
index 14ef6ec44ef95f7285e0872baf12f982b6b37ad8..ded96408efe6c2f894229d153fa623a322c6c533 100644 (file)
@@ -8466,6 +8466,17 @@ F:       fs/timerfd.c
 F:     include/linux/timer*
 F:     kernel/time/*timer*
 
+POWER MANAGEMENT CORE
+M:     "Rafael J. Wysocki" <rjw@rjwysocki.net>
+L:     linux-pm@vger.kernel.org
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
+S:     Supported
+F:     drivers/base/power/
+F:     include/linux/pm.h
+F:     include/linux/pm_*
+F:     include/linux/powercap.h
+F:     drivers/powercap/
+
 POWER SUPPLY CLASS/SUBSYSTEM and DRIVERS
 M:     Sebastian Reichel <sre@kernel.org>
 M:     Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
index 294cfe40388dd582d77d45eac441b15318ac1cde..40beede46e55836898779fc503e5b5380a77551c 100644 (file)
                compatible = "operating-points-v2";
                opp-shared;
 
-               opp00 {
+               opp@200000000 {
                        opp-hz = /bits/ 64 <200000000>;
                        opp-microvolt = <900000>;
                        clock-latency-ns = <200000>;
                };
-               opp01 {
+               opp@300000000 {
                        opp-hz = /bits/ 64 <300000000>;
                        opp-microvolt = <900000>;
                        clock-latency-ns = <200000>;
                };
-               opp02 {
+               opp@400000000 {
                        opp-hz = /bits/ 64 <400000000>;
                        opp-microvolt = <925000>;
                        clock-latency-ns = <200000>;
                };
-               opp03 {
+               opp@500000000 {
                        opp-hz = /bits/ 64 <500000000>;
                        opp-microvolt = <950000>;
                        clock-latency-ns = <200000>;
                };
-               opp04 {
+               opp@600000000 {
                        opp-hz = /bits/ 64 <600000000>;
                        opp-microvolt = <975000>;
                        clock-latency-ns = <200000>;
                };
-               opp05 {
+               opp@700000000 {
                        opp-hz = /bits/ 64 <700000000>;
                        opp-microvolt = <987500>;
                        clock-latency-ns = <200000>;
                };
-               opp06 {
+               opp@800000000 {
                        opp-hz = /bits/ 64 <800000000>;
                        opp-microvolt = <1000000>;
                        clock-latency-ns = <200000>;
                        opp-suspend;
                };
-               opp07 {
+               opp@900000000 {
                        opp-hz = /bits/ 64 <900000000>;
                        opp-microvolt = <1037500>;
                        clock-latency-ns = <200000>;
                };
-               opp08 {
+               opp@1000000000 {
                        opp-hz = /bits/ 64 <1000000000>;
                        opp-microvolt = <1087500>;
                        clock-latency-ns = <200000>;
                };
-               opp09 {
+               opp@1100000000 {
                        opp-hz = /bits/ 64 <1100000000>;
                        opp-microvolt = <1137500>;
                        clock-latency-ns = <200000>;
                };
-               opp10 {
+               opp@1200000000 {
                        opp-hz = /bits/ 64 <1200000000>;
                        opp-microvolt = <1187500>;
                        clock-latency-ns = <200000>;
                };
-               opp11 {
+               opp@1300000000 {
                        opp-hz = /bits/ 64 <1300000000>;
                        opp-microvolt = <1250000>;
                        clock-latency-ns = <200000>;
                };
-               opp12 {
+               opp@1400000000 {
                        opp-hz = /bits/ 64 <1400000000>;
                        opp-microvolt = <1287500>;
                        clock-latency-ns = <200000>;
                };
-               opp13 {
+               opp@1500000000 {
                        opp-hz = /bits/ 64 <1500000000>;
                        opp-microvolt = <1350000>;
                        clock-latency-ns = <200000>;
index 49d1110cff5341954e3d980d003fda4f516138f0..52db8bf7e153b09b4d7532cae4ddff12213f2921 100644 (file)
  *
  */
 
+#include <linux/property.h>
 #include <linux/gpio/machine.h>
 #include <linux/platform_device.h>
-#include <linux/rfkill-gpio.h>
 
 #include "board.h"
 
-static struct rfkill_gpio_platform_data wifi_rfkill_platform_data = {
-       .name   = "wifi_rfkill",
-       .type   = RFKILL_TYPE_WLAN,
+static struct property_entry __initdata wifi_rfkill_prop[] = {
+       PROPERTY_ENTRY_STRING("name", "wifi_rfkill"),
+       PROPERTY_ENTRY_STRING("type", "wlan"),
+       { },
+};
+
+static struct property_set __initdata wifi_rfkill_pset = {
+       .properties = wifi_rfkill_prop,
 };
 
 static struct platform_device wifi_rfkill_device = {
        .name   = "rfkill_gpio",
        .id     = -1,
-       .dev    = {
-               .platform_data = &wifi_rfkill_platform_data,
-       },
 };
 
 static struct gpiod_lookup_table wifi_gpio_lookup = {
@@ -47,6 +49,7 @@ static struct gpiod_lookup_table wifi_gpio_lookup = {
 
 void __init tegra_paz00_wifikill_init(void)
 {
+       platform_device_add_properties(&wifi_rfkill_device, &wifi_rfkill_pset);
        gpiod_add_lookup_table(&wifi_gpio_lookup);
        platform_device_register(&wifi_rfkill_device);
 }
index 3b0c2aa0785733e5d26024a97a0ad63a580e6600..cee411e647ca05fd27f6b1b0d025648ed619001c 100644 (file)
@@ -97,13 +97,11 @@ ftrace_modify_code(unsigned long ip, unsigned char *old_code,
        unsigned char replaced[MCOUNT_INSN_SIZE];
 
        /*
-        * Note: Due to modules and __init, code can
-        *  disappear and change, we need to protect against faulting
-        *  as well as code changing. We do this by using the
-        *  probe_kernel_* functions.
-        *
-        * No real locking needed, this code is run through
-        * kstop_machine, or before SMP starts.
+        * Note:
+        * We are paranoid about modifying text, as if a bug was to happen, it
+        * could cause us to read or write to someplace that could cause harm.
+        * Carefully read and modify the code with probe_kernel_*(), and make
+        * sure what we read is what we expected it to be before modifying it.
         */
 
        if (!do_check)
index ed1d685157c2c30bb6e921f2d4bc412be13c5403..ac8c039b0318fe48929bff8f60ec4f9d58740120 100644 (file)
@@ -54,12 +54,11 @@ static int ftrace_modify_code(unsigned long pc, unsigned char *old_code,
        unsigned char replaced[MCOUNT_INSN_SIZE];
 
        /*
-        * Note: Due to modules and __init, code can
-        *  disappear and change, we need to protect against faulting
-        *  as well as code changing.
-        *
-        * No real locking needed, this code is run through
-        * kstop_machine.
+        * Note:
+        * We are paranoid about modifying text, as if a bug was to happen, it
+        * could cause us to read or write to someplace that could cause harm.
+        * Carefully read and modify the code with probe_kernel_*(), and make
+        * sure what we read is what we expected it to be before modifying it.
         */
 
        /* read the text we want to modify */
index 079d70e6d74b3122adb2f48bebd8056ac4262e4a..38993e09ef03ef371932707058c57bd15dd2d875 100644 (file)
@@ -212,13 +212,11 @@ static int ftrace_modify_code(unsigned long ip, unsigned char *old_code,
        unsigned char replaced[MCOUNT_INSN_SIZE];
 
        /*
-        * Note: Due to modules and __init, code can
-        *  disappear and change, we need to protect against faulting
-        *  as well as code changing. We do this by using the
-        *  probe_kernel_* functions.
-        *
-        * No real locking needed, this code is run through
-        * kstop_machine, or before SMP starts.
+        * Note:
+        * We are paranoid about modifying text, as if a bug was to happen, it
+        * could cause us to read or write to someplace that could cause harm.
+        * Carefully read and modify the code with probe_kernel_*(), and make
+        * sure what we read is what we expected it to be before modifying it.
         */
 
        /* read the text we want to modify */
index 258965d56beb9ccba468ba2bf6b5b99ab17cd798..ccfededfe470b41af1cee5685c3187fca049325f 100644 (file)
@@ -534,9 +534,10 @@ config X86_INTEL_QUARK
 
 config X86_INTEL_LPSS
        bool "Intel Low Power Subsystem Support"
-       depends on ACPI
+       depends on X86 && ACPI
        select COMMON_CLK
        select PINCTRL
+       select IOSF_MBI
        ---help---
          Select to build support for Intel Low Power Subsystem such as
          found on Intel Lynxpoint PCH. Selecting this option enables
index b72ad0faa6c531b91542701dc72f0175158408f4..b41ee164930a0a37a6e02cb64bd2d7e654b92959 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * iosf_mbi.h: Intel OnChip System Fabric MailBox access support
+ * Intel OnChip System Fabric MailBox access support
  */
 
 #ifndef IOSF_MBI_SYMS_H
 #define MBI_MASK_LO            0x000000FF
 #define MBI_ENABLE             0xF0
 
+/* IOSF SB read/write opcodes */
+#define MBI_MMIO_READ          0x00
+#define MBI_MMIO_WRITE         0x01
+#define MBI_CFG_READ           0x04
+#define MBI_CFG_WRITE          0x05
+#define MBI_CR_READ            0x06
+#define MBI_CR_WRITE           0x07
+#define MBI_REG_READ           0x10
+#define MBI_REG_WRITE          0x11
+#define MBI_ESRAM_READ         0x12
+#define MBI_ESRAM_WRITE                0x13
+
 /* Baytrail available units */
 #define BT_MBI_UNIT_AUNIT      0x00
 #define BT_MBI_UNIT_SMC                0x01
 #define BT_MBI_UNIT_SATA       0xA3
 #define BT_MBI_UNIT_PCIE       0xA6
 
-/* Baytrail read/write opcodes */
-#define BT_MBI_AUNIT_READ      0x10
-#define BT_MBI_AUNIT_WRITE     0x11
-#define BT_MBI_SMC_READ                0x10
-#define BT_MBI_SMC_WRITE       0x11
-#define BT_MBI_CPU_READ                0x10
-#define BT_MBI_CPU_WRITE       0x11
-#define BT_MBI_BUNIT_READ      0x10
-#define BT_MBI_BUNIT_WRITE     0x11
-#define BT_MBI_PMC_READ                0x06
-#define BT_MBI_PMC_WRITE       0x07
-#define BT_MBI_GFX_READ                0x00
-#define BT_MBI_GFX_WRITE       0x01
-#define BT_MBI_SMIO_READ       0x06
-#define BT_MBI_SMIO_WRITE      0x07
-#define BT_MBI_USB_READ                0x06
-#define BT_MBI_USB_WRITE       0x07
-#define BT_MBI_SATA_READ       0x00
-#define BT_MBI_SATA_WRITE      0x01
-#define BT_MBI_PCIE_READ       0x00
-#define BT_MBI_PCIE_WRITE      0x01
-
 /* Quark available units */
 #define QRK_MBI_UNIT_HBA       0x00
 #define QRK_MBI_UNIT_HB                0x03
 #define QRK_MBI_UNIT_RMU       0x04
 #define QRK_MBI_UNIT_MM                0x05
-#define QRK_MBI_UNIT_MMESRAM   0x05
 #define QRK_MBI_UNIT_SOC       0x31
 
-/* Quark read/write opcodes */
-#define QRK_MBI_HBA_READ       0x10
-#define QRK_MBI_HBA_WRITE      0x11
-#define QRK_MBI_HB_READ                0x10
-#define QRK_MBI_HB_WRITE       0x11
-#define QRK_MBI_RMU_READ       0x10
-#define QRK_MBI_RMU_WRITE      0x11
-#define QRK_MBI_MM_READ                0x10
-#define QRK_MBI_MM_WRITE       0x11
-#define QRK_MBI_MMESRAM_READ   0x12
-#define QRK_MBI_MMESRAM_WRITE  0x13
-#define QRK_MBI_SOC_READ       0x06
-#define QRK_MBI_SOC_WRITE      0x07
-
 #if IS_ENABLED(CONFIG_IOSF_MBI)
 
 bool iosf_mbi_available(void);
index 311bcf338f07e75a48115ef4edf3df5f748b6940..29408d6d66267c12ce4eab826e38bac3d8367d17 100644 (file)
@@ -105,14 +105,14 @@ ftrace_modify_code_direct(unsigned long ip, unsigned const char *old_code,
 {
        unsigned char replaced[MCOUNT_INSN_SIZE];
 
+       ftrace_expected = old_code;
+
        /*
-        * Note: Due to modules and __init, code can
-        *  disappear and change, we need to protect against faulting
-        *  as well as code changing. We do this by using the
-        *  probe_kernel_* functions.
-        *
-        * No real locking needed, this code is run through
-        * kstop_machine, or before SMP starts.
+        * Note:
+        * We are paranoid about modifying text, as if a bug was to happen, it
+        * could cause us to read or write to someplace that could cause harm.
+        * Carefully read and modify the code with probe_kernel_*(), and make
+        * sure what we read is what we expected it to be before modifying it.
         */
 
        /* read the text we want to modify */
@@ -154,6 +154,8 @@ int ftrace_make_nop(struct module *mod,
        if (addr == MCOUNT_ADDR)
                return ftrace_modify_code_direct(rec->ip, old, new);
 
+       ftrace_expected = NULL;
+
        /* Normal cases use add_brk_on_nop */
        WARN_ONCE(1, "invalid use of ftrace_make_nop");
        return -EINVAL;
@@ -220,6 +222,7 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
                                 unsigned long addr)
 {
        WARN_ON(1);
+       ftrace_expected = NULL;
        return -EINVAL;
 }
 
@@ -314,6 +317,8 @@ static int add_break(unsigned long ip, const char *old)
        if (probe_kernel_read(replaced, (void *)ip, MCOUNT_INSN_SIZE))
                return -EFAULT;
 
+       ftrace_expected = old;
+
        /* Make sure it is what we expect it to be */
        if (memcmp(replaced, old, MCOUNT_INSN_SIZE) != 0)
                return -EINVAL;
@@ -413,6 +418,8 @@ static int remove_breakpoint(struct dyn_ftrace *rec)
                ftrace_addr = ftrace_get_addr_curr(rec);
                nop = ftrace_call_replace(ip, ftrace_addr);
 
+               ftrace_expected = nop;
+
                if (memcmp(&ins[1], &nop[1], MCOUNT_INSN_SIZE - 1) != 0)
                        return -EINVAL;
        }
index 5ca8ead915795f87fc0749c77c881828815b166b..81c769e806140608db9198ed501336cbcfe5605d 100644 (file)
@@ -25,8 +25,6 @@
 #include <asm/cpu_device_id.h>
 #include <asm/iosf_mbi.h>
 
-/* Side band Interface port */
-#define PUNIT_PORT             0x04
 /* Power gate status reg */
 #define PWRGT_STATUS           0x61
 /* Subsystem config/status Video processor */
@@ -85,9 +83,8 @@ static int punit_dev_state_show(struct seq_file *seq_file, void *unused)
 
        seq_puts(seq_file, "\n\nPUNIT NORTH COMPLEX DEVICES :\n");
        while (punit_devp->name) {
-               status = iosf_mbi_read(PUNIT_PORT, BT_MBI_PMC_READ,
-                                      punit_devp->reg,
-                                      &punit_pwr_status);
+               status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
+                                      punit_devp->reg, &punit_pwr_status);
                if (status) {
                        seq_printf(seq_file, "%9s : Read Failed\n",
                                   punit_devp->name);
index 0ee619f9fcb725f73ad13b96c680fe97ad29bef0..c1bdafaac3ca828cec43af9e43d12933e4de7ea9 100644 (file)
@@ -111,23 +111,19 @@ static int imr_read(struct imr_device *idev, u32 imr_id, struct imr_regs *imr)
        u32 reg = imr_id * IMR_NUM_REGS + idev->reg_base;
        int ret;
 
-       ret = iosf_mbi_read(QRK_MBI_UNIT_MM, QRK_MBI_MM_READ,
-                               reg++, &imr->addr_lo);
+       ret = iosf_mbi_read(QRK_MBI_UNIT_MM, MBI_REG_READ, reg++, &imr->addr_lo);
        if (ret)
                return ret;
 
-       ret = iosf_mbi_read(QRK_MBI_UNIT_MM, QRK_MBI_MM_READ,
-                               reg++, &imr->addr_hi);
+       ret = iosf_mbi_read(QRK_MBI_UNIT_MM, MBI_REG_READ, reg++, &imr->addr_hi);
        if (ret)
                return ret;
 
-       ret = iosf_mbi_read(QRK_MBI_UNIT_MM, QRK_MBI_MM_READ,
-                               reg++, &imr->rmask);
+       ret = iosf_mbi_read(QRK_MBI_UNIT_MM, MBI_REG_READ, reg++, &imr->rmask);
        if (ret)
                return ret;
 
-       return iosf_mbi_read(QRK_MBI_UNIT_MM, QRK_MBI_MM_READ,
-                               reg++, &imr->wmask);
+       return iosf_mbi_read(QRK_MBI_UNIT_MM, MBI_REG_READ, reg++, &imr->wmask);
 }
 
 /**
@@ -151,31 +147,27 @@ static int imr_write(struct imr_device *idev, u32 imr_id,
 
        local_irq_save(flags);
 
-       ret = iosf_mbi_write(QRK_MBI_UNIT_MM, QRK_MBI_MM_WRITE, reg++,
-                               imr->addr_lo);
+       ret = iosf_mbi_write(QRK_MBI_UNIT_MM, MBI_REG_WRITE, reg++, imr->addr_lo);
        if (ret)
                goto failed;
 
-       ret = iosf_mbi_write(QRK_MBI_UNIT_MM, QRK_MBI_MM_WRITE,
-                               reg++, imr->addr_hi);
+       ret = iosf_mbi_write(QRK_MBI_UNIT_MM, MBI_REG_WRITE, reg++, imr->addr_hi);
        if (ret)
                goto failed;
 
-       ret = iosf_mbi_write(QRK_MBI_UNIT_MM, QRK_MBI_MM_WRITE,
-                               reg++, imr->rmask);
+       ret = iosf_mbi_write(QRK_MBI_UNIT_MM, MBI_REG_WRITE, reg++, imr->rmask);
        if (ret)
                goto failed;
 
-       ret = iosf_mbi_write(QRK_MBI_UNIT_MM, QRK_MBI_MM_WRITE,
-                               reg++, imr->wmask);
+       ret = iosf_mbi_write(QRK_MBI_UNIT_MM, MBI_REG_WRITE, reg++, imr->wmask);
        if (ret)
                goto failed;
 
        /* Lock bit must be set separately to addr_lo address bits. */
        if (lock) {
                imr->addr_lo |= IMR_LOCK;
-               ret = iosf_mbi_write(QRK_MBI_UNIT_MM, QRK_MBI_MM_WRITE,
-                                       reg - IMR_NUM_REGS, imr->addr_lo);
+               ret = iosf_mbi_write(QRK_MBI_UNIT_MM, MBI_REG_WRITE,
+                                    reg - IMR_NUM_REGS, imr->addr_lo);
                if (ret)
                        goto failed;
        }
index 5eef4cb4f70e6995f2d623268d1f8cd2daab63c2..82b96ee8624c2b2713e981e9d9c4b0aefb9ae811 100644 (file)
@@ -58,14 +58,25 @@ config ACPI_CCA_REQUIRED
        bool
 
 config ACPI_DEBUGGER
-       bool "AML debugger interface (EXPERIMENTAL)"
+       bool "AML debugger interface"
        select ACPI_DEBUG
        help
-         Enable in-kernel debugging of AML facilities: statistics, internal
-         object dump, single step control method execution.
+         Enable in-kernel debugging of AML facilities: statistics,
+         internal object dump, single step control method execution.
          This is still under development, currently enabling this only
          results in the compilation of the ACPICA debugger files.
 
+if ACPI_DEBUGGER
+
+config ACPI_DEBUGGER_USER
+       tristate "Userspace debugger accessiblity"
+       depends on DEBUG_FS
+       help
+         Export /sys/kernel/debug/acpi/acpidbg for userspace utilities
+         to access the debugger functionalities.
+
+endif
+
 config ACPI_SLEEP
        bool
        depends on SUSPEND || HIBERNATION
index 675eaf3371789618cdfb21ead69e121844dc006e..cb648a49543a55a091b7ba756c628d7a076ac428 100644 (file)
@@ -8,13 +8,13 @@ ccflags-$(CONFIG_ACPI_DEBUG)  += -DACPI_DEBUG_OUTPUT
 #
 # ACPI Boot-Time Table Parsing
 #
-obj-y                          += tables.o
+obj-$(CONFIG_ACPI)             += tables.o
 obj-$(CONFIG_X86)              += blacklist.o
 
 #
 # ACPI Core Subsystem (Interpreter)
 #
-obj-y                          += acpi.o \
+obj-$(CONFIG_ACPI)             += acpi.o \
                                        acpica/
 
 # All the builtin files are in the "acpi." module_param namespace.
@@ -66,10 +66,10 @@ obj-$(CONFIG_ACPI_FAN)              += fan.o
 obj-$(CONFIG_ACPI_VIDEO)       += video.o
 obj-$(CONFIG_ACPI_PCI_SLOT)    += pci_slot.o
 obj-$(CONFIG_ACPI_PROCESSOR)   += processor.o
-obj-y                          += container.o
+obj-$(CONFIG_ACPI)             += container.o
 obj-$(CONFIG_ACPI_THERMAL)     += thermal.o
 obj-$(CONFIG_ACPI_NFIT)                += nfit.o
-obj-y                          += acpi_memhotplug.o
+obj-$(CONFIG_ACPI)             += acpi_memhotplug.o
 obj-$(CONFIG_ACPI_HOTPLUG_IOAPIC) += ioapic.o
 obj-$(CONFIG_ACPI_BATTERY)     += battery.o
 obj-$(CONFIG_ACPI_SBS)         += sbshc.o
@@ -79,6 +79,7 @@ obj-$(CONFIG_ACPI_EC_DEBUGFS) += ec_sys.o
 obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o
 obj-$(CONFIG_ACPI_BGRT)                += bgrt.o
 obj-$(CONFIG_ACPI_CPPC_LIB)    += cppc_acpi.o
+obj-$(CONFIG_ACPI_DEBUGGER_USER) += acpi_dbg.o
 
 # processor has its own "processor." module_param namespace
 processor-y                    := processor_driver.o
index a450e7af877c337aec3aff21f0676299b3699f73..d507cf6deda050fde79d3b6237fdbf410407d5d3 100644 (file)
@@ -51,7 +51,7 @@ struct apd_private_data {
        const struct apd_device_desc *dev_desc;
 };
 
-#ifdef CONFIG_X86_AMD_PLATFORM_DEVICE
+#if defined(CONFIG_X86_AMD_PLATFORM_DEVICE) || defined(CONFIG_ARM64)
 #define APD_ADDR(desc) ((unsigned long)&desc)
 
 static int acpi_apd_setup(struct apd_private_data *pdata)
@@ -71,6 +71,7 @@ static int acpi_apd_setup(struct apd_private_data *pdata)
        return 0;
 }
 
+#ifdef CONFIG_X86_AMD_PLATFORM_DEVICE
 static struct apd_device_desc cz_i2c_desc = {
        .setup = acpi_apd_setup,
        .fixed_clk_rate = 133000000,
@@ -80,6 +81,14 @@ static struct apd_device_desc cz_uart_desc = {
        .setup = acpi_apd_setup,
        .fixed_clk_rate = 48000000,
 };
+#endif
+
+#ifdef CONFIG_ARM64
+static struct apd_device_desc xgene_i2c_desc = {
+       .setup = acpi_apd_setup,
+       .fixed_clk_rate = 100000000,
+};
+#endif
 
 #else
 
@@ -132,9 +141,14 @@ static int acpi_apd_create_device(struct acpi_device *adev,
 
 static const struct acpi_device_id acpi_apd_device_ids[] = {
        /* Generic apd devices */
+#ifdef CONFIG_X86_AMD_PLATFORM_DEVICE
        { "AMD0010", APD_ADDR(cz_i2c_desc) },
        { "AMD0020", APD_ADDR(cz_uart_desc) },
        { "AMD0030", },
+#endif
+#ifdef CONFIG_ARM64
+       { "APMC0D0F", APD_ADDR(xgene_i2c_desc) },
+#endif
        { }
 };
 
diff --git a/drivers/acpi/acpi_dbg.c b/drivers/acpi/acpi_dbg.c
new file mode 100644 (file)
index 0000000..15e4604
--- /dev/null
@@ -0,0 +1,804 @@
+/*
+ * ACPI AML interfacing support
+ *
+ * Copyright (C) 2015, Intel Corporation
+ * Authors: Lv Zheng <lv.zheng@intel.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.
+ */
+
+/* #define DEBUG */
+#define pr_fmt(fmt) "ACPI : AML: " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/wait.h>
+#include <linux/poll.h>
+#include <linux/sched.h>
+#include <linux/kthread.h>
+#include <linux/proc_fs.h>
+#include <linux/debugfs.h>
+#include <linux/circ_buf.h>
+#include <linux/acpi.h>
+#include "internal.h"
+
+#define ACPI_AML_BUF_ALIGN     (sizeof (acpi_size))
+#define ACPI_AML_BUF_SIZE      PAGE_SIZE
+
+#define circ_count(circ) \
+       (CIRC_CNT((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
+#define circ_count_to_end(circ) \
+       (CIRC_CNT_TO_END((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
+#define circ_space(circ) \
+       (CIRC_SPACE((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
+#define circ_space_to_end(circ) \
+       (CIRC_SPACE_TO_END((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
+
+#define ACPI_AML_OPENED                0x0001
+#define ACPI_AML_CLOSED                0x0002
+#define ACPI_AML_IN_USER       0x0004 /* user space is writing cmd */
+#define ACPI_AML_IN_KERN       0x0008 /* kernel space is reading cmd */
+#define ACPI_AML_OUT_USER      0x0010 /* user space is reading log */
+#define ACPI_AML_OUT_KERN      0x0020 /* kernel space is writing log */
+#define ACPI_AML_USER          (ACPI_AML_IN_USER | ACPI_AML_OUT_USER)
+#define ACPI_AML_KERN          (ACPI_AML_IN_KERN | ACPI_AML_OUT_KERN)
+#define ACPI_AML_BUSY          (ACPI_AML_USER | ACPI_AML_KERN)
+#define ACPI_AML_OPEN          (ACPI_AML_OPENED | ACPI_AML_CLOSED)
+
+struct acpi_aml_io {
+       wait_queue_head_t wait;
+       unsigned long flags;
+       unsigned long users;
+       struct mutex lock;
+       struct task_struct *thread;
+       char out_buf[ACPI_AML_BUF_SIZE] __aligned(ACPI_AML_BUF_ALIGN);
+       struct circ_buf out_crc;
+       char in_buf[ACPI_AML_BUF_SIZE] __aligned(ACPI_AML_BUF_ALIGN);
+       struct circ_buf in_crc;
+       acpi_osd_exec_callback function;
+       void *context;
+       unsigned long usages;
+};
+
+static struct acpi_aml_io acpi_aml_io;
+static bool acpi_aml_initialized;
+static struct file *acpi_aml_active_reader;
+static struct dentry *acpi_aml_dentry;
+
+static inline bool __acpi_aml_running(void)
+{
+       return acpi_aml_io.thread ? true : false;
+}
+
+static inline bool __acpi_aml_access_ok(unsigned long flag)
+{
+       /*
+        * The debugger interface is in opened state (OPENED && !CLOSED),
+        * then it is allowed to access the debugger buffers from either
+        * user space or the kernel space.
+        * In addition, for the kernel space, only the debugger thread
+        * (thread ID matched) is allowed to access.
+        */
+       if (!(acpi_aml_io.flags & ACPI_AML_OPENED) ||
+           (acpi_aml_io.flags & ACPI_AML_CLOSED) ||
+           !__acpi_aml_running())
+               return false;
+       if ((flag & ACPI_AML_KERN) &&
+           current != acpi_aml_io.thread)
+               return false;
+       return true;
+}
+
+static inline bool __acpi_aml_readable(struct circ_buf *circ, unsigned long flag)
+{
+       /*
+        * Another read is not in progress and there is data in buffer
+        * available for read.
+        */
+       if (!(acpi_aml_io.flags & flag) && circ_count(circ))
+               return true;
+       return false;
+}
+
+static inline bool __acpi_aml_writable(struct circ_buf *circ, unsigned long flag)
+{
+       /*
+        * Another write is not in progress and there is buffer space
+        * available for write.
+        */
+       if (!(acpi_aml_io.flags & flag) && circ_space(circ))
+               return true;
+       return false;
+}
+
+static inline bool __acpi_aml_busy(void)
+{
+       if (acpi_aml_io.flags & ACPI_AML_BUSY)
+               return true;
+       return false;
+}
+
+static inline bool __acpi_aml_opened(void)
+{
+       if (acpi_aml_io.flags & ACPI_AML_OPEN)
+               return true;
+       return false;
+}
+
+static inline bool __acpi_aml_used(void)
+{
+       return acpi_aml_io.usages ? true : false;
+}
+
+static inline bool acpi_aml_running(void)
+{
+       bool ret;
+
+       mutex_lock(&acpi_aml_io.lock);
+       ret = __acpi_aml_running();
+       mutex_unlock(&acpi_aml_io.lock);
+       return ret;
+}
+
+static bool acpi_aml_busy(void)
+{
+       bool ret;
+
+       mutex_lock(&acpi_aml_io.lock);
+       ret = __acpi_aml_busy();
+       mutex_unlock(&acpi_aml_io.lock);
+       return ret;
+}
+
+static bool acpi_aml_used(void)
+{
+       bool ret;
+
+       /*
+        * The usage count is prepared to avoid race conditions between the
+        * starts and the stops of the debugger thread.
+        */
+       mutex_lock(&acpi_aml_io.lock);
+       ret = __acpi_aml_used();
+       mutex_unlock(&acpi_aml_io.lock);
+       return ret;
+}
+
+static bool acpi_aml_kern_readable(void)
+{
+       bool ret;
+
+       mutex_lock(&acpi_aml_io.lock);
+       ret = !__acpi_aml_access_ok(ACPI_AML_IN_KERN) ||
+             __acpi_aml_readable(&acpi_aml_io.in_crc, ACPI_AML_IN_KERN);
+       mutex_unlock(&acpi_aml_io.lock);
+       return ret;
+}
+
+static bool acpi_aml_kern_writable(void)
+{
+       bool ret;
+
+       mutex_lock(&acpi_aml_io.lock);
+       ret = !__acpi_aml_access_ok(ACPI_AML_OUT_KERN) ||
+             __acpi_aml_writable(&acpi_aml_io.out_crc, ACPI_AML_OUT_KERN);
+       mutex_unlock(&acpi_aml_io.lock);
+       return ret;
+}
+
+static bool acpi_aml_user_readable(void)
+{
+       bool ret;
+
+       mutex_lock(&acpi_aml_io.lock);
+       ret = !__acpi_aml_access_ok(ACPI_AML_OUT_USER) ||
+             __acpi_aml_readable(&acpi_aml_io.out_crc, ACPI_AML_OUT_USER);
+       mutex_unlock(&acpi_aml_io.lock);
+       return ret;
+}
+
+static bool acpi_aml_user_writable(void)
+{
+       bool ret;
+
+       mutex_lock(&acpi_aml_io.lock);
+       ret = !__acpi_aml_access_ok(ACPI_AML_IN_USER) ||
+             __acpi_aml_writable(&acpi_aml_io.in_crc, ACPI_AML_IN_USER);
+       mutex_unlock(&acpi_aml_io.lock);
+       return ret;
+}
+
+static int acpi_aml_lock_write(struct circ_buf *circ, unsigned long flag)
+{
+       int ret = 0;
+
+       mutex_lock(&acpi_aml_io.lock);
+       if (!__acpi_aml_access_ok(flag)) {
+               ret = -EFAULT;
+               goto out;
+       }
+       if (!__acpi_aml_writable(circ, flag)) {
+               ret = -EAGAIN;
+               goto out;
+       }
+       acpi_aml_io.flags |= flag;
+out:
+       mutex_unlock(&acpi_aml_io.lock);
+       return ret;
+}
+
+static int acpi_aml_lock_read(struct circ_buf *circ, unsigned long flag)
+{
+       int ret = 0;
+
+       mutex_lock(&acpi_aml_io.lock);
+       if (!__acpi_aml_access_ok(flag)) {
+               ret = -EFAULT;
+               goto out;
+       }
+       if (!__acpi_aml_readable(circ, flag)) {
+               ret = -EAGAIN;
+               goto out;
+       }
+       acpi_aml_io.flags |= flag;
+out:
+       mutex_unlock(&acpi_aml_io.lock);
+       return ret;
+}
+
+static void acpi_aml_unlock_fifo(unsigned long flag, bool wakeup)
+{
+       mutex_lock(&acpi_aml_io.lock);
+       acpi_aml_io.flags &= ~flag;
+       if (wakeup)
+               wake_up_interruptible(&acpi_aml_io.wait);
+       mutex_unlock(&acpi_aml_io.lock);
+}
+
+static int acpi_aml_write_kern(const char *buf, int len)
+{
+       int ret;
+       struct circ_buf *crc = &acpi_aml_io.out_crc;
+       int n;
+       char *p;
+
+       ret = acpi_aml_lock_write(crc, ACPI_AML_OUT_KERN);
+       if (IS_ERR_VALUE(ret))
+               return ret;
+       /* sync tail before inserting logs */
+       smp_mb();
+       p = &crc->buf[crc->head];
+       n = min(len, circ_space_to_end(crc));
+       memcpy(p, buf, n);
+       /* sync head after inserting logs */
+       smp_wmb();
+       crc->head = (crc->head + n) & (ACPI_AML_BUF_SIZE - 1);
+       acpi_aml_unlock_fifo(ACPI_AML_OUT_KERN, true);
+       return n;
+}
+
+static int acpi_aml_readb_kern(void)
+{
+       int ret;
+       struct circ_buf *crc = &acpi_aml_io.in_crc;
+       char *p;
+
+       ret = acpi_aml_lock_read(crc, ACPI_AML_IN_KERN);
+       if (IS_ERR_VALUE(ret))
+               return ret;
+       /* sync head before removing cmds */
+       smp_rmb();
+       p = &crc->buf[crc->tail];
+       ret = (int)*p;
+       /* sync tail before inserting cmds */
+       smp_mb();
+       crc->tail = (crc->tail + 1) & (ACPI_AML_BUF_SIZE - 1);
+       acpi_aml_unlock_fifo(ACPI_AML_IN_KERN, true);
+       return ret;
+}
+
+/*
+ * acpi_aml_write_log() - Capture debugger output
+ * @msg: the debugger output
+ *
+ * This function should be used to implement acpi_os_printf() to filter out
+ * the debugger output and store the output into the debugger interface
+ * buffer. Return the size of stored logs or errno.
+ */
+static ssize_t acpi_aml_write_log(const char *msg)
+{
+       int ret = 0;
+       int count = 0, size = 0;
+
+       if (!acpi_aml_initialized)
+               return -ENODEV;
+       if (msg)
+               count = strlen(msg);
+       while (count > 0) {
+again:
+               ret = acpi_aml_write_kern(msg + size, count);
+               if (ret == -EAGAIN) {
+                       ret = wait_event_interruptible(acpi_aml_io.wait,
+                               acpi_aml_kern_writable());
+                       /*
+                        * We need to retry when the condition
+                        * becomes true.
+                        */
+                       if (ret == 0)
+                               goto again;
+                       break;
+               }
+               if (IS_ERR_VALUE(ret))
+                       break;
+               size += ret;
+               count -= ret;
+       }
+       return size > 0 ? size : ret;
+}
+
+/*
+ * acpi_aml_read_cmd() - Capture debugger input
+ * @msg: the debugger input
+ * @size: the size of the debugger input
+ *
+ * This function should be used to implement acpi_os_get_line() to capture
+ * the debugger input commands and store the input commands into the
+ * debugger interface buffer. Return the size of stored commands or errno.
+ */
+static ssize_t acpi_aml_read_cmd(char *msg, size_t count)
+{
+       int ret = 0;
+       int size = 0;
+
+       /*
+        * This is ensured by the running fact of the debugger thread
+        * unless a bug is introduced.
+        */
+       BUG_ON(!acpi_aml_initialized);
+       while (count > 0) {
+again:
+               /*
+                * Check each input byte to find the end of the command.
+                */
+               ret = acpi_aml_readb_kern();
+               if (ret == -EAGAIN) {
+                       ret = wait_event_interruptible(acpi_aml_io.wait,
+                               acpi_aml_kern_readable());
+                       /*
+                        * We need to retry when the condition becomes
+                        * true.
+                        */
+                       if (ret == 0)
+                               goto again;
+               }
+               if (IS_ERR_VALUE(ret))
+                       break;
+               *(msg + size) = (char)ret;
+               size++;
+               count--;
+               if (ret == '\n') {
+                       /*
+                        * acpi_os_get_line() requires a zero terminated command
+                        * string.
+                        */
+                       *(msg + size - 1) = '\0';
+                       break;
+               }
+       }
+       return size > 0 ? size : ret;
+}
+
+static int acpi_aml_thread(void *unsed)
+{
+       acpi_osd_exec_callback function = NULL;
+       void *context;
+
+       mutex_lock(&acpi_aml_io.lock);
+       if (acpi_aml_io.function) {
+               acpi_aml_io.usages++;
+               function = acpi_aml_io.function;
+               context = acpi_aml_io.context;
+       }
+       mutex_unlock(&acpi_aml_io.lock);
+
+       if (function)
+               function(context);
+
+       mutex_lock(&acpi_aml_io.lock);
+       acpi_aml_io.usages--;
+       if (!__acpi_aml_used()) {
+               acpi_aml_io.thread = NULL;
+               wake_up(&acpi_aml_io.wait);
+       }
+       mutex_unlock(&acpi_aml_io.lock);
+
+       return 0;
+}
+
+/*
+ * acpi_aml_create_thread() - Create AML debugger thread
+ * @function: the debugger thread callback
+ * @context: the context to be passed to the debugger thread
+ *
+ * This function should be used to implement acpi_os_execute() which is
+ * used by the ACPICA debugger to create the debugger thread.
+ */
+static int acpi_aml_create_thread(acpi_osd_exec_callback function, void *context)
+{
+       struct task_struct *t;
+
+       mutex_lock(&acpi_aml_io.lock);
+       acpi_aml_io.function = function;
+       acpi_aml_io.context = context;
+       mutex_unlock(&acpi_aml_io.lock);
+
+       t = kthread_create(acpi_aml_thread, NULL, "aml");
+       if (IS_ERR(t)) {
+               pr_err("Failed to create AML debugger thread.\n");
+               return PTR_ERR(t);
+       }
+
+       mutex_lock(&acpi_aml_io.lock);
+       acpi_aml_io.thread = t;
+       acpi_set_debugger_thread_id((acpi_thread_id)(unsigned long)t);
+       wake_up_process(t);
+       mutex_unlock(&acpi_aml_io.lock);
+       return 0;
+}
+
+static int acpi_aml_wait_command_ready(bool single_step,
+                                      char *buffer, size_t length)
+{
+       acpi_status status;
+
+       if (single_step)
+               acpi_os_printf("\n%1c ", ACPI_DEBUGGER_EXECUTE_PROMPT);
+       else
+               acpi_os_printf("\n%1c ", ACPI_DEBUGGER_COMMAND_PROMPT);
+
+       status = acpi_os_get_line(buffer, length, NULL);
+       if (ACPI_FAILURE(status))
+               return -EINVAL;
+       return 0;
+}
+
+static int acpi_aml_notify_command_complete(void)
+{
+       return 0;
+}
+
+static int acpi_aml_open(struct inode *inode, struct file *file)
+{
+       int ret = 0;
+       acpi_status status;
+
+       mutex_lock(&acpi_aml_io.lock);
+       /*
+        * The debugger interface is being closed, no new user is allowed
+        * during this period.
+        */
+       if (acpi_aml_io.flags & ACPI_AML_CLOSED) {
+               ret = -EBUSY;
+               goto err_lock;
+       }
+       if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
+               /*
+                * Only one reader is allowed to initiate the debugger
+                * thread.
+                */
+               if (acpi_aml_active_reader) {
+                       ret = -EBUSY;
+                       goto err_lock;
+               } else {
+                       pr_debug("Opening debugger reader.\n");
+                       acpi_aml_active_reader = file;
+               }
+       } else {
+               /*
+                * No writer is allowed unless the debugger thread is
+                * ready.
+                */
+               if (!(acpi_aml_io.flags & ACPI_AML_OPENED)) {
+                       ret = -ENODEV;
+                       goto err_lock;
+               }
+       }
+       if (acpi_aml_active_reader == file) {
+               pr_debug("Opening debugger interface.\n");
+               mutex_unlock(&acpi_aml_io.lock);
+
+               pr_debug("Initializing debugger thread.\n");
+               status = acpi_initialize_debugger();
+               if (ACPI_FAILURE(status)) {
+                       pr_err("Failed to initialize debugger.\n");
+                       ret = -EINVAL;
+                       goto err_exit;
+               }
+               pr_debug("Debugger thread initialized.\n");
+
+               mutex_lock(&acpi_aml_io.lock);
+               acpi_aml_io.flags |= ACPI_AML_OPENED;
+               acpi_aml_io.out_crc.head = acpi_aml_io.out_crc.tail = 0;
+               acpi_aml_io.in_crc.head = acpi_aml_io.in_crc.tail = 0;
+               pr_debug("Debugger interface opened.\n");
+       }
+       acpi_aml_io.users++;
+err_lock:
+       if (IS_ERR_VALUE(ret)) {
+               if (acpi_aml_active_reader == file)
+                       acpi_aml_active_reader = NULL;
+       }
+       mutex_unlock(&acpi_aml_io.lock);
+err_exit:
+       return ret;
+}
+
+static int acpi_aml_release(struct inode *inode, struct file *file)
+{
+       mutex_lock(&acpi_aml_io.lock);
+       acpi_aml_io.users--;
+       if (file == acpi_aml_active_reader) {
+               pr_debug("Closing debugger reader.\n");
+               acpi_aml_active_reader = NULL;
+
+               pr_debug("Closing debugger interface.\n");
+               acpi_aml_io.flags |= ACPI_AML_CLOSED;
+
+               /*
+                * Wake up all user space/kernel space blocked
+                * readers/writers.
+                */
+               wake_up_interruptible(&acpi_aml_io.wait);
+               mutex_unlock(&acpi_aml_io.lock);
+               /*
+                * Wait all user space/kernel space readers/writers to
+                * stop so that ACPICA command loop of the debugger thread
+                * should fail all its command line reads after this point.
+                */
+               wait_event(acpi_aml_io.wait, !acpi_aml_busy());
+
+               /*
+                * Then we try to terminate the debugger thread if it is
+                * not terminated.
+                */
+               pr_debug("Terminating debugger thread.\n");
+               acpi_terminate_debugger();
+               wait_event(acpi_aml_io.wait, !acpi_aml_used());
+               pr_debug("Debugger thread terminated.\n");
+
+               mutex_lock(&acpi_aml_io.lock);
+               acpi_aml_io.flags &= ~ACPI_AML_OPENED;
+       }
+       if (acpi_aml_io.users == 0) {
+               pr_debug("Debugger interface closed.\n");
+               acpi_aml_io.flags &= ~ACPI_AML_CLOSED;
+       }
+       mutex_unlock(&acpi_aml_io.lock);
+       return 0;
+}
+
+static int acpi_aml_read_user(char __user *buf, int len)
+{
+       int ret;
+       struct circ_buf *crc = &acpi_aml_io.out_crc;
+       int n;
+       char *p;
+
+       ret = acpi_aml_lock_read(crc, ACPI_AML_OUT_USER);
+       if (IS_ERR_VALUE(ret))
+               return ret;
+       /* sync head before removing logs */
+       smp_rmb();
+       p = &crc->buf[crc->tail];
+       n = min(len, circ_count_to_end(crc));
+       if (copy_to_user(buf, p, n)) {
+               ret = -EFAULT;
+               goto out;
+       }
+       /* sync tail after removing logs */
+       smp_mb();
+       crc->tail = (crc->tail + n) & (ACPI_AML_BUF_SIZE - 1);
+       ret = n;
+out:
+       acpi_aml_unlock_fifo(ACPI_AML_OUT_USER, !IS_ERR_VALUE(ret));
+       return ret;
+}
+
+static ssize_t acpi_aml_read(struct file *file, char __user *buf,
+                            size_t count, loff_t *ppos)
+{
+       int ret = 0;
+       int size = 0;
+
+       if (!count)
+               return 0;
+       if (!access_ok(VERIFY_WRITE, buf, count))
+               return -EFAULT;
+
+       while (count > 0) {
+again:
+               ret = acpi_aml_read_user(buf + size, count);
+               if (ret == -EAGAIN) {
+                       if (file->f_flags & O_NONBLOCK)
+                               break;
+                       else {
+                               ret = wait_event_interruptible(acpi_aml_io.wait,
+                                       acpi_aml_user_readable());
+                               /*
+                                * We need to retry when the condition
+                                * becomes true.
+                                */
+                               if (ret == 0)
+                                       goto again;
+                       }
+               }
+               if (IS_ERR_VALUE(ret)) {
+                       if (!acpi_aml_running())
+                               ret = 0;
+                       break;
+               }
+               if (ret) {
+                       size += ret;
+                       count -= ret;
+                       *ppos += ret;
+                       break;
+               }
+       }
+       return size > 0 ? size : ret;
+}
+
+static int acpi_aml_write_user(const char __user *buf, int len)
+{
+       int ret;
+       struct circ_buf *crc = &acpi_aml_io.in_crc;
+       int n;
+       char *p;
+
+       ret = acpi_aml_lock_write(crc, ACPI_AML_IN_USER);
+       if (IS_ERR_VALUE(ret))
+               return ret;
+       /* sync tail before inserting cmds */
+       smp_mb();
+       p = &crc->buf[crc->head];
+       n = min(len, circ_space_to_end(crc));
+       if (copy_from_user(p, buf, n)) {
+               ret = -EFAULT;
+               goto out;
+       }
+       /* sync head after inserting cmds */
+       smp_wmb();
+       crc->head = (crc->head + n) & (ACPI_AML_BUF_SIZE - 1);
+       ret = n;
+out:
+       acpi_aml_unlock_fifo(ACPI_AML_IN_USER, !IS_ERR_VALUE(ret));
+       return n;
+}
+
+static ssize_t acpi_aml_write(struct file *file, const char __user *buf,
+                             size_t count, loff_t *ppos)
+{
+       int ret = 0;
+       int size = 0;
+
+       if (!count)
+               return 0;
+       if (!access_ok(VERIFY_READ, buf, count))
+               return -EFAULT;
+
+       while (count > 0) {
+again:
+               ret = acpi_aml_write_user(buf + size, count);
+               if (ret == -EAGAIN) {
+                       if (file->f_flags & O_NONBLOCK)
+                               break;
+                       else {
+                               ret = wait_event_interruptible(acpi_aml_io.wait,
+                                       acpi_aml_user_writable());
+                               /*
+                                * We need to retry when the condition
+                                * becomes true.
+                                */
+                               if (ret == 0)
+                                       goto again;
+                       }
+               }
+               if (IS_ERR_VALUE(ret)) {
+                       if (!acpi_aml_running())
+                               ret = 0;
+                       break;
+               }
+               if (ret) {
+                       size += ret;
+                       count -= ret;
+                       *ppos += ret;
+               }
+       }
+       return size > 0 ? size : ret;
+}
+
+static unsigned int acpi_aml_poll(struct file *file, poll_table *wait)
+{
+       int masks = 0;
+
+       poll_wait(file, &acpi_aml_io.wait, wait);
+       if (acpi_aml_user_readable())
+               masks |= POLLIN | POLLRDNORM;
+       if (acpi_aml_user_writable())
+               masks |= POLLOUT | POLLWRNORM;
+
+       return masks;
+}
+
+static const struct file_operations acpi_aml_operations = {
+       .read           = acpi_aml_read,
+       .write          = acpi_aml_write,
+       .poll           = acpi_aml_poll,
+       .open           = acpi_aml_open,
+       .release        = acpi_aml_release,
+       .llseek         = generic_file_llseek,
+};
+
+static const struct acpi_debugger_ops acpi_aml_debugger = {
+       .create_thread           = acpi_aml_create_thread,
+       .read_cmd                = acpi_aml_read_cmd,
+       .write_log               = acpi_aml_write_log,
+       .wait_command_ready      = acpi_aml_wait_command_ready,
+       .notify_command_complete = acpi_aml_notify_command_complete,
+};
+
+int __init acpi_aml_init(void)
+{
+       int ret = 0;
+
+       if (!acpi_debugfs_dir) {
+               ret = -ENOENT;
+               goto err_exit;
+       }
+
+       /* Initialize AML IO interface */
+       mutex_init(&acpi_aml_io.lock);
+       init_waitqueue_head(&acpi_aml_io.wait);
+       acpi_aml_io.out_crc.buf = acpi_aml_io.out_buf;
+       acpi_aml_io.in_crc.buf = acpi_aml_io.in_buf;
+       acpi_aml_dentry = debugfs_create_file("acpidbg",
+                                             S_IFREG | S_IRUGO | S_IWUSR,
+                                             acpi_debugfs_dir, NULL,
+                                             &acpi_aml_operations);
+       if (acpi_aml_dentry == NULL) {
+               ret = -ENODEV;
+               goto err_exit;
+       }
+       ret = acpi_register_debugger(THIS_MODULE, &acpi_aml_debugger);
+       if (ret)
+               goto err_fs;
+       acpi_aml_initialized = true;
+
+err_fs:
+       if (ret) {
+               debugfs_remove(acpi_aml_dentry);
+               acpi_aml_dentry = NULL;
+       }
+err_exit:
+       return ret;
+}
+
+void __exit acpi_aml_exit(void)
+{
+       if (acpi_aml_initialized) {
+               acpi_unregister_debugger(&acpi_aml_debugger);
+               if (acpi_aml_dentry) {
+                       debugfs_remove(acpi_aml_dentry);
+                       acpi_aml_dentry = NULL;
+               }
+               acpi_aml_initialized = false;
+       }
+}
+
+module_init(acpi_aml_init);
+module_exit(acpi_aml_exit);
+
+MODULE_AUTHOR("Lv Zheng");
+MODULE_DESCRIPTION("ACPI debugger userspace IO driver");
+MODULE_LICENSE("GPL");
index f9e0d09f7c66cf6bebfdaab992b3b1780b563766..047281a6ae11f175c67d7d2035fceed702bb78e5 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/clk-provider.h>
 #include <linux/err.h>
 #include <linux/io.h>
+#include <linux/mutex.h>
 #include <linux/platform_device.h>
 #include <linux/platform_data/clk-lpss.h>
 #include <linux/pm_runtime.h>
@@ -26,6 +27,10 @@ ACPI_MODULE_NAME("acpi_lpss");
 
 #ifdef CONFIG_X86_INTEL_LPSS
 
+#include <asm/cpu_device_id.h>
+#include <asm/iosf_mbi.h>
+#include <asm/pmc_atom.h>
+
 #define LPSS_ADDR(desc) ((unsigned long)&desc)
 
 #define LPSS_CLK_SIZE  0x04
@@ -71,7 +76,7 @@ struct lpss_device_desc {
        void (*setup)(struct lpss_private_data *pdata);
 };
 
-static struct lpss_device_desc lpss_dma_desc = {
+static const struct lpss_device_desc lpss_dma_desc = {
        .flags = LPSS_CLK,
 };
 
@@ -84,6 +89,23 @@ struct lpss_private_data {
        u32 prv_reg_ctx[LPSS_PRV_REG_COUNT];
 };
 
+/* LPSS run time quirks */
+static unsigned int lpss_quirks;
+
+/*
+ * LPSS_QUIRK_ALWAYS_POWER_ON: override power state for LPSS DMA device.
+ *
+ * The LPSS DMA controller has neither _PS0 nor _PS3 method. Moreover
+ * it can be powered off automatically whenever the last LPSS device goes down.
+ * In case of no power any access to the DMA controller will hang the system.
+ * The behaviour is reproduced on some HP laptops based on Intel BayTrail as
+ * well as on ASuS T100TA transformer.
+ *
+ * This quirk overrides power state of entire LPSS island to keep DMA powered
+ * on whenever we have at least one other device in use.
+ */
+#define LPSS_QUIRK_ALWAYS_POWER_ON     BIT(0)
+
 /* UART Component Parameter Register */
 #define LPSS_UART_CPR                  0xF4
 #define LPSS_UART_CPR_AFCE             BIT(4)
@@ -196,13 +218,21 @@ static const struct lpss_device_desc bsw_i2c_dev_desc = {
        .setup = byt_i2c_setup,
 };
 
-static struct lpss_device_desc bsw_spi_dev_desc = {
+static const struct lpss_device_desc bsw_spi_dev_desc = {
        .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX
                        | LPSS_NO_D3_DELAY,
        .prv_offset = 0x400,
        .setup = lpss_deassert_reset,
 };
 
+#define ICPU(model)    { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, }
+
+static const struct x86_cpu_id lpss_cpu_ids[] = {
+       ICPU(0x37),     /* Valleyview, Bay Trail */
+       ICPU(0x4c),     /* Braswell, Cherry Trail */
+       {}
+};
+
 #else
 
 #define LPSS_ADDR(desc) (0UL)
@@ -574,6 +604,17 @@ static void acpi_lpss_restore_ctx(struct device *dev,
 {
        unsigned int i;
 
+       for (i = 0; i < LPSS_PRV_REG_COUNT; i++) {
+               unsigned long offset = i * sizeof(u32);
+
+               __lpss_reg_write(pdata->prv_reg_ctx[i], pdata, offset);
+               dev_dbg(dev, "restoring 0x%08x to LPSS reg at offset 0x%02lx\n",
+                       pdata->prv_reg_ctx[i], offset);
+       }
+}
+
+static void acpi_lpss_d3_to_d0_delay(struct lpss_private_data *pdata)
+{
        /*
         * The following delay is needed or the subsequent write operations may
         * fail. The LPSS devices are actually PCI devices and the PCI spec
@@ -586,14 +627,34 @@ static void acpi_lpss_restore_ctx(struct device *dev,
                delay = 0;
 
        msleep(delay);
+}
 
-       for (i = 0; i < LPSS_PRV_REG_COUNT; i++) {
-               unsigned long offset = i * sizeof(u32);
+static int acpi_lpss_activate(struct device *dev)
+{
+       struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev));
+       int ret;
 
-               __lpss_reg_write(pdata->prv_reg_ctx[i], pdata, offset);
-               dev_dbg(dev, "restoring 0x%08x to LPSS reg at offset 0x%02lx\n",
-                       pdata->prv_reg_ctx[i], offset);
-       }
+       ret = acpi_dev_runtime_resume(dev);
+       if (ret)
+               return ret;
+
+       acpi_lpss_d3_to_d0_delay(pdata);
+
+       /*
+        * This is called only on ->probe() stage where a device is either in
+        * known state defined by BIOS or most likely powered off. Due to this
+        * we have to deassert reset line to be sure that ->probe() will
+        * recognize the device.
+        */
+       if (pdata->dev_desc->flags & LPSS_SAVE_CTX)
+               lpss_deassert_reset(pdata);
+
+       return 0;
+}
+
+static void acpi_lpss_dismiss(struct device *dev)
+{
+       acpi_dev_runtime_suspend(dev);
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -621,6 +682,8 @@ static int acpi_lpss_resume_early(struct device *dev)
        if (ret)
                return ret;
 
+       acpi_lpss_d3_to_d0_delay(pdata);
+
        if (pdata->dev_desc->flags & LPSS_SAVE_CTX)
                acpi_lpss_restore_ctx(dev, pdata);
 
@@ -628,6 +691,89 @@ static int acpi_lpss_resume_early(struct device *dev)
 }
 #endif /* CONFIG_PM_SLEEP */
 
+/* IOSF SB for LPSS island */
+#define LPSS_IOSF_UNIT_LPIOEP          0xA0
+#define LPSS_IOSF_UNIT_LPIO1           0xAB
+#define LPSS_IOSF_UNIT_LPIO2           0xAC
+
+#define LPSS_IOSF_PMCSR                        0x84
+#define LPSS_PMCSR_D0                  0
+#define LPSS_PMCSR_D3hot               3
+#define LPSS_PMCSR_Dx_MASK             GENMASK(1, 0)
+
+#define LPSS_IOSF_GPIODEF0             0x154
+#define LPSS_GPIODEF0_DMA1_D3          BIT(2)
+#define LPSS_GPIODEF0_DMA2_D3          BIT(3)
+#define LPSS_GPIODEF0_DMA_D3_MASK      GENMASK(3, 2)
+
+static DEFINE_MUTEX(lpss_iosf_mutex);
+
+static void lpss_iosf_enter_d3_state(void)
+{
+       u32 value1 = 0;
+       u32 mask1 = LPSS_GPIODEF0_DMA_D3_MASK;
+       u32 value2 = LPSS_PMCSR_D3hot;
+       u32 mask2 = LPSS_PMCSR_Dx_MASK;
+       /*
+        * PMC provides an information about actual status of the LPSS devices.
+        * Here we read the values related to LPSS power island, i.e. LPSS
+        * devices, excluding both LPSS DMA controllers, along with SCC domain.
+        */
+       u32 func_dis, d3_sts_0, pmc_status, pmc_mask = 0xfe000ffe;
+       int ret;
+
+       ret = pmc_atom_read(PMC_FUNC_DIS, &func_dis);
+       if (ret)
+               return;
+
+       mutex_lock(&lpss_iosf_mutex);
+
+       ret = pmc_atom_read(PMC_D3_STS_0, &d3_sts_0);
+       if (ret)
+               goto exit;
+
+       /*
+        * Get the status of entire LPSS power island per device basis.
+        * Shutdown both LPSS DMA controllers if and only if all other devices
+        * are already in D3hot.
+        */
+       pmc_status = (~(d3_sts_0 | func_dis)) & pmc_mask;
+       if (pmc_status)
+               goto exit;
+
+       iosf_mbi_modify(LPSS_IOSF_UNIT_LPIO1, MBI_CFG_WRITE,
+                       LPSS_IOSF_PMCSR, value2, mask2);
+
+       iosf_mbi_modify(LPSS_IOSF_UNIT_LPIO2, MBI_CFG_WRITE,
+                       LPSS_IOSF_PMCSR, value2, mask2);
+
+       iosf_mbi_modify(LPSS_IOSF_UNIT_LPIOEP, MBI_CR_WRITE,
+                       LPSS_IOSF_GPIODEF0, value1, mask1);
+exit:
+       mutex_unlock(&lpss_iosf_mutex);
+}
+
+static void lpss_iosf_exit_d3_state(void)
+{
+       u32 value1 = LPSS_GPIODEF0_DMA1_D3 | LPSS_GPIODEF0_DMA2_D3;
+       u32 mask1 = LPSS_GPIODEF0_DMA_D3_MASK;
+       u32 value2 = LPSS_PMCSR_D0;
+       u32 mask2 = LPSS_PMCSR_Dx_MASK;
+
+       mutex_lock(&lpss_iosf_mutex);
+
+       iosf_mbi_modify(LPSS_IOSF_UNIT_LPIOEP, MBI_CR_WRITE,
+                       LPSS_IOSF_GPIODEF0, value1, mask1);
+
+       iosf_mbi_modify(LPSS_IOSF_UNIT_LPIO2, MBI_CFG_WRITE,
+                       LPSS_IOSF_PMCSR, value2, mask2);
+
+       iosf_mbi_modify(LPSS_IOSF_UNIT_LPIO1, MBI_CFG_WRITE,
+                       LPSS_IOSF_PMCSR, value2, mask2);
+
+       mutex_unlock(&lpss_iosf_mutex);
+}
+
 static int acpi_lpss_runtime_suspend(struct device *dev)
 {
        struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev));
@@ -640,7 +786,17 @@ static int acpi_lpss_runtime_suspend(struct device *dev)
        if (pdata->dev_desc->flags & LPSS_SAVE_CTX)
                acpi_lpss_save_ctx(dev, pdata);
 
-       return acpi_dev_runtime_suspend(dev);
+       ret = acpi_dev_runtime_suspend(dev);
+
+       /*
+        * This call must be last in the sequence, otherwise PMC will return
+        * wrong status for devices being about to be powered off. See
+        * lpss_iosf_enter_d3_state() for further information.
+        */
+       if (lpss_quirks & LPSS_QUIRK_ALWAYS_POWER_ON && iosf_mbi_available())
+               lpss_iosf_enter_d3_state();
+
+       return ret;
 }
 
 static int acpi_lpss_runtime_resume(struct device *dev)
@@ -648,10 +804,19 @@ static int acpi_lpss_runtime_resume(struct device *dev)
        struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev));
        int ret;
 
+       /*
+        * This call is kept first to be in symmetry with
+        * acpi_lpss_runtime_suspend() one.
+        */
+       if (lpss_quirks & LPSS_QUIRK_ALWAYS_POWER_ON && iosf_mbi_available())
+               lpss_iosf_exit_d3_state();
+
        ret = acpi_dev_runtime_resume(dev);
        if (ret)
                return ret;
 
+       acpi_lpss_d3_to_d0_delay(pdata);
+
        if (pdata->dev_desc->flags & LPSS_SAVE_CTX)
                acpi_lpss_restore_ctx(dev, pdata);
 
@@ -660,6 +825,10 @@ static int acpi_lpss_runtime_resume(struct device *dev)
 #endif /* CONFIG_PM */
 
 static struct dev_pm_domain acpi_lpss_pm_domain = {
+#ifdef CONFIG_PM
+       .activate = acpi_lpss_activate,
+       .dismiss = acpi_lpss_dismiss,
+#endif
        .ops = {
 #ifdef CONFIG_PM
 #ifdef CONFIG_PM_SLEEP
@@ -705,8 +874,14 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb,
        }
 
        switch (action) {
-       case BUS_NOTIFY_ADD_DEVICE:
+       case BUS_NOTIFY_BIND_DRIVER:
                pdev->dev.pm_domain = &acpi_lpss_pm_domain;
+               break;
+       case BUS_NOTIFY_DRIVER_NOT_BOUND:
+       case BUS_NOTIFY_UNBOUND_DRIVER:
+               pdev->dev.pm_domain = NULL;
+               break;
+       case BUS_NOTIFY_ADD_DEVICE:
                if (pdata->dev_desc->flags & LPSS_LTR)
                        return sysfs_create_group(&pdev->dev.kobj,
                                                  &lpss_attr_group);
@@ -714,7 +889,6 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb,
        case BUS_NOTIFY_DEL_DEVICE:
                if (pdata->dev_desc->flags & LPSS_LTR)
                        sysfs_remove_group(&pdev->dev.kobj, &lpss_attr_group);
-               pdev->dev.pm_domain = NULL;
                break;
        default:
                break;
@@ -754,10 +928,19 @@ static struct acpi_scan_handler lpss_handler = {
 
 void __init acpi_lpss_init(void)
 {
-       if (!lpt_clk_init()) {
-               bus_register_notifier(&platform_bus_type, &acpi_lpss_nb);
-               acpi_scan_add_handler(&lpss_handler);
-       }
+       const struct x86_cpu_id *id;
+       int ret;
+
+       ret = lpt_clk_init();
+       if (ret)
+               return;
+
+       id = x86_match_cpu(lpss_cpu_ids);
+       if (id)
+               lpss_quirks |= LPSS_QUIRK_ALWAYS_POWER_ON;
+
+       bus_register_notifier(&platform_bus_type, &acpi_lpss_nb);
+       acpi_scan_add_handler(&lpss_handler);
 }
 
 #else
index 48fc3ad13a4bbcfe5fc12a5db772855b5add0780..67d97c0090a27ad6a9ae9daecf1a163178481a95 100644 (file)
@@ -367,7 +367,7 @@ static struct acpi_scan_handler acpi_pnp_handler = {
  */
 static int is_cmos_rtc_device(struct acpi_device *adev)
 {
-       struct acpi_device_id ids[] = {
+       static const struct acpi_device_id ids[] = {
                { "PNP0B00" },
                { "PNP0B01" },
                { "PNP0B02" },
index 3405f7a41e2576415d344eb0782323ba469ea0a4..06a006ff89b045b9f9857aac55274a3dd16b7369 100644 (file)
@@ -77,14 +77,21 @@ module_param(allow_duplicates, bool, 0644);
 static int disable_backlight_sysfs_if = -1;
 module_param(disable_backlight_sysfs_if, int, 0444);
 
+#define REPORT_OUTPUT_KEY_EVENTS               0x01
+#define REPORT_BRIGHTNESS_KEY_EVENTS           0x02
+static int report_key_events = -1;
+module_param(report_key_events, int, 0644);
+MODULE_PARM_DESC(report_key_events,
+       "0: none, 1: output changes, 2: brightness changes, 3: all");
+
 static bool device_id_scheme = false;
 module_param(device_id_scheme, bool, 0444);
 
 static bool only_lcd = false;
 module_param(only_lcd, bool, 0444);
 
-static int register_count;
-static DEFINE_MUTEX(register_count_mutex);
+static DECLARE_COMPLETION(register_done);
+static DEFINE_MUTEX(register_done_mutex);
 static struct mutex video_list_lock;
 static struct list_head video_bus_head;
 static int acpi_video_bus_add(struct acpi_device *device);
@@ -412,6 +419,13 @@ static int video_enable_only_lcd(const struct dmi_system_id *d)
        return 0;
 }
 
+static int video_set_report_key_events(const struct dmi_system_id *id)
+{
+       if (report_key_events == -1)
+               report_key_events = (uintptr_t)id->driver_data;
+       return 0;
+}
+
 static struct dmi_system_id video_dmi_table[] = {
        /*
         * Broken _BQC workaround http://bugzilla.kernel.org/show_bug.cgi?id=13121
@@ -500,6 +514,24 @@ static struct dmi_system_id video_dmi_table[] = {
                DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile M9410"),
                },
        },
+       /*
+        * Some machines report wrong key events on the acpi-bus, suppress
+        * key event reporting on these.  Note this is only intended to work
+        * around events which are plain wrong. In some cases we get double
+        * events, in this case acpi-video is considered the canonical source
+        * and the events from the other source should be filtered. E.g.
+        * by calling acpi_video_handles_brightness_key_presses() from the
+        * vendor acpi/wmi driver or by using /lib/udev/hwdb.d/60-keyboard.hwdb
+        */
+       {
+        .callback = video_set_report_key_events,
+        .driver_data = (void *)((uintptr_t)REPORT_OUTPUT_KEY_EVENTS),
+        .ident = "Dell Vostro V131",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+               DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V131"),
+               },
+       },
        {}
 };
 
@@ -1480,7 +1512,7 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event)
                /* Something vetoed the keypress. */
                keycode = 0;
 
-       if (keycode) {
+       if (keycode && (report_key_events & REPORT_OUTPUT_KEY_EVENTS)) {
                input_report_key(input, keycode, 1);
                input_sync(input);
                input_report_key(input, keycode, 0);
@@ -1544,7 +1576,7 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data)
 
        acpi_notifier_call_chain(device, event, 0);
 
-       if (keycode) {
+       if (keycode && (report_key_events & REPORT_BRIGHTNESS_KEY_EVENTS)) {
                input_report_key(input, keycode, 1);
                input_sync(input);
                input_report_key(input, keycode, 0);
@@ -2017,8 +2049,8 @@ int acpi_video_register(void)
 {
        int ret = 0;
 
-       mutex_lock(&register_count_mutex);
-       if (register_count) {
+       mutex_lock(&register_done_mutex);
+       if (completion_done(&register_done)) {
                /*
                 * if the function of acpi_video_register is already called,
                 * don't register the acpi_vide_bus again and return no error.
@@ -2039,22 +2071,22 @@ int acpi_video_register(void)
         * When the acpi_video_bus is loaded successfully, increase
         * the counter reference.
         */
-       register_count = 1;
+       complete(&register_done);
 
 leave:
-       mutex_unlock(&register_count_mutex);
+       mutex_unlock(&register_done_mutex);
        return ret;
 }
 EXPORT_SYMBOL(acpi_video_register);
 
 void acpi_video_unregister(void)
 {
-       mutex_lock(&register_count_mutex);
-       if (register_count) {
+       mutex_lock(&register_done_mutex);
+       if (completion_done(&register_done)) {
                acpi_bus_unregister_driver(&acpi_video_bus);
-               register_count = 0;
+               reinit_completion(&register_done);
        }
-       mutex_unlock(&register_count_mutex);
+       mutex_unlock(&register_done_mutex);
 }
 EXPORT_SYMBOL(acpi_video_unregister);
 
@@ -2062,15 +2094,29 @@ void acpi_video_unregister_backlight(void)
 {
        struct acpi_video_bus *video;
 
-       mutex_lock(&register_count_mutex);
-       if (register_count) {
+       mutex_lock(&register_done_mutex);
+       if (completion_done(&register_done)) {
                mutex_lock(&video_list_lock);
                list_for_each_entry(video, &video_bus_head, entry)
                        acpi_video_bus_unregister_backlight(video);
                mutex_unlock(&video_list_lock);
        }
-       mutex_unlock(&register_count_mutex);
+       mutex_unlock(&register_done_mutex);
+}
+
+bool acpi_video_handles_brightness_key_presses(void)
+{
+       bool have_video_busses;
+
+       wait_for_completion(&register_done);
+       mutex_lock(&video_list_lock);
+       have_video_busses = !list_empty(&video_bus_head);
+       mutex_unlock(&video_list_lock);
+
+       return have_video_busses &&
+              (report_key_events & REPORT_BRIGHTNESS_KEY_EVENTS);
 }
+EXPORT_SYMBOL(acpi_video_handles_brightness_key_presses);
 
 /*
  * This is kind of nasty. Hardware using Intel chipsets may require
index 885936f7954287dcc15ef3048a1546137b25c61e..f682374c19f45a7a421b29b474739e5c7e8109b6 100644 (file)
@@ -50,6 +50,7 @@ acpi-y +=             \
        exdump.o        \
        exfield.o       \
        exfldio.o       \
+       exmisc.o        \
        exmutex.o       \
        exnames.o       \
        exoparg1.o      \
@@ -57,7 +58,6 @@ acpi-y +=             \
        exoparg3.o      \
        exoparg6.o      \
        exprep.o        \
-       exmisc.o        \
        exregion.o      \
        exresnte.o      \
        exresolv.o      \
@@ -66,6 +66,7 @@ acpi-y +=             \
        exstoren.o      \
        exstorob.o      \
        exsystem.o      \
+       extrace.o       \
        exutils.o
 
 acpi-y +=              \
@@ -196,7 +197,6 @@ acpi-$(ACPI_FUTURE_USAGE) +=        \
        dbfileio.o              \
        dbtest.o                \
        utcache.o               \
-       utfileio.o              \
        utprint.o               \
        uttrack.o               \
        utuuid.o
index e4cc48fbf4eef49bdcbac4a879e0739a0faac25f..8b4ff40a294ca2cfd5b86ec6a33d9ba2f3d163c1 100644 (file)
@@ -44,6 +44,8 @@
 #ifndef _ACAPPS
 #define _ACAPPS
 
+#include <stdio.h>
+
 /* Common info for tool signons */
 
 #define ACPICA_NAME                 "Intel ACPI Component Architecture"
        acpi_os_printf (description);
 
 #define ACPI_OPTION(name, description) \
-       acpi_os_printf (" %-18s%s\n", name, description);
+       acpi_os_printf (" %-20s%s\n", name, description);
+
+/* Check for unexpected exceptions */
+
+#define ACPI_CHECK_STATUS(name, status, expected) \
+       if (status != expected) \
+       { \
+               acpi_os_printf ("Unexpected %s from %s (%s-%d)\n", \
+                       acpi_format_exception (status), #name, _acpi_module_name, __LINE__); \
+       }
+
+/* Check for unexpected non-AE_OK errors */
+
+#define ACPI_CHECK_OK(name, status)   ACPI_CHECK_STATUS (name, status, AE_OK);
 
 #define FILE_SUFFIX_DISASSEMBLY     "dsl"
 #define FILE_SUFFIX_BINARY_TABLE    ".dat"     /* Needs the dot */
 
+/* acfileio */
+
+acpi_status
+ac_get_all_tables_from_file(char *filename,
+                           u8 get_only_aml_tables,
+                           struct acpi_new_table_desc **return_list_head);
+
+u8 ac_is_file_binary(FILE * file);
+
+acpi_status ac_validate_table_header(FILE * file, long table_offset);
+
+/* Values for get_only_aml_tables */
+
+#define ACPI_GET_ONLY_AML_TABLES    TRUE
+#define ACPI_GET_ALL_TABLES         FALSE
+
 /*
  * getopt
  */
@@ -107,30 +138,6 @@ extern char *acpi_gbl_optarg;
  */
 u32 cm_get_file_size(ACPI_FILE file);
 
-#ifndef ACPI_DUMP_APP
-/*
- * adisasm
- */
-acpi_status
-ad_aml_disassemble(u8 out_to_file,
-                  char *filename, char *prefix, char **out_filename);
-
-void ad_print_statistics(void);
-
-acpi_status ad_find_dsdt(u8 **dsdt_ptr, u32 *dsdt_length);
-
-void ad_dump_tables(void);
-
-acpi_status ad_get_local_tables(void);
-
-acpi_status
-ad_parse_table(struct acpi_table_header *table,
-              acpi_owner_id * owner_id, u8 load_table, u8 external);
-
-acpi_status ad_display_tables(char *filename, struct acpi_table_header *table);
-
-acpi_status ad_display_statistics(void);
-
 /*
  * adwalk
  */
@@ -168,6 +175,5 @@ char *ad_generate_filename(char *prefix, char *table_id);
 void
 ad_write_table(struct acpi_table_header *table,
               u32 length, char *table_name, char *oem_table_id);
-#endif
 
 #endif                         /* _ACAPPS */
index c928ba494c4000ff71a54bcd4ea022082ee7ccc6..ecb05f1c1d5c42c41d2befbf2abfb25091c42b27 100644 (file)
@@ -80,9 +80,15 @@ struct acpi_db_execute_walk {
 /*
  * dbxface - external debugger interfaces
  */
-acpi_status
-acpi_db_single_step(struct acpi_walk_state *walk_state,
-                   union acpi_parse_object *op, u32 op_type);
+ACPI_DBR_DEPENDENT_RETURN_OK(acpi_status
+                            acpi_db_single_step(struct acpi_walk_state
+                                                *walk_state,
+                                                union acpi_parse_object *op,
+                                                u32 op_type))
+ ACPI_DBR_DEPENDENT_RETURN_VOID(void
+                               acpi_db_signal_break_point(struct
+                                                          acpi_walk_state
+                                                          *walk_state))
 
 /*
  * dbcmds - debug commands and output routines
@@ -182,11 +188,15 @@ void acpi_db_display_method_info(union acpi_parse_object *op);
 
 void acpi_db_decode_and_display_object(char *target, char *output_type);
 
-void
-acpi_db_display_result_object(union acpi_operand_object *obj_desc,
-                             struct acpi_walk_state *walk_state);
+ACPI_DBR_DEPENDENT_RETURN_VOID(void
+                              acpi_db_display_result_object(union
+                                                            acpi_operand_object
+                                                            *obj_desc,
+                                                            struct
+                                                            acpi_walk_state
+                                                            *walk_state))
 
-acpi_status acpi_db_display_all_methods(char *display_count_arg);
+ acpi_status acpi_db_display_all_methods(char *display_count_arg);
 
 void acpi_db_display_arguments(void);
 
@@ -198,9 +208,13 @@ void acpi_db_display_calling_tree(void);
 
 void acpi_db_display_object_type(char *object_arg);
 
-void
-acpi_db_display_argument_object(union acpi_operand_object *obj_desc,
-                               struct acpi_walk_state *walk_state);
+ACPI_DBR_DEPENDENT_RETURN_VOID(void
+                              acpi_db_display_argument_object(union
+                                                              acpi_operand_object
+                                                              *obj_desc,
+                                                              struct
+                                                              acpi_walk_state
+                                                              *walk_state))
 
 /*
  * dbexec - debugger control method execution
@@ -231,10 +245,7 @@ void acpi_db_open_debug_file(char *name);
 
 acpi_status acpi_db_load_acpi_table(char *filename);
 
-acpi_status
-acpi_db_get_table_from_file(char *filename,
-                           struct acpi_table_header **table,
-                           u8 must_be_aml_table);
+acpi_status acpi_db_load_tables(struct acpi_new_table_desc *list_head);
 
 /*
  * dbhistry - debugger HISTORY command
@@ -257,7 +268,7 @@ acpi_db_command_dispatch(char *input_buffer,
 
 void ACPI_SYSTEM_XFACE acpi_db_execute_thread(void *context);
 
-acpi_status acpi_db_user_commands(char prompt, union acpi_parse_object *op);
+acpi_status acpi_db_user_commands(void);
 
 char *acpi_db_get_next_token(char *string,
                             char **next, acpi_object_type * return_type);
index 228704b7865774695764286a32aab5c78490a26b..d18f1840907177e9c928e2d24f2dc1653070393a 100644 (file)
@@ -161,6 +161,11 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
 /*
  * evhandler - Address space handling
  */
+union acpi_operand_object *acpi_ev_find_region_handler(acpi_adr_space_type
+                                                      space_id,
+                                                      union acpi_operand_object
+                                                      *handler_obj);
+
 u8
 acpi_ev_has_default_handler(struct acpi_namespace_node *node,
                            acpi_adr_space_type space_id);
@@ -193,9 +198,11 @@ void
 acpi_ev_detach_region(union acpi_operand_object *region_obj,
                      u8 acpi_ns_is_locked);
 
-acpi_status
+void acpi_ev_associate_reg_method(union acpi_operand_object *region_obj);
+
+void
 acpi_ev_execute_reg_methods(struct acpi_namespace_node *node,
-                           acpi_adr_space_type space_id);
+                           acpi_adr_space_type space_id, u32 function);
 
 acpi_status
 acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function);
index faa97604d878e01a41707494435ed16d7f9b81fc..73462cac41d285341f459eadf590f9588d854098 100644 (file)
@@ -145,6 +145,7 @@ ACPI_GLOBAL(acpi_cache_t *, acpi_gbl_operand_cache);
 
 ACPI_INIT_GLOBAL(u32, acpi_gbl_startup_flags, 0);
 ACPI_INIT_GLOBAL(u8, acpi_gbl_shutdown, TRUE);
+ACPI_INIT_GLOBAL(u8, acpi_gbl_early_initialization, TRUE);
 
 /* Global handlers */
 
@@ -164,7 +165,7 @@ ACPI_GLOBAL(u8, acpi_gbl_next_owner_id_offset);
 
 /* Initialization sequencing */
 
-ACPI_GLOBAL(u8, acpi_gbl_reg_methods_executed);
+ACPI_INIT_GLOBAL(u8, acpi_gbl_reg_methods_enabled, FALSE);
 
 /* Misc */
 
@@ -326,7 +327,6 @@ ACPI_GLOBAL(struct acpi_external_file *, acpi_gbl_external_file_list);
 #ifdef ACPI_DEBUGGER
 
 ACPI_INIT_GLOBAL(u8, acpi_gbl_abort_method, FALSE);
-ACPI_INIT_GLOBAL(u8, acpi_gbl_method_executing, FALSE);
 ACPI_INIT_GLOBAL(acpi_thread_id, acpi_gbl_db_thread_id, ACPI_INVALID_THREAD_ID);
 
 ACPI_GLOBAL(u8, acpi_gbl_db_opt_no_ini_methods);
@@ -345,7 +345,6 @@ ACPI_GLOBAL(acpi_object_type, acpi_gbl_db_arg_types[ACPI_DEBUGGER_MAX_ARGS]);
 
 /* These buffers should all be the same size */
 
-ACPI_GLOBAL(char, acpi_gbl_db_line_buf[ACPI_DB_LINE_BUFFER_SIZE]);
 ACPI_GLOBAL(char, acpi_gbl_db_parsed_buf[ACPI_DB_LINE_BUFFER_SIZE]);
 ACPI_GLOBAL(char, acpi_gbl_db_scope_buf[ACPI_DB_LINE_BUFFER_SIZE]);
 ACPI_GLOBAL(char, acpi_gbl_db_debug_filename[ACPI_DB_LINE_BUFFER_SIZE]);
@@ -360,9 +359,6 @@ ACPI_GLOBAL(u16, acpi_gbl_node_type_count_misc);
 ACPI_GLOBAL(u32, acpi_gbl_num_nodes);
 ACPI_GLOBAL(u32, acpi_gbl_num_objects);
 
-ACPI_GLOBAL(acpi_mutex, acpi_gbl_db_command_ready);
-ACPI_GLOBAL(acpi_mutex, acpi_gbl_db_command_complete);
-
 #endif                         /* ACPI_DEBUGGER */
 
 /*****************************************************************************
index e1dd784d851599e12a8adbf831d3f560f3c0dc94..24928ec444de5f2d4a98ceda181bc0a171299e9d 100644 (file)
@@ -219,6 +219,13 @@ struct acpi_table_list {
 #define ACPI_ROOT_ORIGIN_ALLOCATED      (1)
 #define ACPI_ROOT_ALLOW_RESIZE          (2)
 
+/* List to manage incoming ACPI tables */
+
+struct acpi_new_table_desc {
+       struct acpi_table_header *table;
+       struct acpi_new_table_desc *next;
+};
+
 /* Predefined table indexes */
 
 #define ACPI_INVALID_TABLE_INDEX        (0xFFFFFFFF)
@@ -388,7 +395,8 @@ union acpi_predefined_info {
 
 /* Return object auto-repair info */
 
-typedef acpi_status(*acpi_object_converter) (union acpi_operand_object
+typedef acpi_status(*acpi_object_converter) (struct acpi_namespace_node * scope,
+                                            union acpi_operand_object
                                             *original_object,
                                             union acpi_operand_object
                                             **converted_object);
@@ -420,6 +428,7 @@ struct acpi_simple_repair_info {
 
 struct acpi_reg_walk_info {
        acpi_adr_space_type space_id;
+       u32 function;
        u32 reg_run_count;
 };
 
@@ -861,6 +870,7 @@ struct acpi_parse_state {
 #define ACPI_PARSEOP_CLOSING_PAREN      0x10
 #define ACPI_PARSEOP_COMPOUND           0x20
 #define ACPI_PARSEOP_ASSIGNMENT         0x40
+#define ACPI_PARSEOP_ELSEIF             0x80
 
 /*****************************************************************************
  *
index e85366ceb15a28d2a6c7602ce458253055c0c6fb..bad5bca03acc3b879f871d5b9125cd586e9fca38 100644 (file)
 #define ACPI_HW_OPTIONAL_FUNCTION(addr)     NULL
 #endif
 
-/*
- * Some code only gets executed when the debugger is built in.
- * Note that this is entirely independent of whether the
- * DEBUG_PRINT stuff (set by ACPI_DEBUG_OUTPUT) is on, or not.
- */
-#ifdef ACPI_DEBUGGER
-#define ACPI_DEBUGGER_EXEC(a)           a
-#else
-#define ACPI_DEBUGGER_EXEC(a)
-#endif
-
 /*
  * Macros used for ACPICA utilities only
  */
index 5d261c942a0d129150ab76c05e82af9b1ab43a2e..d082e62d73080d05d2d81b0a27d3197d3e798a38 100644 (file)
@@ -77,6 +77,7 @@
 /* Object is not a package element */
 
 #define ACPI_NOT_PACKAGE_ELEMENT    ACPI_UINT32_MAX
+#define ACPI_ALL_PACKAGE_ELEMENTS   (ACPI_UINT32_MAX-1)
 
 /* Always emit warning message, not dependent on node flags */
 
@@ -183,13 +184,20 @@ acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
                          union acpi_operand_object **return_object);
 
 acpi_status
-acpi_ns_convert_to_unicode(union acpi_operand_object *original_object,
+acpi_ns_convert_to_unicode(struct acpi_namespace_node *scope,
+                          union acpi_operand_object *original_object,
                           union acpi_operand_object **return_object);
 
 acpi_status
-acpi_ns_convert_to_resource(union acpi_operand_object *original_object,
+acpi_ns_convert_to_resource(struct acpi_namespace_node *scope,
+                           union acpi_operand_object *original_object,
                            union acpi_operand_object **return_object);
 
+acpi_status
+acpi_ns_convert_to_reference(struct acpi_namespace_node *scope,
+                            union acpi_operand_object *original_object,
+                            union acpi_operand_object **return_object);
+
 /*
  * nsdump - Namespace dump/print utilities
  */
index 0bd02c4a5f759ec8a4062a292c9f6dfc3424f18e..2b154cfbe136691b887cef179b974fb99f3af84d 100644 (file)
 #define AOPOBJ_AML_CONSTANT         0x01       /* Integer is an AML constant */
 #define AOPOBJ_STATIC_POINTER       0x02       /* Data is part of an ACPI table, don't delete */
 #define AOPOBJ_DATA_VALID           0x04       /* Object is initialized and data is valid */
-#define AOPOBJ_OBJECT_INITIALIZED   0x08       /* Region is initialized, _REG was run */
-#define AOPOBJ_SETUP_COMPLETE       0x10       /* Region setup is complete */
-#define AOPOBJ_INVALID              0x20       /* Host OS won't allow a Region address */
+#define AOPOBJ_OBJECT_INITIALIZED   0x08       /* Region is initialized */
+#define AOPOBJ_REG_CONNECTED        0x10       /* _REG was run */
+#define AOPOBJ_SETUP_COMPLETE       0x20       /* Region setup is complete */
+#define AOPOBJ_INVALID              0x40       /* Host OS won't allow a Region address */
 
 /******************************************************************************
  *
index f9acf92fa0bc2121b6a50a99874979d63e0fe37b..324512db62bf0474d5bd5b7b9c50c2355972a643 100644 (file)
@@ -92,7 +92,7 @@
 #define ARGP_BYTELIST_OP                ARGP_LIST1 (ARGP_NAMESTRING)
 #define ARGP_CONCAT_OP                  ARGP_LIST3 (ARGP_TERMARG,    ARGP_TERMARG,       ARGP_TARGET)
 #define ARGP_CONCAT_RES_OP              ARGP_LIST3 (ARGP_TERMARG,    ARGP_TERMARG,       ARGP_TARGET)
-#define ARGP_COND_REF_OF_OP             ARGP_LIST2 (ARGP_SUPERNAME,  ARGP_SUPERNAME)
+#define ARGP_COND_REF_OF_OP             ARGP_LIST2 (ARGP_NAME_OR_REF,ARGP_TARGET)
 #define ARGP_CONNECTFIELD_OP            ARGP_LIST1 (ARGP_NAMESTRING)
 #define ARGP_CONTINUE_OP                ARG_NONE
 #define ARGP_COPY_OP                    ARGP_LIST2 (ARGP_TERMARG,    ARGP_SIMPLENAME)
 #define ARGP_NAMEPATH_OP                ARGP_LIST1 (ARGP_NAMESTRING)
 #define ARGP_NOOP_OP                    ARG_NONE
 #define ARGP_NOTIFY_OP                  ARGP_LIST2 (ARGP_SUPERNAME,  ARGP_TERMARG)
+#define ARGP_OBJECT_TYPE_OP             ARGP_LIST1 (ARGP_NAME_OR_REF)
 #define ARGP_ONE_OP                     ARG_NONE
 #define ARGP_ONES_OP                    ARG_NONE
 #define ARGP_PACKAGE_OP                 ARGP_LIST3 (ARGP_PKGLENGTH,  ARGP_BYTEDATA,      ARGP_DATAOBJLIST)
 #define ARGP_POWER_RES_OP               ARGP_LIST5 (ARGP_PKGLENGTH,  ARGP_NAME,          ARGP_BYTEDATA,  ARGP_WORDDATA,  ARGP_OBJLIST)
 #define ARGP_PROCESSOR_OP               ARGP_LIST6 (ARGP_PKGLENGTH,  ARGP_NAME,          ARGP_BYTEDATA,  ARGP_DWORDDATA, ARGP_BYTEDATA,  ARGP_OBJLIST)
 #define ARGP_QWORD_OP                   ARGP_LIST1 (ARGP_QWORDDATA)
-#define ARGP_REF_OF_OP                  ARGP_LIST1 (ARGP_SUPERNAME)
+#define ARGP_REF_OF_OP                  ARGP_LIST1 (ARGP_NAME_OR_REF)
 #define ARGP_REGION_OP                  ARGP_LIST4 (ARGP_NAME,       ARGP_BYTEDATA,      ARGP_TERMARG,   ARGP_TERMARG)
 #define ARGP_RELEASE_OP                 ARGP_LIST1 (ARGP_SUPERNAME)
 #define ARGP_RESERVEDFIELD_OP           ARGP_LIST1 (ARGP_NAMESTRING)
 #define ARGP_TO_HEX_STR_OP              ARGP_LIST2 (ARGP_TERMARG,    ARGP_TARGET)
 #define ARGP_TO_INTEGER_OP              ARGP_LIST2 (ARGP_TERMARG,    ARGP_TARGET)
 #define ARGP_TO_STRING_OP               ARGP_LIST3 (ARGP_TERMARG,    ARGP_TERMARG,       ARGP_TARGET)
-#define ARGP_TYPE_OP                    ARGP_LIST1 (ARGP_SUPERNAME)
 #define ARGP_UNLOAD_OP                  ARGP_LIST1 (ARGP_SUPERNAME)
 #define ARGP_VAR_PACKAGE_OP             ARGP_LIST3 (ARGP_PKGLENGTH,  ARGP_TERMARG,       ARGP_DATAOBJLIST)
 #define ARGP_WAIT_OP                    ARGP_LIST2 (ARGP_SUPERNAME,  ARGP_TERMARG)
 #define ARGI_BUFFER_OP                  ARGI_LIST1 (ARGI_INTEGER)
 #define ARGI_BYTE_OP                    ARGI_INVALID_OPCODE
 #define ARGI_BYTELIST_OP                ARGI_INVALID_OPCODE
-#define ARGI_CONCAT_OP                  ARGI_LIST3 (ARGI_COMPUTEDATA,ARGI_COMPUTEDATA,   ARGI_TARGETREF)
+#define ARGI_CONCAT_OP                  ARGI_LIST3 (ARGI_ANYTYPE,    ARGI_ANYTYPE,       ARGI_TARGETREF)
 #define ARGI_CONCAT_RES_OP              ARGI_LIST3 (ARGI_BUFFER,     ARGI_BUFFER,        ARGI_TARGETREF)
 #define ARGI_COND_REF_OF_OP             ARGI_LIST2 (ARGI_OBJECT_REF, ARGI_TARGETREF)
 #define ARGI_CONNECTFIELD_OP            ARGI_INVALID_OPCODE
 #define ARGI_NAMEPATH_OP                ARGI_INVALID_OPCODE
 #define ARGI_NOOP_OP                    ARG_NONE
 #define ARGI_NOTIFY_OP                  ARGI_LIST2 (ARGI_DEVICE_REF, ARGI_INTEGER)
+#define ARGI_OBJECT_TYPE_OP             ARGI_LIST1 (ARGI_ANYTYPE)
 #define ARGI_ONE_OP                     ARG_NONE
 #define ARGI_ONES_OP                    ARG_NONE
 #define ARGI_PACKAGE_OP                 ARGI_LIST1 (ARGI_INTEGER)
 #define ARGI_TO_HEX_STR_OP              ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET)
 #define ARGI_TO_INTEGER_OP              ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET)
 #define ARGI_TO_STRING_OP               ARGI_LIST3 (ARGI_BUFFER,     ARGI_INTEGER,       ARGI_FIXED_TARGET)
-#define ARGI_TYPE_OP                    ARGI_LIST1 (ARGI_ANYTYPE)
 #define ARGI_UNLOAD_OP                  ARGI_LIST1 (ARGI_DDBHANDLE)
 #define ARGI_VAR_PACKAGE_OP             ARGI_LIST1 (ARGI_INTEGER)
 #define ARGI_WAIT_OP                    ARGI_LIST2 (ARGI_EVENT,      ARGI_INTEGER)
index 8fc8c7cea87963ceb40c8a3184290ebe23b0d331..96d510a7feba1d05da7b0cf845de300cc273c6bb 100644 (file)
@@ -92,7 +92,13 @@ acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state,
 acpi_status
 acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state,
                          struct acpi_parse_state *parser_state,
-                         union acpi_parse_object *arg, u8 method_call);
+                         union acpi_parse_object *arg,
+                         u8 possible_method_call);
+
+/* Values for u8 above */
+
+#define ACPI_NOT_METHOD_CALL            FALSE
+#define ACPI_POSSIBLE_METHOD_CALL       TRUE
 
 acpi_status
 acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
index 8b8fef6cc32df7dac1d77191172550b5bf7b3d2c..9e84c05c0b910cc9644eee0782f2064cd0d445bf 100644 (file)
@@ -184,24 +184,24 @@ acpi_status acpi_ut_init_globals(void);
 
 #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
 
-char *acpi_ut_get_mutex_name(u32 mutex_id);
+const char *acpi_ut_get_mutex_name(u32 mutex_id);
 
 const char *acpi_ut_get_notify_name(u32 notify_value, acpi_object_type type);
 #endif
 
-char *acpi_ut_get_type_name(acpi_object_type type);
+const char *acpi_ut_get_type_name(acpi_object_type type);
 
-char *acpi_ut_get_node_name(void *object);
+const char *acpi_ut_get_node_name(void *object);
 
-char *acpi_ut_get_descriptor_name(void *object);
+const char *acpi_ut_get_descriptor_name(void *object);
 
 const char *acpi_ut_get_reference_name(union acpi_operand_object *object);
 
-char *acpi_ut_get_object_type_name(union acpi_operand_object *obj_desc);
+const char *acpi_ut_get_object_type_name(union acpi_operand_object *obj_desc);
 
-char *acpi_ut_get_region_name(u8 space_id);
+const char *acpi_ut_get_region_name(u8 space_id);
 
-char *acpi_ut_get_event_name(u32 event_id);
+const char *acpi_ut_get_event_name(u32 event_id);
 
 char acpi_ut_hex_to_ascii_char(u64 integer, u32 position);
 
@@ -352,14 +352,6 @@ acpi_ut_execute_power_methods(struct acpi_namespace_node *device_node,
                              const char **method_names,
                              u8 method_count, u8 *out_values);
 
-/*
- * utfileio - file operations
- */
-#ifdef ACPI_APPLICATION
-acpi_status
-acpi_ut_read_table_from_file(char *filename, struct acpi_table_header **table);
-#endif
-
 /*
  * utids - device ID support
  */
@@ -371,10 +363,6 @@ acpi_status
 acpi_ut_execute_UID(struct acpi_namespace_node *device_node,
                    struct acpi_pnp_device_id ** return_id);
 
-acpi_status
-acpi_ut_execute_SUB(struct acpi_namespace_node *device_node,
-                   struct acpi_pnp_device_id **return_id);
-
 acpi_status
 acpi_ut_execute_CID(struct acpi_namespace_node *device_node,
                    struct acpi_pnp_device_id_list ** return_cid_list);
index 883f20cfa69809674d04db7070118bda7d2400d5..ab9f3f1fbb0f233a9ca7ba3b2fb4ebc6521b7115 100644 (file)
 #define AML_CREATE_WORD_FIELD_OP    (u16) 0x8b
 #define AML_CREATE_BYTE_FIELD_OP    (u16) 0x8c
 #define AML_CREATE_BIT_FIELD_OP     (u16) 0x8d
-#define AML_TYPE_OP                 (u16) 0x8e
+#define AML_OBJECT_TYPE_OP          (u16) 0x8e
 #define AML_CREATE_QWORD_FIELD_OP   (u16) 0x8f /* ACPI 2.0 */
 #define AML_LAND_OP                 (u16) 0x90
 #define AML_LOR_OP                  (u16) 0x91
 #define ARGP_TERMLIST               0x0F
 #define ARGP_WORDDATA               0x10
 #define ARGP_QWORDDATA              0x11
-#define ARGP_SIMPLENAME             0x12
+#define ARGP_SIMPLENAME             0x12       /* name_string | local_term | arg_term */
+#define ARGP_NAME_OR_REF            0x13       /* For object_type only */
 
 /*
  * Resolved argument types for the AML Interpreter
index 30414b3d7fddd2d97f00bb796776ff4435d629a2..328c35b323d55f04ee0d5e7ceac5781a3c87ed42 100644 (file)
@@ -798,7 +798,7 @@ acpi_db_device_resources(acpi_handle obj_handle,
        acpi_status status;
 
        node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle);
-       parent_path = acpi_ns_get_external_pathname(node);
+       parent_path = acpi_ns_get_normalized_pathname(node, TRUE);
        if (!parent_path) {
                return (AE_NO_MEMORY);
        }
@@ -1131,13 +1131,8 @@ void acpi_db_trace(char *enable_arg, char *method_arg, char *once_arg)
        u32 debug_layer = 0;
        u32 flags = 0;
 
-       if (enable_arg) {
-               acpi_ut_strupr(enable_arg);
-       }
-
-       if (once_arg) {
-               acpi_ut_strupr(once_arg);
-       }
+       acpi_ut_strupr(enable_arg);
+       acpi_ut_strupr(once_arg);
 
        if (method_arg) {
                if (acpi_db_trace_method_name) {
index 672977ec7c7df275fa174b84c14f544892250d8e..1965b48d8e833e42cf3fe2fd74b4c91ecdd93599 100644 (file)
@@ -48,6 +48,7 @@
 #include "acnamesp.h"
 #include "acparser.h"
 #include "acinterp.h"
+#include "acevents.h"
 #include "acdebug.h"
 
 #define _COMPONENT          ACPI_CA_DEBUGGER
@@ -588,7 +589,7 @@ void acpi_db_display_calling_tree(void)
  *
  * FUNCTION:    acpi_db_display_object_type
  *
- * PARAMETERS:  name            - User entered NS node handle or name
+ * PARAMETERS:  object_arg      - User entered NS node handle
  *
  * RETURN:      None
  *
@@ -596,44 +597,34 @@ void acpi_db_display_calling_tree(void)
  *
  ******************************************************************************/
 
-void acpi_db_display_object_type(char *name)
+void acpi_db_display_object_type(char *object_arg)
 {
-       struct acpi_namespace_node *node;
+       acpi_handle handle;
        struct acpi_device_info *info;
        acpi_status status;
        u32 i;
 
-       node = acpi_db_convert_to_node(name);
-       if (!node) {
-               return;
-       }
+       handle = ACPI_TO_POINTER(strtoul(object_arg, NULL, 16));
 
-       status = acpi_get_object_info(ACPI_CAST_PTR(acpi_handle, node), &info);
+       status = acpi_get_object_info(handle, &info);
        if (ACPI_FAILURE(status)) {
                acpi_os_printf("Could not get object info, %s\n",
                               acpi_format_exception(status));
                return;
        }
 
-       if (info->valid & ACPI_VALID_ADR) {
-               acpi_os_printf("ADR: %8.8X%8.8X, STA: %8.8X, Flags: %X\n",
-                              ACPI_FORMAT_UINT64(info->address),
-                              info->current_status, info->flags);
-       }
-       if (info->valid & ACPI_VALID_SXDS) {
-               acpi_os_printf("S1D-%2.2X S2D-%2.2X S3D-%2.2X S4D-%2.2X\n",
-                              info->highest_dstates[0],
-                              info->highest_dstates[1],
-                              info->highest_dstates[2],
-                              info->highest_dstates[3]);
-       }
-       if (info->valid & ACPI_VALID_SXWS) {
-               acpi_os_printf
-                   ("S0W-%2.2X S1W-%2.2X S2W-%2.2X S3W-%2.2X S4W-%2.2X\n",
-                    info->lowest_dstates[0], info->lowest_dstates[1],
-                    info->lowest_dstates[2], info->lowest_dstates[3],
-                    info->lowest_dstates[4]);
-       }
+       acpi_os_printf("ADR: %8.8X%8.8X, STA: %8.8X, Flags: %X\n",
+                      ACPI_FORMAT_UINT64(info->address),
+                      info->current_status, info->flags);
+
+       acpi_os_printf("S1D-%2.2X S2D-%2.2X S3D-%2.2X S4D-%2.2X\n",
+                      info->highest_dstates[0], info->highest_dstates[1],
+                      info->highest_dstates[2], info->highest_dstates[3]);
+
+       acpi_os_printf("S0W-%2.2X S1W-%2.2X S2W-%2.2X S3W-%2.2X S4W-%2.2X\n",
+                      info->lowest_dstates[0], info->lowest_dstates[1],
+                      info->lowest_dstates[2], info->lowest_dstates[3],
+                      info->lowest_dstates[4]);
 
        if (info->valid & ACPI_VALID_HID) {
                acpi_os_printf("HID: %s\n", info->hardware_id.string);
@@ -643,10 +634,6 @@ void acpi_db_display_object_type(char *name)
                acpi_os_printf("UID: %s\n", info->unique_id.string);
        }
 
-       if (info->valid & ACPI_VALID_SUB) {
-               acpi_os_printf("SUB: %s\n", info->subsystem_id.string);
-       }
-
        if (info->valid & ACPI_VALID_CID) {
                for (i = 0; i < info->compatible_id_list.count; i++) {
                        acpi_os_printf("CID %u: %s\n", i,
@@ -679,6 +666,12 @@ acpi_db_display_result_object(union acpi_operand_object *obj_desc,
                              struct acpi_walk_state *walk_state)
 {
 
+#ifndef ACPI_APPLICATION
+       if (acpi_gbl_db_thread_id != acpi_os_get_thread_id()) {
+               return;
+       }
+#endif
+
        /* Only display if single stepping */
 
        if (!acpi_gbl_cm_single_step) {
@@ -708,6 +701,12 @@ acpi_db_display_argument_object(union acpi_operand_object *obj_desc,
                                struct acpi_walk_state *walk_state)
 {
 
+#ifndef ACPI_APPLICATION
+       if (acpi_gbl_db_thread_id != acpi_os_get_thread_id()) {
+               return;
+       }
+#endif
+
        if (!acpi_gbl_cm_single_step) {
                return;
        }
@@ -951,28 +950,25 @@ void acpi_db_display_handlers(void)
        if (obj_desc) {
                for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_gbl_space_id_list); i++) {
                        space_id = acpi_gbl_space_id_list[i];
-                       handler_obj = obj_desc->device.handler;
 
                        acpi_os_printf(ACPI_PREDEFINED_PREFIX,
                                       acpi_ut_get_region_name((u8)space_id),
                                       space_id);
 
-                       while (handler_obj) {
-                               if (acpi_gbl_space_id_list[i] ==
-                                   handler_obj->address_space.space_id) {
-                                       acpi_os_printf
-                                           (ACPI_HANDLER_PRESENT_STRING,
-                                            (handler_obj->address_space.
-                                             handler_flags &
-                                             ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)
-                                            ? "Default" : "User",
-                                            handler_obj->address_space.
-                                            handler);
-
-                                       goto found_handler;
-                               }
+                       handler_obj =
+                           acpi_ev_find_region_handler(space_id,
+                                                       obj_desc->common_notify.
+                                                       handler);
+                       if (handler_obj) {
+                               acpi_os_printf(ACPI_HANDLER_PRESENT_STRING,
+                                              (handler_obj->address_space.
+                                               handler_flags &
+                                               ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)
+                                              ? "Default" : "User",
+                                              handler_obj->address_space.
+                                              handler);
 
-                               handler_obj = handler_obj->address_space.next;
+                               goto found_handler;
                        }
 
                        /* There is no handler for this space_id */
@@ -984,7 +980,7 @@ found_handler:              ;
 
                /* Find all handlers for user-defined space_IDs */
 
-               handler_obj = obj_desc->device.handler;
+               handler_obj = obj_desc->common_notify.handler;
                while (handler_obj) {
                        if (handler_obj->address_space.space_id >=
                            ACPI_USER_REGION_BEGIN) {
@@ -1079,14 +1075,14 @@ acpi_db_display_non_root_handlers(acpi_handle obj_handle,
                return (AE_OK);
        }
 
-       pathname = acpi_ns_get_external_pathname(node);
+       pathname = acpi_ns_get_normalized_pathname(node, TRUE);
        if (!pathname) {
                return (AE_OK);
        }
 
        /* Display all handlers associated with this device */
 
-       handler_obj = obj_desc->device.handler;
+       handler_obj = obj_desc->common_notify.handler;
        while (handler_obj) {
                acpi_os_printf(ACPI_PREDEFINED_PREFIX,
                               acpi_ut_get_region_name((u8)handler_obj->
index d0e6b20ce82ab7861cb50a1bd7241d3c0cc24adf..31f54d71c51ab4ceda42a30db252777ebeb721ba 100644 (file)
 #include "accommon.h"
 #include "acdebug.h"
 #include "actables.h"
+#include <stdio.h>
+#ifdef ACPI_APPLICATION
+#include "acapps.h"
+#endif
 
 #define _COMPONENT          ACPI_CA_DEBUGGER
 ACPI_MODULE_NAME("dbfileio")
@@ -110,122 +114,31 @@ void acpi_db_open_debug_file(char *name)
 }
 #endif
 
-#ifdef ACPI_APPLICATION
-#include "acapps.h"
-
-/*******************************************************************************
- *
- * FUNCTION:    ae_local_load_table
- *
- * PARAMETERS:  table           - pointer to a buffer containing the entire
- *                                table to be loaded
- *
- * RETURN:      Status
- *
- * DESCRIPTION: This function is called to load a table from the caller's
- *              buffer. The buffer must contain an entire ACPI Table including
- *              a valid header. The header fields will be verified, and if it
- *              is determined that the table is invalid, the call will fail.
- *
- ******************************************************************************/
-
-static acpi_status ae_local_load_table(struct acpi_table_header *table)
-{
-       acpi_status status = AE_OK;
-
-       ACPI_FUNCTION_TRACE(ae_local_load_table);
-
-#if 0
-/*    struct acpi_table_desc          table_info; */
-
-       if (!table) {
-               return_ACPI_STATUS(AE_BAD_PARAMETER);
-       }
-
-       table_info.pointer = table;
-       status = acpi_tb_recognize_table(&table_info, ACPI_TABLE_ALL);
-       if (ACPI_FAILURE(status)) {
-               return_ACPI_STATUS(status);
-       }
-
-       /* Install the new table into the local data structures */
-
-       status = acpi_tb_init_table_descriptor(&table_info);
-       if (ACPI_FAILURE(status)) {
-               if (status == AE_ALREADY_EXISTS) {
-
-                       /* Table already exists, no error */
-
-                       status = AE_OK;
-               }
-
-               /* Free table allocated by acpi_tb_get_table */
-
-               acpi_tb_delete_single_table(&table_info);
-               return_ACPI_STATUS(status);
-       }
-#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
-
-       status =
-           acpi_ns_load_table(table_info.installed_desc, acpi_gbl_root_node);
-       if (ACPI_FAILURE(status)) {
-
-               /* Uninstall table and free the buffer */
-
-               acpi_tb_delete_tables_by_type(ACPI_TABLE_ID_DSDT);
-               return_ACPI_STATUS(status);
-       }
-#endif
-#endif
-
-       return_ACPI_STATUS(status);
-}
-#endif
-
 /*******************************************************************************
  *
- * FUNCTION:    acpi_db_get_table_from_file
+ * FUNCTION:    acpi_db_load_tables
  *
- * PARAMETERS:  filename        - File where table is located
- *              return_table    - Where a pointer to the table is returned
+ * PARAMETERS:  list_head       - List of ACPI tables to load
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Load an ACPI table from a file
+ * DESCRIPTION: Load ACPI tables from a previously constructed table list.
  *
  ******************************************************************************/
 
-acpi_status
-acpi_db_get_table_from_file(char *filename,
-                           struct acpi_table_header **return_table,
-                           u8 must_be_aml_file)
+acpi_status acpi_db_load_tables(struct acpi_new_table_desc *list_head)
 {
-#ifdef ACPI_APPLICATION
        acpi_status status;
+       struct acpi_new_table_desc *table_list_head;
        struct acpi_table_header *table;
-       u8 is_aml_table = TRUE;
-
-       status = acpi_ut_read_table_from_file(filename, &table);
-       if (ACPI_FAILURE(status)) {
-               return (status);
-       }
-
-       if (must_be_aml_file) {
-               is_aml_table = acpi_ut_is_aml_table(table);
-               if (!is_aml_table) {
-                       ACPI_EXCEPTION((AE_INFO, AE_OK,
-                                       "Input for -e is not an AML table: "
-                                       "\"%4.4s\" (must be DSDT/SSDT)",
-                                       table->signature));
-                       return (AE_TYPE);
-               }
-       }
 
-       if (is_aml_table) {
+       /* Load all ACPI tables in the list */
 
-               /* Attempt to recognize and install the table */
+       table_list_head = list_head;
+       while (table_list_head) {
+               table = table_list_head->table;
 
-               status = ae_local_load_table(table);
+               status = acpi_load_table(table);
                if (ACPI_FAILURE(status)) {
                        if (status == AE_ALREADY_EXISTS) {
                                acpi_os_printf
@@ -239,18 +152,12 @@ acpi_db_get_table_from_file(char *filename,
                        return (status);
                }
 
-               acpi_tb_print_table_header(0, table);
-
                fprintf(stderr,
                        "Acpi table [%4.4s] successfully installed and loaded\n",
                        table->signature);
-       }
 
-       acpi_gbl_acpi_hardware_present = FALSE;
-       if (return_table) {
-               *return_table = table;
+               table_list_head = table_list_head->next;
        }
 
-#endif                         /* ACPI_APPLICATION */
        return (AE_OK);
 }
index 0480254437f1a30be42b91a920735b18d2b28f95..6203001baa301507a4e4b893138eca323307b613 100644 (file)
 #include "accommon.h"
 #include "acdebug.h"
 
+#ifdef ACPI_APPLICATION
+#include "acapps.h"
+#endif
+
 #define _COMPONENT          ACPI_CA_DEBUGGER
 ACPI_MODULE_NAME("dbinput")
 
@@ -53,8 +57,6 @@ static u32 acpi_db_get_line(char *input_buffer);
 
 static u32 acpi_db_match_command(char *user_command);
 
-static void acpi_db_single_thread(void);
-
 static void acpi_db_display_command_info(char *command, u8 display_all);
 
 static void acpi_db_display_help(char *command);
@@ -623,9 +625,7 @@ static u32 acpi_db_get_line(char *input_buffer)
 
        /* Uppercase the actual command */
 
-       if (acpi_gbl_db_args[0]) {
-               acpi_ut_strupr(acpi_gbl_db_args[0]);
-       }
+       acpi_ut_strupr(acpi_gbl_db_args[0]);
 
        count = i;
        if (count) {
@@ -1050,11 +1050,17 @@ acpi_db_command_dispatch(char *input_buffer,
                acpi_db_close_debug_file();
                break;
 
-       case CMD_LOAD:
+       case CMD_LOAD:{
+                       struct acpi_new_table_desc *list_head = NULL;
 
-               status =
-                   acpi_db_get_table_from_file(acpi_gbl_db_args[1], NULL,
-                                               FALSE);
+                       status =
+                           ac_get_all_tables_from_file(acpi_gbl_db_args[1],
+                                                       ACPI_GET_ALL_TABLES,
+                                                       &list_head);
+                       if (ACPI_SUCCESS(status)) {
+                               acpi_db_load_tables(list_head);
+                       }
+               }
                break;
 
        case CMD_OPEN:
@@ -1149,55 +1155,16 @@ acpi_db_command_dispatch(char *input_buffer,
 
 void ACPI_SYSTEM_XFACE acpi_db_execute_thread(void *context)
 {
-       acpi_status status = AE_OK;
-       acpi_status Mstatus;
-
-       while (status != AE_CTRL_TERMINATE && !acpi_gbl_db_terminate_loop) {
-               acpi_gbl_method_executing = FALSE;
-               acpi_gbl_step_to_next_call = FALSE;
-
-               Mstatus = acpi_os_acquire_mutex(acpi_gbl_db_command_ready,
-                                               ACPI_WAIT_FOREVER);
-               if (ACPI_FAILURE(Mstatus)) {
-                       return;
-               }
-
-               status =
-                   acpi_db_command_dispatch(acpi_gbl_db_line_buf, NULL, NULL);
 
-               acpi_os_release_mutex(acpi_gbl_db_command_complete);
-       }
+       (void)acpi_db_user_commands();
        acpi_gbl_db_threads_terminated = TRUE;
 }
 
-/*******************************************************************************
- *
- * FUNCTION:    acpi_db_single_thread
- *
- * PARAMETERS:  None
- *
- * RETURN:      None
- *
- * DESCRIPTION: Debugger execute thread. Waits for a command line, then
- *              simply dispatches it.
- *
- ******************************************************************************/
-
-static void acpi_db_single_thread(void)
-{
-
-       acpi_gbl_method_executing = FALSE;
-       acpi_gbl_step_to_next_call = FALSE;
-
-       (void)acpi_db_command_dispatch(acpi_gbl_db_line_buf, NULL, NULL);
-}
-
 /*******************************************************************************
  *
  * FUNCTION:    acpi_db_user_commands
  *
- * PARAMETERS:  prompt              - User prompt (depends on mode)
- *              op                  - Current executing parse op
+ * PARAMETERS:  None
  *
  * RETURN:      None
  *
@@ -1206,7 +1173,7 @@ static void acpi_db_single_thread(void)
  *
  ******************************************************************************/
 
-acpi_status acpi_db_user_commands(char prompt, union acpi_parse_object *op)
+acpi_status acpi_db_user_commands(void)
 {
        acpi_status status = AE_OK;
 
@@ -1216,52 +1183,31 @@ acpi_status acpi_db_user_commands(char prompt, union acpi_parse_object *op)
 
        while (!acpi_gbl_db_terminate_loop) {
 
-               /* Force output to console until a command is entered */
-
-               acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
-
-               /* Different prompt if method is executing */
-
-               if (!acpi_gbl_method_executing) {
-                       acpi_os_printf("%1c ", ACPI_DEBUGGER_COMMAND_PROMPT);
-               } else {
-                       acpi_os_printf("%1c ", ACPI_DEBUGGER_EXECUTE_PROMPT);
-               }
+               /* Wait the readiness of the command */
 
-               /* Get the user input line */
-
-               status = acpi_os_get_line(acpi_gbl_db_line_buf,
-                                         ACPI_DB_LINE_BUFFER_SIZE, NULL);
+               status = acpi_os_wait_command_ready();
                if (ACPI_FAILURE(status)) {
-                       ACPI_EXCEPTION((AE_INFO, status,
-                                       "While parsing command line"));
-                       return (status);
+                       break;
                }
 
-               /* Check for single or multithreaded debug */
+               /* Just call to the command line interpreter */
 
-               if (acpi_gbl_debugger_configuration & DEBUGGER_MULTI_THREADED) {
-                       /*
-                        * Signal the debug thread that we have a command to execute,
-                        * and wait for the command to complete.
-                        */
-                       acpi_os_release_mutex(acpi_gbl_db_command_ready);
-                       if (ACPI_FAILURE(status)) {
-                               return (status);
-                       }
+               acpi_gbl_method_executing = FALSE;
+               acpi_gbl_step_to_next_call = FALSE;
 
-                       status =
-                           acpi_os_acquire_mutex(acpi_gbl_db_command_complete,
-                                                 ACPI_WAIT_FOREVER);
-                       if (ACPI_FAILURE(status)) {
-                               return (status);
-                       }
-               } else {
-                       /* Just call to the command line interpreter */
+               (void)acpi_db_command_dispatch(acpi_gbl_db_line_buf, NULL,
+                                              NULL);
+
+               /* Notify the completion of the command */
 
-                       acpi_db_single_thread();
+               status = acpi_os_notify_command_complete();
+               if (ACPI_FAILURE(status)) {
+                       break;
                }
        }
 
+       if (ACPI_FAILURE(status) && status != AE_CTRL_TERMINATE) {
+               ACPI_EXCEPTION((AE_INFO, status, "While parsing command line"));
+       }
        return (status);
 }
index 04ff1ebfda5879f3207f29a1413509f567f46f57..4f68dfc6ea551f597589919dae64d740ef73c574 100644 (file)
@@ -438,7 +438,7 @@ acpi_db_walk_for_predefined_names(acpi_handle obj_handle,
                return (AE_OK);
        }
 
-       pathname = acpi_ns_get_external_pathname(node);
+       pathname = acpi_ns_get_normalized_pathname(node, TRUE);
        if (!pathname) {
                return (AE_OK);
        }
index 4ba0a20811ebb7ffe34afcdd8b5f7ae1322986a7..de255d9759413a406c50fc3599df83ba24bdd4d4 100644 (file)
@@ -382,6 +382,7 @@ acpi_status acpi_db_display_statistics(char *type_arg)
                                       acpi_gbl_node_type_count[i],
                                       acpi_gbl_obj_type_count[i]);
                }
+
                acpi_os_printf("%16.16s % 10ld% 10ld\n", "Misc/Unknown",
                               acpi_gbl_node_type_count_misc,
                               acpi_gbl_obj_type_count_misc);
index 10ea8bf9b8101090c22d4e20dbcd3ce81ec93aac..68b4e8d9e1d6c42e189d374aed20963936194bad 100644 (file)
@@ -953,7 +953,7 @@ acpi_db_evaluate_one_predefined_name(acpi_handle obj_handle,
                return (AE_OK);
        }
 
-       pathname = acpi_ns_get_external_pathname(node);
+       pathname = acpi_ns_get_normalized_pathname(node, TRUE);
        if (!pathname) {
                return (AE_OK);
        }
index 86790e0801395757040a903fd5d984855846204c..8c85d85a9cb2cb1b415da88e95d88a7ff4f8f788 100644 (file)
@@ -173,6 +173,7 @@ void acpi_db_dump_external_object(union acpi_object *obj_desc, u32 level)
                        if (obj_desc->buffer.length > 16) {
                                acpi_os_printf("\n");
                        }
+
                        acpi_ut_debug_dump_buffer(ACPI_CAST_PTR
                                                  (u8,
                                                   obj_desc->buffer.pointer),
index 342298a6e10fe24f290271d465fdc79fdffd34f6..d7ff58e8c23363f4680959eb51661ae33bab4703 100644 (file)
@@ -85,46 +85,21 @@ acpi_db_start_command(struct acpi_walk_state *walk_state,
 
        acpi_gbl_method_executing = TRUE;
        status = AE_CTRL_TRUE;
-       while (status == AE_CTRL_TRUE) {
-               if (acpi_gbl_debugger_configuration == DEBUGGER_MULTI_THREADED) {
-
-                       /* Handshake with the front-end that gets user command lines */
-
-                       acpi_os_release_mutex(acpi_gbl_db_command_complete);
-
-                       status =
-                           acpi_os_acquire_mutex(acpi_gbl_db_command_ready,
-                                                 ACPI_WAIT_FOREVER);
-                       if (ACPI_FAILURE(status)) {
-                               return (status);
-                       }
-               } else {
-                       /* Single threaded, we must get a command line ourselves */
-
-                       /* Force output to console until a command is entered */
 
-                       acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
+       while (status == AE_CTRL_TRUE) {
 
-                       /* Different prompt if method is executing */
+               /* Notify the completion of the command */
 
-                       if (!acpi_gbl_method_executing) {
-                               acpi_os_printf("%1c ",
-                                              ACPI_DEBUGGER_COMMAND_PROMPT);
-                       } else {
-                               acpi_os_printf("%1c ",
-                                              ACPI_DEBUGGER_EXECUTE_PROMPT);
-                       }
+               status = acpi_os_notify_command_complete();
+               if (ACPI_FAILURE(status)) {
+                       goto error_exit;
+               }
 
-                       /* Get the user input line */
+               /* Wait the readiness of the command */
 
-                       status = acpi_os_get_line(acpi_gbl_db_line_buf,
-                                                 ACPI_DB_LINE_BUFFER_SIZE,
-                                                 NULL);
-                       if (ACPI_FAILURE(status)) {
-                               ACPI_EXCEPTION((AE_INFO, status,
-                                               "While parsing command line"));
-                               return (status);
-                       }
+               status = acpi_os_wait_command_ready();
+               if (ACPI_FAILURE(status)) {
+                       goto error_exit;
                }
 
                status =
@@ -134,9 +109,44 @@ acpi_db_start_command(struct acpi_walk_state *walk_state,
 
        /* acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); */
 
+error_exit:
+       if (ACPI_FAILURE(status) && status != AE_CTRL_TERMINATE) {
+               ACPI_EXCEPTION((AE_INFO, status,
+                               "While parsing/handling command line"));
+       }
        return (status);
 }
 
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_db_signal_break_point
+ *
+ * PARAMETERS:  walk_state      - Current walk
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Called for AML_BREAK_POINT_OP
+ *
+ ******************************************************************************/
+
+void acpi_db_signal_break_point(struct acpi_walk_state *walk_state)
+{
+
+#ifndef ACPI_APPLICATION
+       if (acpi_gbl_db_thread_id != acpi_os_get_thread_id()) {
+               return;
+       }
+#endif
+
+       /*
+        * Set the single-step flag. This will cause the debugger (if present)
+        * to break to the console within the AML debugger at the start of the
+        * next AML instruction.
+        */
+       acpi_gbl_cm_single_step = TRUE;
+       acpi_os_printf("**break** Executed AML BreakPoint opcode\n");
+}
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_db_single_step
@@ -420,15 +430,7 @@ acpi_status acpi_initialize_debugger(void)
 
                /* These were created with one unit, grab it */
 
-               status = acpi_os_acquire_mutex(acpi_gbl_db_command_complete,
-                                              ACPI_WAIT_FOREVER);
-               if (ACPI_FAILURE(status)) {
-                       acpi_os_printf("Could not get debugger mutex\n");
-                       return_ACPI_STATUS(status);
-               }
-
-               status = acpi_os_acquire_mutex(acpi_gbl_db_command_ready,
-                                              ACPI_WAIT_FOREVER);
+               status = acpi_os_initialize_command_signals();
                if (ACPI_FAILURE(status)) {
                        acpi_os_printf("Could not get debugger mutex\n");
                        return_ACPI_STATUS(status);
@@ -473,13 +475,14 @@ void acpi_terminate_debugger(void)
        acpi_gbl_db_terminate_loop = TRUE;
 
        if (acpi_gbl_debugger_configuration & DEBUGGER_MULTI_THREADED) {
-               acpi_os_release_mutex(acpi_gbl_db_command_ready);
 
                /* Wait the AML Debugger threads */
 
                while (!acpi_gbl_db_threads_terminated) {
                        acpi_os_sleep(100);
                }
+
+               acpi_os_terminate_command_signals();
        }
 
        if (acpi_gbl_db_buffer) {
index e2ab59e39162763e38121d027882cd925dd7ec2f..76cfced31f9fc8501fbcc3fa5859c60331d32727 100644 (file)
@@ -194,8 +194,8 @@ acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc)
        extra_desc = acpi_ns_get_secondary_object(obj_desc);
        node = obj_desc->buffer_field.node;
 
-       ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname(ACPI_TYPE_BUFFER_FIELD,
-                                                     node, NULL));
+       ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
+                       (ACPI_TYPE_BUFFER_FIELD, node, NULL));
 
        ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BufferField Arg Init\n",
                          acpi_ut_get_node_name(node)));
@@ -385,7 +385,8 @@ acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc)
        ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
                        (ACPI_TYPE_REGION, node, NULL));
 
-       ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] OpRegion Arg Init at AML %p\n",
+       ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+                         "[%4.4s] OpRegion Arg Init at AML %p\n",
                          acpi_ut_get_node_name(node),
                          extra_desc->extra.aml_start));
 
index 435fc16e2f8323dad308dc546b96971c97508e55..06a6f7f3af5258b67e72bf5b578b21d810f92735 100644 (file)
@@ -47,6 +47,7 @@
 #include "amlcode.h"
 #include "acdispat.h"
 #include "acinterp.h"
+#include "acdebug.h"
 
 #define _COMPONENT          ACPI_DISPATCHER
 ACPI_MODULE_NAME("dscontrol")
@@ -348,14 +349,7 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state,
 
        case AML_BREAK_POINT_OP:
 
-               /*
-                * Set the single-step flag. This will cause the debugger (if present)
-                * to break to the console within the AML debugger at the start of the
-                * next AML instruction.
-                */
-               ACPI_DEBUGGER_EXEC(acpi_gbl_cm_single_step = TRUE);
-               ACPI_DEBUGGER_EXEC(acpi_os_printf
-                                  ("**break** Executed AML BreakPoint opcode\n"));
+               acpi_db_signal_break_point(walk_state);
 
                /* Call to the OSL in case OS wants a piece of the action */
 
index 309556efc55396c5b2f013e62240643c2d7c8ecc..1eb82bd7ee1699392e12f86bbc8cafa8eaa7ed6a 100644 (file)
@@ -161,6 +161,7 @@ acpi_ds_dump_method_stack(acpi_status status,
        ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
                          "\n**** Exception %s during execution of method ",
                          acpi_format_exception(status)));
+
        acpi_ds_print_node_pathname(walk_state->method_node, NULL);
 
        /* Display stack of executing methods */
@@ -203,8 +204,8 @@ acpi_ds_dump_method_stack(acpi_status status,
                } else {
                        /*
                         * This method has called another method
-                        * NOTE: the method call parse subtree is already deleted at this
-                        * point, so we cannot disassemble the method invocation.
+                        * NOTE: the method call parse subtree is already deleted at
+                        * this point, so we cannot disassemble the method invocation.
                         */
                        ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH,
                                              "Call to method "));
index 20de148594fdc0459e1ddd589abe999f71c0003f..6bca0ec42dbdcfde8d9d03e7992a3ee0d79b4f8d 100644 (file)
@@ -106,6 +106,7 @@ acpi_ds_create_external_region(acpi_status lookup_status,
         * insert the name into the namespace.
         */
        acpi_dm_add_op_to_external_list(op, path, ACPI_TYPE_REGION, 0, 0);
+
        status = acpi_ns_lookup(walk_state->scope_info, path, ACPI_TYPE_REGION,
                                ACPI_IMODE_LOAD_PASS1, ACPI_NS_SEARCH_PARENT,
                                walk_state, node);
@@ -202,11 +203,10 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op,
 
                /* Enter the name_string into the namespace */
 
-               status =
-                   acpi_ns_lookup(walk_state->scope_info,
-                                  arg->common.value.string, ACPI_TYPE_ANY,
-                                  ACPI_IMODE_LOAD_PASS1, flags, walk_state,
-                                  &node);
+               status = acpi_ns_lookup(walk_state->scope_info,
+                                       arg->common.value.string, ACPI_TYPE_ANY,
+                                       ACPI_IMODE_LOAD_PASS1, flags,
+                                       walk_state, &node);
                if (ACPI_FAILURE(status)) {
                        ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
                        return_ACPI_STATUS(status);
@@ -244,8 +244,8 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op,
        }
 
        /*
-        * Remember location in AML stream of the field unit opcode and operands --
-        * since the buffer and index operands must be evaluated.
+        * Remember location in AML stream of the field unit opcode and operands
+        * -- since the buffer and index operands must be evaluated.
         */
        second_desc = obj_desc->common.next_object;
        second_desc->extra.aml_start = op->named.data;
@@ -310,8 +310,8 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
                switch (arg->common.aml_opcode) {
                case AML_INT_RESERVEDFIELD_OP:
 
-                       position = (u64) info->field_bit_position
-                           + (u64) arg->common.value.size;
+                       position = (u64)info->field_bit_position +
+                           (u64)arg->common.value.size;
 
                        if (position > ACPI_UINT32_MAX) {
                                ACPI_ERROR((AE_INFO,
@@ -344,13 +344,13 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
 
                        /* access_attribute (attrib_quick, attrib_byte, etc.) */
 
-                       info->attribute =
-                           (u8)((arg->common.value.integer >> 8) & 0xFF);
+                       info->attribute = (u8)
+                           ((arg->common.value.integer >> 8) & 0xFF);
 
                        /* access_length (for serial/buffer protocols) */
 
-                       info->access_length =
-                           (u8)((arg->common.value.integer >> 16) & 0xFF);
+                       info->access_length = (u8)
+                           ((arg->common.value.integer >> 16) & 0xFF);
                        break;
 
                case AML_INT_CONNECTION_OP:
@@ -425,8 +425,8 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
 
                        /* Keep track of bit position for the next field */
 
-                       position = (u64) info->field_bit_position
-                           + (u64) arg->common.value.size;
+                       position = (u64)info->field_bit_position +
+                           (u64)arg->common.value.size;
 
                        if (position > ACPI_UINT32_MAX) {
                                ACPI_ERROR((AE_INFO,
@@ -716,11 +716,12 @@ acpi_ds_create_bank_field(union acpi_parse_object *op,
 
        /*
         * Use Info.data_register_node to store bank_field Op
-        * It's safe because data_register_node will never be used when create bank field
-        * We store aml_start and aml_length in the bank_field Op for late evaluation
-        * Used in acpi_ex_prep_field_value(Info)
+        * It's safe because data_register_node will never be used when create
+        * bank field \we store aml_start and aml_length in the bank_field Op for
+        * late evaluation. Used in acpi_ex_prep_field_value(Info)
         *
-        * TBD: Or, should we add a field in struct acpi_create_field_info, like "void *ParentOp"?
+        * TBD: Or, should we add a field in struct acpi_create_field_info, like
+        * "void *ParentOp"?
         */
        info.data_register_node = (struct acpi_namespace_node *)op;
 
index 920f1b199bc6fdc24f6e0dea9134c9109692a6e3..c1d8af8a8aaf19a66de381761509d3662b048cf6 100644 (file)
@@ -247,7 +247,7 @@ acpi_ds_initialize_objects(u32 table_index,
        /* Summary of objects initialized */
 
        ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
-                             "Table [%4.4s:%8.8s] (id %.2X) - %4u Objects with %3u Devices, "
+                             "Table [%4.4s: %-8.8s] (id %.2X) - %4u Objects with %3u Devices, "
                              "%3u Regions, %4u Methods (%u/%u/%u Serial/Non/Cvt)\n",
                              table->signature, table->oem_table_id, owner_id,
                              info.object_count, info.device_count,
index bc32f3194afe1675bdc767d9f1dbd26a2959b3aa..6585e8e37c8e015adb791d4a1f9b1e67bdd84172 100644 (file)
@@ -118,10 +118,9 @@ acpi_ds_auto_serialize_method(struct acpi_namespace_node *node,
                return_ACPI_STATUS(AE_NO_MEMORY);
        }
 
-       status =
-           acpi_ds_init_aml_walk(walk_state, op, node,
-                                 obj_desc->method.aml_start,
-                                 obj_desc->method.aml_length, NULL, 0);
+       status = acpi_ds_init_aml_walk(walk_state, op, node,
+                                      obj_desc->method.aml_start,
+                                      obj_desc->method.aml_length, NULL, 0);
        if (ACPI_FAILURE(status)) {
                acpi_ds_delete_walk_state(walk_state);
                acpi_ps_free_op(op);
@@ -375,7 +374,8 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node,
                    && (walk_state->thread->current_sync_level >
                        obj_desc->method.mutex->mutex.sync_level)) {
                        ACPI_ERROR((AE_INFO,
-                                   "Cannot acquire Mutex for method [%4.4s], current SyncLevel is too large (%u)",
+                                   "Cannot acquire Mutex for method [%4.4s]"
+                                   ", current SyncLevel is too large (%u)",
                                    acpi_ut_get_node_name(method_node),
                                    walk_state->thread->current_sync_level));
 
@@ -411,8 +411,19 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node,
 
                                obj_desc->method.mutex->mutex.thread_id =
                                    walk_state->thread->thread_id;
-                               walk_state->thread->current_sync_level =
-                                   obj_desc->method.sync_level;
+
+                               /*
+                                * Update the current sync_level only if this is not an auto-
+                                * serialized method. In the auto case, we have to ignore
+                                * the sync level for the method mutex (created for the
+                                * auto-serialization) because we have no idea of what the
+                                * sync level should be. Therefore, just ignore it.
+                                */
+                               if (!(obj_desc->method.info_flags &
+                                     ACPI_METHOD_IGNORE_SYNC_LEVEL)) {
+                                       walk_state->thread->current_sync_level =
+                                           obj_desc->method.sync_level;
+                               }
                        } else {
                                obj_desc->method.mutex->mutex.
                                    original_sync_level =
@@ -501,16 +512,18 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread,
 
        /* Init for new method, possibly wait on method mutex */
 
-       status = acpi_ds_begin_method_execution(method_node, obj_desc,
-                                               this_walk_state);
+       status =
+           acpi_ds_begin_method_execution(method_node, obj_desc,
+                                          this_walk_state);
        if (ACPI_FAILURE(status)) {
                return_ACPI_STATUS(status);
        }
 
        /* Begin method parse/execution. Create a new walk state */
 
-       next_walk_state = acpi_ds_create_walk_state(obj_desc->method.owner_id,
-                                                   NULL, obj_desc, thread);
+       next_walk_state =
+           acpi_ds_create_walk_state(obj_desc->method.owner_id, NULL, obj_desc,
+                                     thread);
        if (!next_walk_state) {
                status = AE_NO_MEMORY;
                goto cleanup;
@@ -797,7 +810,8 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
                    info_flags & ACPI_METHOD_SERIALIZED_PENDING) {
                        if (walk_state) {
                                ACPI_INFO((AE_INFO,
-                                          "Marking method %4.4s as Serialized because of AE_ALREADY_EXISTS error",
+                                          "Marking method %4.4s as Serialized "
+                                          "because of AE_ALREADY_EXISTS error",
                                           walk_state->method_node->name.
                                           ascii));
                        }
@@ -815,6 +829,7 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
                         */
                        method_desc->method.info_flags &=
                            ~ACPI_METHOD_SERIALIZED_PENDING;
+
                        method_desc->method.info_flags |=
                            (ACPI_METHOD_SERIALIZED |
                             ACPI_METHOD_IGNORE_SYNC_LEVEL);
index 2e4c42b377eca5a0825d0a1382bdc07f5ded213f..03c44f2ac7b7235440e18af97e0f74d968ebaeb8 100644 (file)
@@ -99,6 +99,7 @@ void acpi_ds_method_data_init(struct acpi_walk_state *walk_state)
        for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++) {
                ACPI_MOVE_32_TO_32(&walk_state->arguments[i].name,
                                   NAMEOF_ARG_NTE);
+
                walk_state->arguments[i].name.integer |= (i << 24);
                walk_state->arguments[i].descriptor_type = ACPI_DESC_TYPE_NAMED;
                walk_state->arguments[i].type = ACPI_TYPE_ANY;
@@ -201,7 +202,7 @@ acpi_ds_method_data_init_args(union acpi_operand_object **params,
 
        if (!params) {
                ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
-                                 "No param list passed to method\n"));
+                                 "No parameter list passed to method\n"));
                return_ACPI_STATUS(AE_OK);
        }
 
@@ -214,9 +215,9 @@ acpi_ds_method_data_init_args(union acpi_operand_object **params,
                 * Store the argument in the method/walk descriptor.
                 * Do not copy the arg in order to implement call by reference
                 */
-               status = acpi_ds_method_data_set_value(ACPI_REFCLASS_ARG, index,
-                                                      params[index],
-                                                      walk_state);
+               status =
+                   acpi_ds_method_data_set_value(ACPI_REFCLASS_ARG, index,
+                                                 params[index], walk_state);
                if (ACPI_FAILURE(status)) {
                        return_ACPI_STATUS(status);
                }
@@ -610,11 +611,11 @@ acpi_ds_store_object_to_local(u8 type,
                         * do the indirect store
                         */
                        if ((ACPI_GET_DESCRIPTOR_TYPE(current_obj_desc) ==
-                            ACPI_DESC_TYPE_OPERAND)
-                           && (current_obj_desc->common.type ==
-                               ACPI_TYPE_LOCAL_REFERENCE)
-                           && (current_obj_desc->reference.class ==
-                               ACPI_REFCLASS_REFOF)) {
+                            ACPI_DESC_TYPE_OPERAND) &&
+                           (current_obj_desc->common.type ==
+                            ACPI_TYPE_LOCAL_REFERENCE) &&
+                           (current_obj_desc->reference.class ==
+                            ACPI_REFCLASS_REFOF)) {
                                ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
                                                  "Arg (%p) is an ObjRef(Node), storing in node %p\n",
                                                  new_obj_desc,
@@ -638,6 +639,7 @@ acpi_ds_store_object_to_local(u8 type,
                                if (new_obj_desc != obj_desc) {
                                        acpi_ut_remove_reference(new_obj_desc);
                                }
+
                                return_ACPI_STATUS(status);
                        }
                }
index 2beb7fd674ae14a20b43031254d874afbd859886..302c91f5377b19d0a5b85febb5d26375d3642f5c 100644 (file)
@@ -463,10 +463,10 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
                                                  arg->common.node);
                        }
                } else {
-                       status = acpi_ds_build_internal_object(walk_state, arg,
-                                                              &obj_desc->
-                                                              package.
-                                                              elements[i]);
+                       status =
+                           acpi_ds_build_internal_object(walk_state, arg,
+                                                         &obj_desc->package.
+                                                         elements[i]);
                }
 
                if (*obj_desc_ptr) {
@@ -525,7 +525,8 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
                }
 
                ACPI_INFO((AE_INFO,
-                          "Actual Package length (%u) is larger than NumElements field (%u), truncated",
+                          "Actual Package length (%u) is larger than "
+                          "NumElements field (%u), truncated",
                           i, element_count));
        } else if (i < element_count) {
                /*
@@ -533,7 +534,8 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
                 * Note: this is not an error, the package is padded out with NULLs.
                 */
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                                 "Package List length (%u) smaller than NumElements count (%u), padded with null elements\n",
+                                 "Package List length (%u) smaller than NumElements "
+                                 "count (%u), padded with null elements\n",
                                  i, element_count));
        }
 
@@ -584,8 +586,9 @@ acpi_ds_create_node(struct acpi_walk_state *walk_state,
 
        /* Build an internal object for the argument(s) */
 
-       status = acpi_ds_build_internal_object(walk_state, op->common.value.arg,
-                                              &obj_desc);
+       status =
+           acpi_ds_build_internal_object(walk_state, op->common.value.arg,
+                                         &obj_desc);
        if (ACPI_FAILURE(status)) {
                return_ACPI_STATUS(status);
        }
index 81d7b9863e3213855790536b41b550a48e727375..1edd66f18907905a7d73b7e011bcf6f9e1168daf 100644 (file)
@@ -243,8 +243,9 @@ acpi_ds_init_buffer_field(u16 aml_opcode,
         * For field_flags, use LOCK_RULE = 0 (NO_LOCK),
         * UPDATE_RULE = 0 (UPDATE_PRESERVE)
         */
-       status = acpi_ex_prep_common_field_object(obj_desc, field_flags, 0,
-                                                 bit_offset, bit_count);
+       status =
+           acpi_ex_prep_common_field_object(obj_desc, field_flags, 0,
+                                            bit_offset, bit_count);
        if (ACPI_FAILURE(status)) {
                goto cleanup;
        }
@@ -330,8 +331,9 @@ acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state,
 
        /* Resolve the operands */
 
-       status = acpi_ex_resolve_operands(op->common.aml_opcode,
-                                         ACPI_WALK_OPERANDS, walk_state);
+       status =
+           acpi_ex_resolve_operands(op->common.aml_opcode, ACPI_WALK_OPERANDS,
+                                    walk_state);
        if (ACPI_FAILURE(status)) {
                ACPI_ERROR((AE_INFO, "(%s) bad operand(s), status 0x%X",
                            acpi_ps_get_opcode_name(op->common.aml_opcode),
@@ -414,8 +416,9 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
 
        /* Resolve the length and address operands to numbers */
 
-       status = acpi_ex_resolve_operands(op->common.aml_opcode,
-                                         ACPI_WALK_OPERANDS, walk_state);
+       status =
+           acpi_ex_resolve_operands(op->common.aml_opcode, ACPI_WALK_OPERANDS,
+                                    walk_state);
        if (ACPI_FAILURE(status)) {
                return_ACPI_STATUS(status);
        }
@@ -452,7 +455,6 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
        /* Now the address and length are valid for this opregion */
 
        obj_desc->region.flags |= AOPOBJ_DATA_VALID;
-
        return_ACPI_STATUS(status);
 }
 
@@ -510,8 +512,9 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state,
         * Resolve the Signature string, oem_id string,
         * and oem_table_id string operands
         */
-       status = acpi_ex_resolve_operands(op->common.aml_opcode,
-                                         ACPI_WALK_OPERANDS, walk_state);
+       status =
+           acpi_ex_resolve_operands(op->common.aml_opcode, ACPI_WALK_OPERANDS,
+                                    walk_state);
        if (ACPI_FAILURE(status)) {
                goto cleanup;
        }
index ebc577baeaf9fb14e29796a9286d22ca107fa6b5..fa8e2920a3ef5b0706a3035fd430d96c7d6d21bc 100644 (file)
@@ -245,9 +245,9 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
                         * we will use the return value
                         */
                        if ((walk_state->control_state->common.state ==
-                            ACPI_CONTROL_PREDICATE_EXECUTING)
-                           && (walk_state->control_state->control.
-                               predicate_op == op)) {
+                            ACPI_CONTROL_PREDICATE_EXECUTING) &&
+                           (walk_state->control_state->control.predicate_op ==
+                            op)) {
                                goto result_used;
                        }
                        break;
@@ -481,10 +481,9 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
 
                /* Get the entire name string from the AML stream */
 
-               status =
-                   acpi_ex_get_name_string(ACPI_TYPE_ANY,
-                                           arg->common.value.buffer,
-                                           &name_string, &name_length);
+               status = acpi_ex_get_name_string(ACPI_TYPE_ANY,
+                                                arg->common.value.buffer,
+                                                &name_string, &name_length);
 
                if (ACPI_FAILURE(status)) {
                        return_ACPI_STATUS(status);
@@ -503,9 +502,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
                 */
                if ((walk_state->deferred_node) &&
                    (walk_state->deferred_node->type == ACPI_TYPE_BUFFER_FIELD)
-                   && (arg_index ==
-                       (u32) ((walk_state->opcode ==
-                               AML_CREATE_FIELD_OP) ? 3 : 2))) {
+                   && (arg_index == (u32)
+                       ((walk_state->opcode == AML_CREATE_FIELD_OP) ? 3 : 2))) {
                        obj_desc =
                            ACPI_CAST_PTR(union acpi_operand_object,
                                          walk_state->deferred_node);
@@ -522,9 +520,10 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
                        op_info =
                            acpi_ps_get_opcode_info(parent_op->common.
                                                    aml_opcode);
-                       if ((op_info->flags & AML_NSNODE)
-                           && (parent_op->common.aml_opcode !=
-                               AML_INT_METHODCALL_OP)
+
+                       if ((op_info->flags & AML_NSNODE) &&
+                           (parent_op->common.aml_opcode !=
+                            AML_INT_METHODCALL_OP)
                            && (parent_op->common.aml_opcode != AML_REGION_OP)
                            && (parent_op->common.aml_opcode !=
                                AML_INT_NAMEPATH_OP)) {
@@ -605,8 +604,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
                if (ACPI_FAILURE(status)) {
                        return_ACPI_STATUS(status);
                }
-               ACPI_DEBUGGER_EXEC(acpi_db_display_argument_object
-                                  (obj_desc, walk_state));
+
+               acpi_db_display_argument_object(obj_desc, walk_state);
        } else {
                /* Check for null name case */
 
@@ -633,15 +632,16 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
                        return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
                }
 
-               if ((op_info->flags & AML_HAS_RETVAL)
-                   || (arg->common.flags & ACPI_PARSEOP_IN_STACK)) {
+               if ((op_info->flags & AML_HAS_RETVAL) ||
+                   (arg->common.flags & ACPI_PARSEOP_IN_STACK)) {
                        ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
                                          "Argument previously created, already stacked\n"));
 
-                       ACPI_DEBUGGER_EXEC(acpi_db_display_argument_object
-                                          (walk_state->
-                                           operands[walk_state->num_operands -
-                                                    1], walk_state));
+                       acpi_db_display_argument_object(walk_state->
+                                                       operands[walk_state->
+                                                                num_operands -
+                                                                1],
+                                                       walk_state);
 
                        /*
                         * Use value that was already previously returned
@@ -685,8 +685,7 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
                        return_ACPI_STATUS(status);
                }
 
-               ACPI_DEBUGGER_EXEC(acpi_db_display_argument_object
-                                  (obj_desc, walk_state));
+               acpi_db_display_argument_object(obj_desc, walk_state);
        }
 
        return_ACPI_STATUS(AE_OK);
index df54d46225cdf6e4401234300cc3db195993a337..ed2f1d3620923c21c47587ff297cf3a8ed24987b 100644 (file)
@@ -172,14 +172,14 @@ acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state,
 
 cleanup:
 
-       ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Completed a predicate eval=%X Op=%p\n",
+       ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+                         "Completed a predicate eval=%X Op=%p\n",
                          walk_state->control_state->common.value,
                          walk_state->op));
 
        /* Break to debugger to display result */
 
-       ACPI_DEBUGGER_EXEC(acpi_db_display_result_object
-                          (local_obj_desc, walk_state));
+       acpi_db_display_result_object(local_obj_desc, walk_state);
 
        /*
         * Delete the predicate result object (we know that
@@ -264,8 +264,8 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state,
            (walk_state->control_state->common.state ==
             ACPI_CONTROL_CONDITIONAL_EXECUTING)) {
                ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
-                                 "Exec predicate Op=%p State=%p\n", op,
-                                 walk_state));
+                                 "Exec predicate Op=%p State=%p\n",
+                                 op, walk_state));
 
                walk_state->control_state->common.state =
                    ACPI_CONTROL_PREDICATE_EXECUTING;
@@ -386,11 +386,10 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
 
        /* Call debugger for single step support (DEBUG build only) */
 
-       ACPI_DEBUGGER_EXEC(status =
-                          acpi_db_single_step(walk_state, op, op_class));
-       ACPI_DEBUGGER_EXEC(if (ACPI_FAILURE(status)) {
-                          return_ACPI_STATUS(status);}
-       ) ;
+       status = acpi_db_single_step(walk_state, op, op_class);
+       if (ACPI_FAILURE(status)) {
+               return_ACPI_STATUS(status);
+       }
 
        /* Decode the Opcode Class */
 
@@ -502,9 +501,8 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
                                                  "Method Reference in a Package, Op=%p\n",
                                                  op));
 
-                               op->common.node =
-                                   (struct acpi_namespace_node *)op->asl.value.
-                                   arg->asl.node;
+                               op->common.node = (struct acpi_namespace_node *)
+                                   op->asl.value.arg->asl.node;
                                acpi_ut_add_reference(op->asl.value.arg->asl.
                                                      node->object);
                                return_ACPI_STATUS(AE_OK);
@@ -586,8 +584,8 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
                                 * Put the Node on the object stack (Contains the ACPI Name
                                 * of this object)
                                 */
-                               walk_state->operands[0] =
-                                   (void *)op->common.parent->common.node;
+                               walk_state->operands[0] = (void *)
+                                   op->common.parent->common.node;
                                walk_state->num_operands = 1;
 
                                status = acpi_ds_create_node(walk_state,
@@ -692,7 +690,8 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
                default:
 
                        ACPI_ERROR((AE_INFO,
-                                   "Unimplemented opcode, class=0x%X type=0x%X Opcode=0x%X Op=%p",
+                                   "Unimplemented opcode, class=0x%X "
+                                   "type=0x%X Opcode=0x%X Op=%p",
                                    op_class, op_type, op->common.aml_opcode,
                                    op));
 
@@ -728,8 +727,8 @@ cleanup:
 
                /* Break to debugger to display result */
 
-               ACPI_DEBUGGER_EXEC(acpi_db_display_result_object
-                                  (walk_state->result_obj, walk_state));
+               acpi_db_display_result_object(walk_state->result_obj,
+                                             walk_state);
 
                /*
                 * Delete the result op if and only if:
index 097188a6b1c1bb23d5ede8f940254cc93309d443..b3254742aaf67032156c13499f237f14b74a7197 100644 (file)
@@ -476,13 +476,9 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state)
                        status =
                            acpi_ex_create_region(op->named.data,
                                                  op->named.length,
-                                                 (acpi_adr_space_type) ((op->
-                                                                         common.
-                                                                         value.
-                                                                         arg)->
-                                                                        common.
-                                                                        value.
-                                                                        integer),
+                                                 (acpi_adr_space_type)
+                                                 ((op->common.value.arg)->
+                                                  common.value.integer),
                                                  walk_state);
                        if (ACPI_FAILURE(status)) {
                                return_ACPI_STATUS(status);
index e2c08cd79aca7a64bcf6b7c8107c8ed0d4d601a5..8a32153a111bd0530c1b0452e7f1d6d8e96030bb 100644 (file)
@@ -598,11 +598,10 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
                                 * Executing a method: initialize the region and unlock
                                 * the interpreter
                                 */
-                               status =
-                                   acpi_ex_create_region(op->named.data,
-                                                         op->named.length,
-                                                         region_space,
-                                                         walk_state);
+                               status = acpi_ex_create_region(op->named.data,
+                                                              op->named.length,
+                                                              region_space,
+                                                              walk_state);
                                if (ACPI_FAILURE(status)) {
                                        return_ACPI_STATUS(status);
                                }
@@ -664,6 +663,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
                                                                  length,
                                                                  walk_state);
                                }
+
                                walk_state->operands[0] = NULL;
                                walk_state->num_operands = 0;
 
index 43b3ea40c0b66eb554c297a833bfc507a735238f..2d7a0449346935673821cb22f9a309b6d12d521b 100644 (file)
@@ -77,6 +77,7 @@ void acpi_ds_scope_stack_clear(struct acpi_walk_state *walk_state)
                                  "Popped object type (%s)\n",
                                  acpi_ut_get_type_name(scope_info->common.
                                                        value)));
+
                acpi_ut_delete_generic_state(scope_info);
        }
 }
index ccf7932474475874678a122afcfdad9b02e7d695..112e821a1cecf21f75b7cbc90b7fb1ef4e8e5da5 100644 (file)
@@ -92,8 +92,8 @@ acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info)
                ACPI_SET_BIT(gpe_register_info->enable_for_run,
                             (u8)register_bit);
        }
-       gpe_register_info->enable_mask = gpe_register_info->enable_for_run;
 
+       gpe_register_info->enable_mask = gpe_register_info->enable_for_run;
        return_ACPI_STATUS(AE_OK);
 }
 
index e0f24c50451343ea79f5782d07749c6e4f366fb4..c00a9f2f82d568877fc734de71c722fc9fded00c 100644 (file)
@@ -167,6 +167,7 @@ acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block)
                if (gpe_block->next) {
                        gpe_block->next->previous = gpe_block->previous;
                }
+
                acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
        }
 
index 3a958f3612fe6860ff7082660cf89f30988fee85..fd5ab901223878bd878e679f632d030d915e6788 100644 (file)
@@ -346,6 +346,7 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
                                        ACPI_FREE(notify);
                                        notify = next;
                                }
+
                                gpe_event_info->dispatch.notify_list = NULL;
                                gpe_event_info->flags &=
                                    ~ACPI_GPE_DISPATCH_MASK;
index 74e8595f5a2bbf5dbfc82ff3e5d1e3b99c3b866a..709419c7cde4101ce95775faebfc8302893e3622 100644 (file)
@@ -159,7 +159,7 @@ acpi_ev_has_default_handler(struct acpi_namespace_node *node,
 
        obj_desc = acpi_ns_get_attached_object(node);
        if (obj_desc) {
-               handler_obj = obj_desc->device.handler;
+               handler_obj = obj_desc->common_notify.handler;
 
                /* Walk the linked list of handlers for this object */
 
@@ -247,35 +247,31 @@ acpi_ev_install_handler(acpi_handle obj_handle,
 
                /* Check if this Device already has a handler for this address space */
 
-               next_handler_obj = obj_desc->device.handler;
-               while (next_handler_obj) {
+               next_handler_obj =
+                   acpi_ev_find_region_handler(handler_obj->address_space.
+                                               space_id,
+                                               obj_desc->common_notify.
+                                               handler);
+               if (next_handler_obj) {
 
                        /* Found a handler, is it for the same address space? */
 
-                       if (next_handler_obj->address_space.space_id ==
-                           handler_obj->address_space.space_id) {
-                               ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
-                                                 "Found handler for region [%s] in device %p(%p) "
-                                                 "handler %p\n",
-                                                 acpi_ut_get_region_name
-                                                 (handler_obj->address_space.
-                                                  space_id), obj_desc,
-                                                 next_handler_obj,
-                                                 handler_obj));
-
-                               /*
-                                * Since the object we found it on was a device, then it
-                                * means that someone has already installed a handler for
-                                * the branch of the namespace from this device on. Just
-                                * bail out telling the walk routine to not traverse this
-                                * branch. This preserves the scoping rule for handlers.
-                                */
-                               return (AE_CTRL_DEPTH);
-                       }
-
-                       /* Walk the linked list of handlers attached to this device */
-
-                       next_handler_obj = next_handler_obj->address_space.next;
+                       ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+                                         "Found handler for region [%s] in device %p(%p) handler %p\n",
+                                         acpi_ut_get_region_name(handler_obj->
+                                                                 address_space.
+                                                                 space_id),
+                                         obj_desc, next_handler_obj,
+                                         handler_obj));
+
+                       /*
+                        * Since the object we found it on was a device, then it means
+                        * that someone has already installed a handler for the branch
+                        * of the namespace from this device on. Just bail out telling
+                        * the walk routine to not traverse this branch. This preserves
+                        * the scoping rule for handlers.
+                        */
+                       return (AE_CTRL_DEPTH);
                }
 
                /*
@@ -307,6 +303,44 @@ acpi_ev_install_handler(acpi_handle obj_handle,
        return (status);
 }
 
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ev_find_region_handler
+ *
+ * PARAMETERS:  space_id        - The address space ID
+ *              handler_obj     - Head of the handler object list
+ *
+ * RETURN:      Matching handler object. NULL if space ID not matched
+ *
+ * DESCRIPTION: Search a handler object list for a match on the address
+ *              space ID.
+ *
+ ******************************************************************************/
+
+union acpi_operand_object *acpi_ev_find_region_handler(acpi_adr_space_type
+                                                      space_id,
+                                                      union acpi_operand_object
+                                                      *handler_obj)
+{
+
+       /* Walk the handler list for this device */
+
+       while (handler_obj) {
+
+               /* Same space_id indicates a handler is installed */
+
+               if (handler_obj->address_space.space_id == space_id) {
+                       return (handler_obj);
+               }
+
+               /* Next handler object */
+
+               handler_obj = handler_obj->address_space.next;
+       }
+
+       return (NULL);
+}
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ev_install_space_handler
@@ -332,15 +366,15 @@ acpi_ev_install_space_handler(struct acpi_namespace_node * node,
 {
        union acpi_operand_object *obj_desc;
        union acpi_operand_object *handler_obj;
-       acpi_status status;
+       acpi_status status = AE_OK;
        acpi_object_type type;
        u8 flags = 0;
 
        ACPI_FUNCTION_TRACE(ev_install_space_handler);
 
        /*
-        * This registration is valid for only the types below and the root. This
-        * is where the default handlers get placed.
+        * This registration is valid for only the types below and the root.
+        * The root node is where the default handlers get installed.
         */
        if ((node->type != ACPI_TYPE_DEVICE) &&
            (node->type != ACPI_TYPE_PROCESSOR) &&
@@ -407,38 +441,30 @@ acpi_ev_install_space_handler(struct acpi_namespace_node * node,
        obj_desc = acpi_ns_get_attached_object(node);
        if (obj_desc) {
                /*
-                * The attached device object already exists. Make sure the handler
-                * is not already installed.
+                * The attached device object already exists. Now make sure
+                * the handler is not already installed.
                 */
-               handler_obj = obj_desc->device.handler;
-
-               /* Walk the handler list for this device */
-
-               while (handler_obj) {
-
-                       /* Same space_id indicates a handler already installed */
+               handler_obj = acpi_ev_find_region_handler(space_id,
+                                                         obj_desc->
+                                                         common_notify.
+                                                         handler);
 
-                       if (handler_obj->address_space.space_id == space_id) {
-                               if (handler_obj->address_space.handler ==
-                                   handler) {
-                                       /*
-                                        * It is (relatively) OK to attempt to install the SAME
-                                        * handler twice. This can easily happen with the
-                                        * PCI_Config space.
-                                        */
-                                       status = AE_SAME_HANDLER;
-                                       goto unlock_and_exit;
-                               } else {
-                                       /* A handler is already installed */
-
-                                       status = AE_ALREADY_EXISTS;
-                               }
+               if (handler_obj) {
+                       if (handler_obj->address_space.handler == handler) {
+                               /*
+                                * It is (relatively) OK to attempt to install the SAME
+                                * handler twice. This can easily happen with the
+                                * PCI_Config space.
+                                */
+                               status = AE_SAME_HANDLER;
                                goto unlock_and_exit;
-                       }
+                       } else {
+                               /* A handler is already installed */
 
-                       /* Walk the linked list of handlers */
+                               status = AE_ALREADY_EXISTS;
+                       }
 
-                       handler_obj = handler_obj->address_space.next;
+                       goto unlock_and_exit;
                }
        } else {
                ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
@@ -477,7 +503,8 @@ acpi_ev_install_space_handler(struct acpi_namespace_node * node,
        }
 
        ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
-                         "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n",
+                         "Installing address handler for region %s(%X) "
+                         "on Device %4.4s %p(%p)\n",
                          acpi_ut_get_region_name(space_id), space_id,
                          acpi_ut_get_node_name(node), node, obj_desc));
 
@@ -506,28 +533,26 @@ acpi_ev_install_space_handler(struct acpi_namespace_node * node,
 
        /* Install at head of Device.address_space list */
 
-       handler_obj->address_space.next = obj_desc->device.handler;
+       handler_obj->address_space.next = obj_desc->common_notify.handler;
 
        /*
         * The Device object is the first reference on the handler_obj.
         * Each region that uses the handler adds a reference.
         */
-       obj_desc->device.handler = handler_obj;
+       obj_desc->common_notify.handler = handler_obj;
 
        /*
-        * Walk the namespace finding all of the regions this
-        * handler will manage.
+        * Walk the namespace finding all of the regions this handler will
+        * manage.
         *
-        * Start at the device and search the branch toward
-        * the leaf nodes until either the leaf is encountered or
-        * a device is detected that has an address handler of the
-        * same type.
+        * Start at the device and search the branch toward the leaf nodes
+        * until either the leaf is encountered or a device is detected that
+        * has an address handler of the same type.
         *
-        * In either case, back up and search down the remainder
-        * of the branch
+        * In either case, back up and search down the remainder of the branch
         */
-       status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
-                                       ACPI_NS_WALK_UNLOCK,
+       status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node,
+                                       ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
                                        acpi_ev_install_handler, NULL,
                                        handler_obj, NULL);
 
index f7c9dfe7b990134a3b773380868af4e5dcb4b985..8866f50d38f7ddb746285a46295367b3f5de3e33 100644 (file)
@@ -68,6 +68,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context);
 
 u8 acpi_ev_is_notify_object(struct acpi_namespace_node *node)
 {
+
        switch (node->type) {
        case ACPI_TYPE_DEVICE:
        case ACPI_TYPE_PROCESSOR:
@@ -170,8 +171,8 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node,
                          acpi_ut_get_notify_name(notify_value, ACPI_TYPE_ANY),
                          node));
 
-       status = acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_notify_dispatch,
-                                info);
+       status = acpi_os_execute(OSL_NOTIFY_HANDLER,
+                                acpi_ev_notify_dispatch, info);
        if (ACPI_FAILURE(status)) {
                acpi_ut_delete_generic_state(info);
        }
index 5ee79a16fe33bc3e5ea0133dcb502f5539d2b14e..a43178f20c593db410ba5ccda6c6259d6676d71c 100644 (file)
@@ -97,15 +97,12 @@ acpi_status acpi_ev_initialize_op_regions(void)
                if (acpi_ev_has_default_handler(acpi_gbl_root_node,
                                                acpi_gbl_default_address_spaces
                                                [i])) {
-                       status =
-                           acpi_ev_execute_reg_methods(acpi_gbl_root_node,
-                                                       acpi_gbl_default_address_spaces
-                                                       [i]);
+                       acpi_ev_execute_reg_methods(acpi_gbl_root_node,
+                                                   acpi_gbl_default_address_spaces
+                                                   [i], ACPI_REG_CONNECT);
                }
        }
 
-       acpi_gbl_reg_methods_executed = TRUE;
-
        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
        return_ACPI_STATUS(status);
 }
@@ -127,6 +124,12 @@ acpi_status acpi_ev_initialize_op_regions(void)
  * DESCRIPTION: Dispatch an address space or operation region access to
  *              a previously installed handler.
  *
+ * NOTE: During early initialization, we always install the default region
+ * handlers for Memory, I/O and PCI_Config. This ensures that these operation
+ * region address spaces are always available as per the ACPI specification.
+ * This is especially needed in order to support the execution of
+ * module-level AML code during loading of the ACPI tables.
+ *
  ******************************************************************************/
 
 acpi_status
@@ -498,6 +501,12 @@ acpi_ev_attach_region(union acpi_operand_object *handler_obj,
 
        ACPI_FUNCTION_TRACE(ev_attach_region);
 
+       /* Install the region's handler */
+
+       if (region_obj->region.handler) {
+               return_ACPI_STATUS(AE_ALREADY_EXISTS);
+       }
+
        ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
                          "Adding Region [%4.4s] %p to address handler %p [%s]\n",
                          acpi_ut_get_node_name(region_obj->region.node),
@@ -509,17 +518,56 @@ acpi_ev_attach_region(union acpi_operand_object *handler_obj,
 
        region_obj->region.next = handler_obj->address_space.region_list;
        handler_obj->address_space.region_list = region_obj;
+       region_obj->region.handler = handler_obj;
+       acpi_ut_add_reference(handler_obj);
 
-       /* Install the region's handler */
+       return_ACPI_STATUS(AE_OK);
+}
 
-       if (region_obj->region.handler) {
-               return_ACPI_STATUS(AE_ALREADY_EXISTS);
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ev_associate_reg_method
+ *
+ * PARAMETERS:  region_obj          - Region object
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Find and associate _REG method to a region
+ *
+ ******************************************************************************/
+
+void acpi_ev_associate_reg_method(union acpi_operand_object *region_obj)
+{
+       acpi_name *reg_name_ptr = (acpi_name *) METHOD_NAME__REG;
+       struct acpi_namespace_node *method_node;
+       struct acpi_namespace_node *node;
+       union acpi_operand_object *region_obj2;
+       acpi_status status;
+
+       ACPI_FUNCTION_TRACE(ev_associate_reg_method);
+
+       region_obj2 = acpi_ns_get_secondary_object(region_obj);
+       if (!region_obj2) {
+               return_VOID;
        }
 
-       region_obj->region.handler = handler_obj;
-       acpi_ut_add_reference(handler_obj);
+       node = region_obj->region.node->parent;
 
-       return_ACPI_STATUS(AE_OK);
+       /* Find any "_REG" method associated with this region definition */
+
+       status =
+           acpi_ns_search_one_scope(*reg_name_ptr, node, ACPI_TYPE_METHOD,
+                                    &method_node);
+       if (ACPI_SUCCESS(status)) {
+               /*
+                * The _REG method is optional and there can be only one per region
+                * definition. This will be executed when the handler is attached
+                * or removed
+                */
+               region_obj2->extra.method_REG = method_node;
+       }
+
+       return_VOID;
 }
 
 /*******************************************************************************
@@ -550,7 +598,18 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function)
                return_ACPI_STATUS(AE_NOT_EXIST);
        }
 
-       if (region_obj2->extra.method_REG == NULL) {
+       if (region_obj2->extra.method_REG == NULL ||
+           region_obj->region.handler == NULL ||
+           !acpi_gbl_reg_methods_enabled) {
+               return_ACPI_STATUS(AE_OK);
+       }
+
+       /* _REG(DISCONNECT) should be paired with _REG(CONNECT) */
+
+       if ((function == ACPI_REG_CONNECT &&
+            region_obj->common.flags & AOPOBJ_REG_CONNECTED) ||
+           (function == ACPI_REG_DISCONNECT &&
+            !(region_obj->common.flags & AOPOBJ_REG_CONNECTED))) {
                return_ACPI_STATUS(AE_OK);
        }
 
@@ -599,6 +658,16 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function)
        status = acpi_ns_evaluate(info);
        acpi_ut_remove_reference(args[1]);
 
+       if (ACPI_FAILURE(status)) {
+               goto cleanup2;
+       }
+
+       if (function == ACPI_REG_CONNECT) {
+               region_obj->common.flags |= AOPOBJ_REG_CONNECTED;
+       } else {
+               region_obj->common.flags &= ~AOPOBJ_REG_CONNECTED;
+       }
+
 cleanup2:
        acpi_ut_remove_reference(args[0]);
 
@@ -613,24 +682,25 @@ cleanup1:
  *
  * PARAMETERS:  node            - Namespace node for the device
  *              space_id        - The address space ID
+ *              function        - Passed to _REG: On (1) or Off (0)
  *
- * RETURN:      Status
+ * RETURN:      None
  *
  * DESCRIPTION: Run all _REG methods for the input Space ID;
  *              Note: assumes namespace is locked, or system init time.
  *
  ******************************************************************************/
 
-acpi_status
+void
 acpi_ev_execute_reg_methods(struct acpi_namespace_node *node,
-                           acpi_adr_space_type space_id)
+                           acpi_adr_space_type space_id, u32 function)
 {
-       acpi_status status;
        struct acpi_reg_walk_info info;
 
        ACPI_FUNCTION_TRACE(ev_execute_reg_methods);
 
        info.space_id = space_id;
+       info.function = function;
        info.reg_run_count = 0;
 
        ACPI_DEBUG_PRINT_RAW((ACPI_DB_NAMES,
@@ -643,9 +713,9 @@ acpi_ev_execute_reg_methods(struct acpi_namespace_node *node,
         * regions and _REG methods. (i.e. handlers must be installed for all
         * regions of this Space ID before we can run any _REG methods)
         */
-       status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
-                                       ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run,
-                                       NULL, &info, NULL);
+       (void)acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
+                                    ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run, NULL,
+                                    &info, NULL);
 
        /* Special case for EC: handle "orphan" _REG methods with no region */
 
@@ -658,7 +728,7 @@ acpi_ev_execute_reg_methods(struct acpi_namespace_node *node,
                              info.reg_run_count,
                              acpi_ut_get_region_name(info.space_id)));
 
-       return_ACPI_STATUS(status);
+       return_VOID;
 }
 
 /*******************************************************************************
@@ -717,7 +787,7 @@ acpi_ev_reg_run(acpi_handle obj_handle,
        }
 
        info->reg_run_count++;
-       status = acpi_ev_execute_reg_method(obj_desc, ACPI_REG_CONNECT);
+       status = acpi_ev_execute_reg_method(obj_desc, info->function);
        return (status);
 }
 
index da323390bb70688a8361b8c3022b76641a05fa54..bb2e529249c7a524c40afb4f040ef4919345078e 100644 (file)
@@ -507,9 +507,6 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj,
        acpi_adr_space_type space_id;
        struct acpi_namespace_node *node;
        acpi_status status;
-       struct acpi_namespace_node *method_node;
-       acpi_name *reg_name_ptr = (acpi_name *) METHOD_NAME__REG;
-       union acpi_operand_object *region_obj2;
 
        ACPI_FUNCTION_TRACE_U32(ev_initialize_region, acpi_ns_locked);
 
@@ -521,38 +518,15 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj,
                return_ACPI_STATUS(AE_OK);
        }
 
-       region_obj2 = acpi_ns_get_secondary_object(region_obj);
-       if (!region_obj2) {
-               return_ACPI_STATUS(AE_NOT_EXIST);
-       }
+       acpi_ev_associate_reg_method(region_obj);
+       region_obj->common.flags |= AOPOBJ_OBJECT_INITIALIZED;
 
        node = region_obj->region.node->parent;
        space_id = region_obj->region.space_id;
 
-       /* Setup defaults */
-
-       region_obj->region.handler = NULL;
-       region_obj2->extra.method_REG = NULL;
-       region_obj->common.flags &= ~(AOPOBJ_SETUP_COMPLETE);
-       region_obj->common.flags |= AOPOBJ_OBJECT_INITIALIZED;
-
-       /* Find any "_REG" method associated with this region definition */
-
-       status =
-           acpi_ns_search_one_scope(*reg_name_ptr, node, ACPI_TYPE_METHOD,
-                                    &method_node);
-       if (ACPI_SUCCESS(status)) {
-               /*
-                * The _REG method is optional and there can be only one per region
-                * definition. This will be executed when the handler is attached
-                * or removed
-                */
-               region_obj2->extra.method_REG = method_node;
-       }
-
        /*
         * The following loop depends upon the root Node having no parent
-        * ie: acpi_gbl_root_node->parent_entry being set to NULL
+        * ie: acpi_gbl_root_node->Parent being set to NULL
         */
        while (node) {
 
@@ -566,18 +540,10 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj,
 
                        switch (node->type) {
                        case ACPI_TYPE_DEVICE:
-
-                               handler_obj = obj_desc->device.handler;
-                               break;
-
                        case ACPI_TYPE_PROCESSOR:
-
-                               handler_obj = obj_desc->processor.handler;
-                               break;
-
                        case ACPI_TYPE_THERMAL:
 
-                               handler_obj = obj_desc->thermal_zone.handler;
+                               handler_obj = obj_desc->common_notify.handler;
                                break;
 
                        case ACPI_TYPE_METHOD:
@@ -602,60 +568,49 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj,
                                break;
                        }
 
-                       while (handler_obj) {
-
-                               /* Is this handler of the correct type? */
+                       handler_obj =
+                           acpi_ev_find_region_handler(space_id, handler_obj);
+                       if (handler_obj) {
 
-                               if (handler_obj->address_space.space_id ==
-                                   space_id) {
+                               /* Found correct handler */
 
-                                       /* Found correct handler */
+                               ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+                                                 "Found handler %p for region %p in obj %p\n",
+                                                 handler_obj, region_obj,
+                                                 obj_desc));
 
-                                       ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
-                                                         "Found handler %p for region %p in obj %p\n",
-                                                         handler_obj,
+                               status =
+                                   acpi_ev_attach_region(handler_obj,
                                                          region_obj,
-                                                         obj_desc));
+                                                         acpi_ns_locked);
 
+                               /*
+                                * Tell all users that this region is usable by
+                                * running the _REG method
+                                */
+                               if (acpi_ns_locked) {
                                        status =
-                                           acpi_ev_attach_region(handler_obj,
-                                                                 region_obj,
-                                                                 acpi_ns_locked);
-
-                                       /*
-                                        * Tell all users that this region is usable by
-                                        * running the _REG method
-                                        */
-                                       if (acpi_ns_locked) {
-                                               status =
-                                                   acpi_ut_release_mutex
-                                                   (ACPI_MTX_NAMESPACE);
-                                               if (ACPI_FAILURE(status)) {
-                                                       return_ACPI_STATUS
-                                                           (status);
-                                               }
+                                           acpi_ut_release_mutex
+                                           (ACPI_MTX_NAMESPACE);
+                                       if (ACPI_FAILURE(status)) {
+                                               return_ACPI_STATUS(status);
                                        }
+                               }
 
+                               status =
+                                   acpi_ev_execute_reg_method(region_obj,
+                                                              ACPI_REG_CONNECT);
+
+                               if (acpi_ns_locked) {
                                        status =
-                                           acpi_ev_execute_reg_method
-                                           (region_obj, ACPI_REG_CONNECT);
-
-                                       if (acpi_ns_locked) {
-                                               status =
-                                                   acpi_ut_acquire_mutex
-                                                   (ACPI_MTX_NAMESPACE);
-                                               if (ACPI_FAILURE(status)) {
-                                                       return_ACPI_STATUS
-                                                           (status);
-                                               }
+                                           acpi_ut_acquire_mutex
+                                           (ACPI_MTX_NAMESPACE);
+                                       if (ACPI_FAILURE(status)) {
+                                               return_ACPI_STATUS(status);
                                        }
-
-                                       return_ACPI_STATUS(AE_OK);
                                }
 
-                               /* Try next handler in the list */
-
-                               handler_obj = handler_obj->address_space.next;
+                               return_ACPI_STATUS(AE_OK);
                        }
                }
 
index 07d22bfbaa00d99f8f549d0deb94cd688122177e..012b9dedfa79eb9c62bdcd78e3a2da6c3edb6e46 100644 (file)
@@ -879,9 +879,8 @@ acpi_install_gpe_handler(acpi_handle gpe_device,
 
        ACPI_FUNCTION_TRACE(acpi_install_gpe_handler);
 
-       status =
-           acpi_ev_install_gpe_handler(gpe_device, gpe_number, type, FALSE,
-                                       address, context);
+       status = acpi_ev_install_gpe_handler(gpe_device, gpe_number, type,
+                                            FALSE, address, context);
 
        return_ACPI_STATUS(status);
 }
@@ -914,8 +913,8 @@ acpi_install_gpe_raw_handler(acpi_handle gpe_device,
 
        ACPI_FUNCTION_TRACE(acpi_install_gpe_raw_handler);
 
-       status = acpi_ev_install_gpe_handler(gpe_device, gpe_number, type, TRUE,
-                                            address, context);
+       status = acpi_ev_install_gpe_handler(gpe_device, gpe_number, type,
+                                            TRUE, address, context);
 
        return_ACPI_STATUS(status);
 }
index f21afbab03f74b8f796b9209b22b4291d856db3c..35f9e60ce2b7f091971fb4aa36bb62ecacfe8f66 100644 (file)
@@ -112,41 +112,9 @@ acpi_install_address_space_handler(acpi_handle device,
                goto unlock_and_exit;
        }
 
-       /*
-        * For the default space_IDs, (the IDs for which there are default region handlers
-        * installed) Only execute the _REG methods if the global initialization _REG
-        * methods have already been run (via acpi_initialize_objects). In other words,
-        * we will defer the execution of the _REG methods for these space_IDs until
-        * execution of acpi_initialize_objects. This is done because we need the handlers
-        * for the default spaces (mem/io/pci/table) to be installed before we can run
-        * any control methods (or _REG methods). There is known BIOS code that depends
-        * on this.
-        *
-        * For all other space_IDs, we can safely execute the _REG methods immediately.
-        * This means that for IDs like embedded_controller, this function should be called
-        * only after acpi_enable_subsystem has been called.
-        */
-       switch (space_id) {
-       case ACPI_ADR_SPACE_SYSTEM_MEMORY:
-       case ACPI_ADR_SPACE_SYSTEM_IO:
-       case ACPI_ADR_SPACE_PCI_CONFIG:
-       case ACPI_ADR_SPACE_DATA_TABLE:
-
-               if (!acpi_gbl_reg_methods_executed) {
-
-                       /* We will defer execution of the _REG methods for this space */
-                       goto unlock_and_exit;
-               }
-               break;
-
-       default:
-
-               break;
-       }
-
        /* Run all _REG methods for this address space */
 
-       status = acpi_ev_execute_reg_methods(node, space_id);
+       acpi_ev_execute_reg_methods(node, space_id, ACPI_REG_CONNECT);
 
 unlock_and_exit:
        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
@@ -215,8 +183,8 @@ acpi_remove_address_space_handler(acpi_handle device,
 
        /* Find the address handler the user requested */
 
-       handler_obj = obj_desc->device.handler;
-       last_obj_ptr = &obj_desc->device.handler;
+       handler_obj = obj_desc->common_notify.handler;
+       last_obj_ptr = &obj_desc->common_notify.handler;
        while (handler_obj) {
 
                /* We have a handler, see if user requested this one */
index b540913c11acebdb2bb9ee16e9915445a58dd40f..adcb9c7029c44f34225fdd7cdebc08fcd3fd46ee 100644 (file)
@@ -358,8 +358,8 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
                }
 
                /*
-                * If the Region Address and Length have not been previously evaluated,
-                * evaluate them now and save the results.
+                * If the Region Address and Length have not been previously
+                * evaluated, evaluate them now and save the results.
                 */
                if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
                        status = acpi_ds_get_region_arguments(obj_desc);
@@ -454,8 +454,8 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
                }
 
                /*
-                * Copy the table from the buffer because the buffer could be modified
-                * or even deleted in the future
+                * Copy the table from the buffer because the buffer could be
+                * modified or even deleted in the future
                 */
                table = ACPI_ALLOCATE(length);
                if (!table) {
index 1e4c5b6dc0b0ed400056cf59097875bf8a99ccfd..73c2e823488dfd6421023bcf9004c6d2128d2274 100644 (file)
@@ -227,8 +227,8 @@ acpi_ex_convert_to_buffer(union acpi_operand_object *obj_desc,
                /* Copy the integer to the buffer, LSB first */
 
                new_buf = return_desc->buffer.pointer;
-               memcpy(new_buf,
-                      &obj_desc->integer.value, acpi_gbl_integer_byte_width);
+               memcpy(new_buf, &obj_desc->integer.value,
+                      acpi_gbl_integer_byte_width);
                break;
 
        case ACPI_TYPE_STRING:
@@ -354,9 +354,8 @@ acpi_ex_convert_to_ascii(u64 integer, u16 base, u8 *string, u8 data_width)
 
                        /* Get one hex digit, most significant digits first */
 
-                       string[k] =
-                           (u8) acpi_ut_hex_to_ascii_char(integer,
-                                                          ACPI_MUL_4(j));
+                       string[k] = (u8)
+                           acpi_ut_hex_to_ascii_char(integer, ACPI_MUL_4(j));
                        k++;
                }
                break;
index ccb7219bdcee2756eb79f8a8b5e5d4aac3ae5423..46be5a276863294fdf01dd8a9d3b3213bdd7bfa6 100644 (file)
@@ -189,9 +189,9 @@ acpi_status acpi_ex_create_event(struct acpi_walk_state *walk_state)
 
        /* Attach object to the Node */
 
-       status =
-           acpi_ns_attach_object((struct acpi_namespace_node *)walk_state->
-                                 operands[0], obj_desc, ACPI_TYPE_EVENT);
+       status = acpi_ns_attach_object((struct acpi_namespace_node *)
+                                      walk_state->operands[0], obj_desc,
+                                      ACPI_TYPE_EVENT);
 
 cleanup:
        /*
@@ -326,9 +326,10 @@ acpi_ex_create_region(u8 * aml_start,
         * Remember location in AML stream of address & length
         * operands since they need to be evaluated at run time.
         */
-       region_obj2 = obj_desc->common.next_object;
+       region_obj2 = acpi_ns_get_secondary_object(obj_desc);
        region_obj2->extra.aml_start = aml_start;
        region_obj2->extra.aml_length = aml_length;
+       region_obj2->extra.method_REG = NULL;
        if (walk_state->scope_info) {
                region_obj2->extra.scope_node =
                    walk_state->scope_info->scope.node;
@@ -342,6 +343,10 @@ acpi_ex_create_region(u8 * aml_start,
        obj_desc->region.address = 0;
        obj_desc->region.length = 0;
        obj_desc->region.node = node;
+       obj_desc->region.handler = NULL;
+       obj_desc->common.flags &=
+           ~(AOPOBJ_SETUP_COMPLETE | AOPOBJ_REG_CONNECTED |
+             AOPOBJ_OBJECT_INITIALIZED);
 
        /* Install the new region object in the parent Node */
 
@@ -492,10 +497,9 @@ acpi_ex_create_method(u8 * aml_start,
         * Disassemble the method flags. Split off the arg_count, Serialized
         * flag, and sync_level for efficiency.
         */
-       method_flags = (u8) operand[1]->integer.value;
-
-       obj_desc->method.param_count =
-           (u8) (method_flags & AML_METHOD_ARG_COUNT);
+       method_flags = (u8)operand[1]->integer.value;
+       obj_desc->method.param_count = (u8)
+           (method_flags & AML_METHOD_ARG_COUNT);
 
        /*
         * Get the sync_level. If method is serialized, a mutex will be
index de92458236f56aa25a546276bc59f94038a78029..b22309094c5f79c0b7417bf09a504591e0f757ba 100644 (file)
 
 #include <acpi/acpi.h>
 #include "accommon.h"
-#include "acnamesp.h"
 #include "acinterp.h"
-#include "acparser.h"
 
 #define _COMPONENT          ACPI_EXECUTER
 ACPI_MODULE_NAME("exdebug")
 
-static union acpi_operand_object *acpi_gbl_trace_method_object = NULL;
-
-/* Local prototypes */
-
-#ifdef ACPI_DEBUG_OUTPUT
-static const char *acpi_ex_get_trace_event_name(acpi_trace_event_type type);
-#endif
-
 #ifndef ACPI_NO_ERROR_MESSAGES
 /*******************************************************************************
  *
@@ -80,7 +70,6 @@ static const char *acpi_ex_get_trace_event_name(acpi_trace_event_type type);
  * enabled if necessary.
  *
  ******************************************************************************/
-
 void
 acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
                        u32 level, u32 index)
@@ -99,20 +88,40 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
                return_VOID;
        }
 
-       /*
-        * We will emit the current timer value (in microseconds) with each
-        * debug output. Only need the lower 26 bits. This allows for 67
-        * million microseconds or 67 seconds before rollover.
-        */
-       timer = ((u32)acpi_os_get_timer() / 10);        /* (100 nanoseconds to microseconds) */
-       timer &= 0x03FFFFFF;
+       /* Null string or newline -- don't emit the line header */
+
+       if (source_desc &&
+           (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == ACPI_DESC_TYPE_OPERAND) &&
+           (source_desc->common.type == ACPI_TYPE_STRING)) {
+               if ((source_desc->string.length == 0) ||
+                   ((source_desc->string.length == 1) &&
+                    (*source_desc->string.pointer == '\n'))) {
+                       acpi_os_printf("\n");
+                       return_VOID;
+               }
+       }
 
        /*
         * Print line header as long as we are not in the middle of an
         * object display
         */
        if (!((level > 0) && index == 0)) {
-               acpi_os_printf("[ACPI Debug %.8u] %*s", timer, level, " ");
+               if (acpi_gbl_display_debug_timer) {
+                       /*
+                        * We will emit the current timer value (in microseconds) with each
+                        * debug output. Only need the lower 26 bits. This allows for 67
+                        * million microseconds or 67 seconds before rollover.
+                        *
+                        * Convert 100 nanosecond units to microseconds
+                        */
+                       timer = ((u32)acpi_os_get_timer() / 10);
+                       timer &= 0x03FFFFFF;
+
+                       acpi_os_printf("[ACPI Debug T=0x%8.8X] %*s", timer,
+                                      level, " ");
+               } else {
+                       acpi_os_printf("[ACPI Debug] %*s", level, " ");
+               }
        }
 
        /* Display the index for package output only */
@@ -127,8 +136,15 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
        }
 
        if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == ACPI_DESC_TYPE_OPERAND) {
-               acpi_os_printf("%s ",
-                              acpi_ut_get_object_type_name(source_desc));
+
+               /* No object type prefix needed for integers and strings */
+
+               if ((source_desc->common.type != ACPI_TYPE_INTEGER) &&
+                   (source_desc->common.type != ACPI_TYPE_STRING)) {
+                       acpi_os_printf("%s ",
+                                      acpi_ut_get_object_type_name
+                                      (source_desc));
+               }
 
                if (!acpi_ut_valid_internal_object(source_desc)) {
                        acpi_os_printf("%p, Invalid Internal Object!\n",
@@ -137,7 +153,7 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
                }
        } else if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) ==
                   ACPI_DESC_TYPE_NAMED) {
-               acpi_os_printf("%s: %p\n",
+               acpi_os_printf("%s (Node %p)\n",
                               acpi_ut_get_type_name(((struct
                                                       acpi_namespace_node *)
                                                      source_desc)->type),
@@ -175,14 +191,12 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
 
        case ACPI_TYPE_STRING:
 
-               acpi_os_printf("[0x%.2X] \"%s\"\n",
-                              source_desc->string.length,
-                              source_desc->string.pointer);
+               acpi_os_printf("\"%s\"\n", source_desc->string.pointer);
                break;
 
        case ACPI_TYPE_PACKAGE:
 
-               acpi_os_printf("[Contains 0x%.2X Elements]\n",
+               acpi_os_printf("(Contains 0x%.2X Elements):\n",
                               source_desc->package.count);
 
                /* Output the entire contents of the package */
@@ -261,11 +275,14 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
                        if (ACPI_GET_DESCRIPTOR_TYPE
                            (source_desc->reference.object) ==
                            ACPI_DESC_TYPE_NAMED) {
-                               acpi_ex_do_debug_object(((struct
-                                                         acpi_namespace_node *)
+
+                               /* Reference object is a namespace node */
+
+                               acpi_ex_do_debug_object(ACPI_CAST_PTR
+                                                       (union
+                                                        acpi_operand_object,
                                                         source_desc->reference.
-                                                        object)->object,
-                                                       level + 4, 0);
+                                                        object), level + 4, 0);
                        } else {
                                object_desc = source_desc->reference.object;
                                value = source_desc->reference.value;
@@ -293,9 +310,14 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
                                case ACPI_TYPE_PACKAGE:
 
                                        acpi_os_printf("Package[%u] = ", value);
-                                       acpi_ex_do_debug_object(*source_desc->
-                                                               reference.where,
-                                                               level + 4, 0);
+                                       if (!(*source_desc->reference.where)) {
+                                               acpi_os_printf
+                                                   ("[Uninitialized Package Element]\n");
+                                       } else {
+                                               acpi_ex_do_debug_object
+                                                   (*source_desc->reference.
+                                                    where, level + 4, 0);
+                                       }
                                        break;
 
                                default:
@@ -311,7 +333,7 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
 
        default:
 
-               acpi_os_printf("%p\n", source_desc);
+               acpi_os_printf("(Descriptor %p)\n", source_desc);
                break;
        }
 
@@ -319,316 +341,3 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
        return_VOID;
 }
 #endif
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ex_interpreter_trace_enabled
- *
- * PARAMETERS:  name                - Whether method name should be matched,
- *                                    this should be checked before starting
- *                                    the tracer
- *
- * RETURN:      TRUE if interpreter trace is enabled.
- *
- * DESCRIPTION: Check whether interpreter trace is enabled
- *
- ******************************************************************************/
-
-static u8 acpi_ex_interpreter_trace_enabled(char *name)
-{
-
-       /* Check if tracing is enabled */
-
-       if (!(acpi_gbl_trace_flags & ACPI_TRACE_ENABLED)) {
-               return (FALSE);
-       }
-
-       /*
-        * Check if tracing is filtered:
-        *
-        * 1. If the tracer is started, acpi_gbl_trace_method_object should have
-        *    been filled by the trace starter
-        * 2. If the tracer is not started, acpi_gbl_trace_method_name should be
-        *    matched if it is specified
-        * 3. If the tracer is oneshot style, acpi_gbl_trace_method_name should
-        *    not be cleared by the trace stopper during the first match
-        */
-       if (acpi_gbl_trace_method_object) {
-               return (TRUE);
-       }
-       if (name &&
-           (acpi_gbl_trace_method_name &&
-            strcmp(acpi_gbl_trace_method_name, name))) {
-               return (FALSE);
-       }
-       if ((acpi_gbl_trace_flags & ACPI_TRACE_ONESHOT) &&
-           !acpi_gbl_trace_method_name) {
-               return (FALSE);
-       }
-
-       return (TRUE);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ex_get_trace_event_name
- *
- * PARAMETERS:  type            - Trace event type
- *
- * RETURN:      Trace event name.
- *
- * DESCRIPTION: Used to obtain the full trace event name.
- *
- ******************************************************************************/
-
-#ifdef ACPI_DEBUG_OUTPUT
-
-static const char *acpi_ex_get_trace_event_name(acpi_trace_event_type type)
-{
-       switch (type) {
-       case ACPI_TRACE_AML_METHOD:
-
-               return "Method";
-
-       case ACPI_TRACE_AML_OPCODE:
-
-               return "Opcode";
-
-       case ACPI_TRACE_AML_REGION:
-
-               return "Region";
-
-       default:
-
-               return "";
-       }
-}
-
-#endif
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ex_trace_point
- *
- * PARAMETERS:  type                - Trace event type
- *              begin               - TRUE if before execution
- *              aml                 - Executed AML address
- *              pathname            - Object path
- *
- * RETURN:      None
- *
- * DESCRIPTION: Internal interpreter execution trace.
- *
- ******************************************************************************/
-
-void
-acpi_ex_trace_point(acpi_trace_event_type type,
-                   u8 begin, u8 *aml, char *pathname)
-{
-
-       ACPI_FUNCTION_NAME(ex_trace_point);
-
-       if (pathname) {
-               ACPI_DEBUG_PRINT((ACPI_DB_TRACE_POINT,
-                                 "%s %s [0x%p:%s] execution.\n",
-                                 acpi_ex_get_trace_event_name(type),
-                                 begin ? "Begin" : "End", aml, pathname));
-       } else {
-               ACPI_DEBUG_PRINT((ACPI_DB_TRACE_POINT,
-                                 "%s %s [0x%p] execution.\n",
-                                 acpi_ex_get_trace_event_name(type),
-                                 begin ? "Begin" : "End", aml));
-       }
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ex_start_trace_method
- *
- * PARAMETERS:  method_node         - Node of the method
- *              obj_desc            - The method object
- *              walk_state          - current state, NULL if not yet executing
- *                                    a method.
- *
- * RETURN:      None
- *
- * DESCRIPTION: Start control method execution trace
- *
- ******************************************************************************/
-
-void
-acpi_ex_start_trace_method(struct acpi_namespace_node *method_node,
-                          union acpi_operand_object *obj_desc,
-                          struct acpi_walk_state *walk_state)
-{
-       acpi_status status;
-       char *pathname = NULL;
-       u8 enabled = FALSE;
-
-       ACPI_FUNCTION_NAME(ex_start_trace_method);
-
-       if (method_node) {
-               pathname = acpi_ns_get_normalized_pathname(method_node, TRUE);
-       }
-
-       status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
-       if (ACPI_FAILURE(status)) {
-               goto exit;
-       }
-
-       enabled = acpi_ex_interpreter_trace_enabled(pathname);
-       if (enabled && !acpi_gbl_trace_method_object) {
-               acpi_gbl_trace_method_object = obj_desc;
-               acpi_gbl_original_dbg_level = acpi_dbg_level;
-               acpi_gbl_original_dbg_layer = acpi_dbg_layer;
-               acpi_dbg_level = ACPI_TRACE_LEVEL_ALL;
-               acpi_dbg_layer = ACPI_TRACE_LAYER_ALL;
-
-               if (acpi_gbl_trace_dbg_level) {
-                       acpi_dbg_level = acpi_gbl_trace_dbg_level;
-               }
-               if (acpi_gbl_trace_dbg_layer) {
-                       acpi_dbg_layer = acpi_gbl_trace_dbg_layer;
-               }
-       }
-       (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
-
-exit:
-       if (enabled) {
-               ACPI_TRACE_POINT(ACPI_TRACE_AML_METHOD, TRUE,
-                                obj_desc ? obj_desc->method.aml_start : NULL,
-                                pathname);
-       }
-       if (pathname) {
-               ACPI_FREE(pathname);
-       }
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ex_stop_trace_method
- *
- * PARAMETERS:  method_node         - Node of the method
- *              obj_desc            - The method object
- *              walk_state          - current state, NULL if not yet executing
- *                                    a method.
- *
- * RETURN:      None
- *
- * DESCRIPTION: Stop control method execution trace
- *
- ******************************************************************************/
-
-void
-acpi_ex_stop_trace_method(struct acpi_namespace_node *method_node,
-                         union acpi_operand_object *obj_desc,
-                         struct acpi_walk_state *walk_state)
-{
-       acpi_status status;
-       char *pathname = NULL;
-       u8 enabled;
-
-       ACPI_FUNCTION_NAME(ex_stop_trace_method);
-
-       if (method_node) {
-               pathname = acpi_ns_get_normalized_pathname(method_node, TRUE);
-       }
-
-       status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
-       if (ACPI_FAILURE(status)) {
-               goto exit_path;
-       }
-
-       enabled = acpi_ex_interpreter_trace_enabled(NULL);
-
-       (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
-
-       if (enabled) {
-               ACPI_TRACE_POINT(ACPI_TRACE_AML_METHOD, FALSE,
-                                obj_desc ? obj_desc->method.aml_start : NULL,
-                                pathname);
-       }
-
-       status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
-       if (ACPI_FAILURE(status)) {
-               goto exit_path;
-       }
-
-       /* Check whether the tracer should be stopped */
-
-       if (acpi_gbl_trace_method_object == obj_desc) {
-
-               /* Disable further tracing if type is one-shot */
-
-               if (acpi_gbl_trace_flags & ACPI_TRACE_ONESHOT) {
-                       acpi_gbl_trace_method_name = NULL;
-               }
-
-               acpi_dbg_level = acpi_gbl_original_dbg_level;
-               acpi_dbg_layer = acpi_gbl_original_dbg_layer;
-               acpi_gbl_trace_method_object = NULL;
-       }
-
-       (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
-
-exit_path:
-       if (pathname) {
-               ACPI_FREE(pathname);
-       }
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ex_start_trace_opcode
- *
- * PARAMETERS:  op                  - The parser opcode object
- *              walk_state          - current state, NULL if not yet executing
- *                                    a method.
- *
- * RETURN:      None
- *
- * DESCRIPTION: Start opcode execution trace
- *
- ******************************************************************************/
-
-void
-acpi_ex_start_trace_opcode(union acpi_parse_object *op,
-                          struct acpi_walk_state *walk_state)
-{
-
-       ACPI_FUNCTION_NAME(ex_start_trace_opcode);
-
-       if (acpi_ex_interpreter_trace_enabled(NULL) &&
-           (acpi_gbl_trace_flags & ACPI_TRACE_OPCODE)) {
-               ACPI_TRACE_POINT(ACPI_TRACE_AML_OPCODE, TRUE,
-                                op->common.aml, op->common.aml_op_name);
-       }
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ex_stop_trace_opcode
- *
- * PARAMETERS:  op                  - The parser opcode object
- *              walk_state          - current state, NULL if not yet executing
- *                                    a method.
- *
- * RETURN:      None
- *
- * DESCRIPTION: Stop opcode execution trace
- *
- ******************************************************************************/
-
-void
-acpi_ex_stop_trace_opcode(union acpi_parse_object *op,
-                         struct acpi_walk_state *walk_state)
-{
-
-       ACPI_FUNCTION_NAME(ex_stop_trace_opcode);
-
-       if (acpi_ex_interpreter_trace_enabled(NULL) &&
-           (acpi_gbl_trace_flags & ACPI_TRACE_OPCODE)) {
-               ACPI_TRACE_POINT(ACPI_TRACE_AML_OPCODE, FALSE,
-                                op->common.aml, op->common.aml_op_name);
-       }
-}
index d836f888bb16324cc4df1dfe9e0e2ac7ffbd20e0..ff976c43b99202c582f067ca1729378b5acd61b4 100644 (file)
@@ -508,7 +508,8 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc,
                        if (next) {
                                acpi_os_printf("(%s %2.2X)",
                                               acpi_ut_get_object_type_name
-                                              (next), next->common.type);
+                                              (next),
+                                              next->address_space.space_id);
 
                                while (next->address_space.next) {
                                        if ((next->common.type ==
@@ -520,7 +521,8 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc,
                                        acpi_os_printf("->%p(%s %2.2X)", next,
                                                       acpi_ut_get_object_type_name
                                                       (next),
-                                                      next->common.type);
+                                                      next->address_space.
+                                                      space_id);
 
                                        if ((next == start) || (next == data)) {
                                                acpi_os_printf
index 61fd9c7b88bc508360ab4d96a034b8ac41bcca65..ad7080ba65e298e0d8bfc15b3648f6d09309fe2b 100644 (file)
@@ -167,10 +167,11 @@ acpi_ex_read_data_from_field(struct acpi_walk_state * walk_state,
                    || obj_desc->field.region_obj->region.space_id ==
                    ACPI_ADR_SPACE_IPMI)) {
                /*
-                * This is an SMBus, GSBus or IPMI read. We must create a buffer to hold
-                * the data and then directly access the region handler.
+                * This is an SMBus, GSBus or IPMI read. We must create a buffer to
+                * hold the data and then directly access the region handler.
                 *
-                * Note: SMBus and GSBus protocol value is passed in upper 16-bits of Function
+                * Note: SMBus and GSBus protocol value is passed in upper 16-bits
+                * of Function
                 */
                if (obj_desc->field.region_obj->region.space_id ==
                    ACPI_ADR_SPACE_SMBUS) {
@@ -180,17 +181,17 @@ acpi_ex_read_data_from_field(struct acpi_walk_state * walk_state,
                } else if (obj_desc->field.region_obj->region.space_id ==
                           ACPI_ADR_SPACE_GSBUS) {
                        accessor_type = obj_desc->field.attribute;
-                       length = acpi_ex_get_serial_access_length(accessor_type,
-                                                                 obj_desc->
-                                                                 field.
-                                                                 access_length);
+                       length =
+                           acpi_ex_get_serial_access_length(accessor_type,
+                                                            obj_desc->field.
+                                                            access_length);
 
                        /*
                         * Add additional 2 bytes for the generic_serial_bus data buffer:
                         *
-                        *     Status;      (Byte 0 of the data buffer)
-                        *     Length;      (Byte 1 of the data buffer)
-                        *     Data[x-1];   (Bytes 2-x of the arbitrary length data buffer)
+                        *     Status;    (Byte 0 of the data buffer)
+                        *     Length;    (Byte 1 of the data buffer)
+                        *     Data[x-1]: (Bytes 2-x of the arbitrary length data buffer)
                         */
                        length += 2;
                        function = ACPI_READ | (accessor_type << 16);
@@ -216,6 +217,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state * walk_state,
                                                             buffer_desc->
                                                             buffer.pointer),
                                               function);
+
                acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
                goto exit;
        }
@@ -232,6 +234,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state * walk_state,
         */
        length =
            (acpi_size) ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->field.bit_length);
+
        if (length > acpi_gbl_integer_byte_width) {
 
                /* Field is too large for an Integer, create a Buffer instead */
@@ -273,8 +276,10 @@ acpi_ex_read_data_from_field(struct acpi_walk_state * walk_state,
 
                /* Perform the write */
 
-               status = acpi_ex_access_region(obj_desc, 0,
-                                              (u64 *)buffer, ACPI_READ);
+               status =
+                   acpi_ex_access_region(obj_desc, 0, (u64 *)buffer,
+                                         ACPI_READ);
+
                acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
                if (ACPI_FAILURE(status)) {
                        acpi_ut_remove_reference(buffer_desc);
@@ -366,19 +371,22 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
                    || obj_desc->field.region_obj->region.space_id ==
                    ACPI_ADR_SPACE_IPMI)) {
                /*
-                * This is an SMBus, GSBus or IPMI write. We will bypass the entire field
-                * mechanism and handoff the buffer directly to the handler. For
-                * these address spaces, the buffer is bi-directional; on a write,
-                * return data is returned in the same buffer.
+                * This is an SMBus, GSBus or IPMI write. We will bypass the entire
+                * field mechanism and handoff the buffer directly to the handler.
+                * For these address spaces, the buffer is bi-directional; on a
+                * write, return data is returned in the same buffer.
                 *
                 * Source must be a buffer of sufficient size:
-                * ACPI_SMBUS_BUFFER_SIZE, ACPI_GSBUS_BUFFER_SIZE, or ACPI_IPMI_BUFFER_SIZE.
+                * ACPI_SMBUS_BUFFER_SIZE, ACPI_GSBUS_BUFFER_SIZE, or
+                * ACPI_IPMI_BUFFER_SIZE.
                 *
-                * Note: SMBus and GSBus protocol type is passed in upper 16-bits of Function
+                * Note: SMBus and GSBus protocol type is passed in upper 16-bits
+                * of Function
                 */
                if (source_desc->common.type != ACPI_TYPE_BUFFER) {
                        ACPI_ERROR((AE_INFO,
-                                   "SMBus/IPMI/GenericSerialBus write requires Buffer, found type %s",
+                                   "SMBus/IPMI/GenericSerialBus write requires "
+                                   "Buffer, found type %s",
                                    acpi_ut_get_object_type_name(source_desc)));
 
                        return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
@@ -392,17 +400,17 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
                } else if (obj_desc->field.region_obj->region.space_id ==
                           ACPI_ADR_SPACE_GSBUS) {
                        accessor_type = obj_desc->field.attribute;
-                       length = acpi_ex_get_serial_access_length(accessor_type,
-                                                                 obj_desc->
-                                                                 field.
-                                                                 access_length);
+                       length =
+                           acpi_ex_get_serial_access_length(accessor_type,
+                                                            obj_desc->field.
+                                                            access_length);
 
                        /*
                         * Add additional 2 bytes for the generic_serial_bus data buffer:
                         *
-                        *     Status;      (Byte 0 of the data buffer)
-                        *     Length;      (Byte 1 of the data buffer)
-                        *     Data[x-1];   (Bytes 2-x of the arbitrary length data buffer)
+                        *     Status;    (Byte 0 of the data buffer)
+                        *     Length;    (Byte 1 of the data buffer)
+                        *     Data[x-1]: (Bytes 2-x of the arbitrary length data buffer)
                         */
                        length += 2;
                        function = ACPI_WRITE | (accessor_type << 16);
@@ -414,7 +422,8 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
 
                if (source_desc->buffer.length < length) {
                        ACPI_ERROR((AE_INFO,
-                                   "SMBus/IPMI/GenericSerialBus write requires Buffer of length %u, found length %u",
+                                   "SMBus/IPMI/GenericSerialBus write requires "
+                                   "Buffer of length %u, found length %u",
                                    length, source_desc->buffer.length));
 
                        return_ACPI_STATUS(AE_AML_BUFFER_LIMIT);
@@ -438,8 +447,8 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
                 * Perform the write (returns status and perhaps data in the
                 * same buffer)
                 */
-               status = acpi_ex_access_region(obj_desc, 0,
-                                              (u64 *) buffer, function);
+               status =
+                   acpi_ex_access_region(obj_desc, 0, (u64 *)buffer, function);
                acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
 
                *result_desc = buffer_desc;
@@ -460,7 +469,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
                }
 
                ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
-                                 "GPIO FieldWrite [FROM]: (%s:%X), Val %.8X  [TO]:  Pin %u Bits %u\n",
+                                 "GPIO FieldWrite [FROM]: (%s:%X), Val %.8X  [TO]: Pin %u Bits %u\n",
                                  acpi_ut_get_type_name(source_desc->common.
                                                        type),
                                  source_desc->common.type,
@@ -476,8 +485,9 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
 
                /* Perform the write */
 
-               status = acpi_ex_access_region(obj_desc, 0,
-                                              (u64 *)buffer, ACPI_WRITE);
+               status =
+                   acpi_ex_access_region(obj_desc, 0, (u64 *)buffer,
+                                         ACPI_WRITE);
                acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
                return_ACPI_STATUS(status);
        }
index 70b7bbbb860b216aaeeb5e520cb5e253fc9b8f6b..0337191dbf3dbb0f253134f7a5b2904e5e78d039 100644 (file)
@@ -180,7 +180,8 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
                         * byte, and a field with Dword access specified.
                         */
                        ACPI_ERROR((AE_INFO,
-                                   "Field [%4.4s] access width (%u bytes) too large for region [%4.4s] (length %u)",
+                                   "Field [%4.4s] access width (%u bytes) "
+                                   "too large for region [%4.4s] (length %u)",
                                    acpi_ut_get_node_name(obj_desc->
                                                          common_field.node),
                                    obj_desc->common_field.access_byte_width,
@@ -194,7 +195,8 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
                 * exceeds region length, indicate an error
                 */
                ACPI_ERROR((AE_INFO,
-                           "Field [%4.4s] Base+Offset+Width %u+%u+%u is beyond end of region [%4.4s] (length %u)",
+                           "Field [%4.4s] Base+Offset+Width %u+%u+%u "
+                           "is beyond end of region [%4.4s] (length %u)",
                            acpi_ut_get_node_name(obj_desc->common_field.node),
                            obj_desc->common_field.base_byte_offset,
                            field_datum_byte_offset,
@@ -638,15 +640,15 @@ acpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc,
 
                        ACPI_ERROR((AE_INFO,
                                    "Unknown UpdateRule value: 0x%X",
-                                   (obj_desc->common_field.
-                                    field_flags &
+                                   (obj_desc->common_field.field_flags &
                                     AML_FIELD_UPDATE_RULE_MASK)));
                        return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
                }
        }
 
        ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
-                         "Mask %8.8X%8.8X, DatumOffset %X, Width %X, Value %8.8X%8.8X, MergedValue %8.8X%8.8X\n",
+                         "Mask %8.8X%8.8X, DatumOffset %X, Width %X, "
+                         "Value %8.8X%8.8X, MergedValue %8.8X%8.8X\n",
                          ACPI_FORMAT_UINT64(mask),
                          field_datum_byte_offset,
                          obj_desc->common_field.access_byte_width,
@@ -655,8 +657,9 @@ acpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc,
 
        /* Write the merged value */
 
-       status = acpi_ex_field_datum_io(obj_desc, field_datum_byte_offset,
-                                       &merged_value, ACPI_WRITE);
+       status =
+           acpi_ex_field_datum_io(obj_desc, field_datum_byte_offset,
+                                  &merged_value, ACPI_WRITE);
 
        return_ACPI_STATUS(status);
 }
@@ -764,8 +767,9 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
                /* Get next input datum from the field */
 
                field_offset += obj_desc->common_field.access_byte_width;
-               status = acpi_ex_field_datum_io(obj_desc, field_offset,
-                                               &raw_datum, ACPI_READ);
+               status =
+                   acpi_ex_field_datum_io(obj_desc, field_offset, &raw_datum,
+                                          ACPI_READ);
                if (ACPI_FAILURE(status)) {
                        return_ACPI_STATUS(status);
                }
@@ -858,6 +862,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
        new_buffer = NULL;
        required_length =
            ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length);
+
        /*
         * We must have a buffer that is at least as long as the field
         * we are writing to. This is because individual fields are
@@ -932,9 +937,9 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
                /* Write merged datum to the target field */
 
                merged_datum &= mask;
-               status = acpi_ex_write_with_update_rule(obj_desc, mask,
-                                                       merged_datum,
-                                                       field_offset);
+               status =
+                   acpi_ex_write_with_update_rule(obj_desc, mask, merged_datum,
+                                                  field_offset);
                if (ACPI_FAILURE(status)) {
                        goto exit;
                }
@@ -990,9 +995,9 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
        /* Write the last datum to the field */
 
        merged_datum &= mask;
-       status = acpi_ex_write_with_update_rule(obj_desc,
-                                               mask, merged_datum,
-                                               field_offset);
+       status =
+           acpi_ex_write_with_update_rule(obj_desc, mask, merged_datum,
+                                          field_offset);
 
 exit:
        /* Free temporary buffer if we used one */
index d02afece0f103ae9034d54657b9ef2a3ca686d9b..f598b3948c17d1bfade75ecc122ef1127554e6f3 100644 (file)
@@ -98,9 +98,9 @@ acpi_ex_get_object_reference(union acpi_operand_object *obj_desc,
 
                default:
 
-                       ACPI_ERROR((AE_INFO, "Unknown Reference Class 0x%2.2X",
+                       ACPI_ERROR((AE_INFO, "Invalid Reference Class 0x%2.2X",
                                    obj_desc->reference.class));
-                       return_ACPI_STATUS(AE_AML_INTERNAL);
+                       return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
                }
                break;
 
@@ -247,6 +247,7 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0,
        union acpi_operand_object *local_operand1 = operand1;
        union acpi_operand_object *return_desc;
        char *new_buf;
+       const char *type_string;
        acpi_status status;
 
        ACPI_FUNCTION_TRACE(ex_do_concatenate);
@@ -266,9 +267,41 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0,
                break;
 
        case ACPI_TYPE_STRING:
+               /*
+                * Per the ACPI spec, Concatenate only supports int/str/buf.
+                * However, we support all objects here as an extension.
+                * This improves the usefulness of the Printf() macro.
+                * 12/2015.
+                */
+               switch (operand1->common.type) {
+               case ACPI_TYPE_INTEGER:
+               case ACPI_TYPE_STRING:
+               case ACPI_TYPE_BUFFER:
+
+                       status =
+                           acpi_ex_convert_to_string(operand1, &local_operand1,
+                                                     ACPI_IMPLICIT_CONVERT_HEX);
+                       break;
+
+               default:
+                       /*
+                        * Just emit a string containing the object type.
+                        */
+                       type_string =
+                           acpi_ut_get_type_name(operand1->common.type);
+
+                       local_operand1 = acpi_ut_create_string_object(((acpi_size) strlen(type_string) + 9));   /* 9 For "[Object]" */
+                       if (!local_operand1) {
+                               status = AE_NO_MEMORY;
+                               goto cleanup;
+                       }
 
-               status = acpi_ex_convert_to_string(operand1, &local_operand1,
-                                                  ACPI_IMPLICIT_CONVERT_HEX);
+                       strcpy(local_operand1->string.pointer, "[");
+                       strcat(local_operand1->string.pointer, type_string);
+                       strcat(local_operand1->string.pointer, " Object]");
+                       status = AE_OK;
+                       break;
+               }
                break;
 
        case ACPI_TYPE_BUFFER:
@@ -347,8 +380,7 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0,
                /* Concatenate the strings */
 
                strcpy(new_buf, operand0->string.pointer);
-               strcpy(new_buf + operand0->string.length,
-                      local_operand1->string.pointer);
+               strcat(new_buf, local_operand1->string.pointer);
                break;
 
        case ACPI_TYPE_BUFFER:
@@ -591,8 +623,9 @@ acpi_ex_do_logical_op(u16 opcode,
 
        case ACPI_TYPE_STRING:
 
-               status = acpi_ex_convert_to_string(operand1, &local_operand1,
-                                                  ACPI_IMPLICIT_CONVERT_HEX);
+               status =
+                   acpi_ex_convert_to_string(operand1, &local_operand1,
+                                             ACPI_IMPLICIT_CONVERT_HEX);
                break;
 
        case ACPI_TYPE_BUFFER:
index 472030f2b5bb33b56342bed34f25852424834a90..843c60ae91f633b73850819a97ff5e3a19dcfa8b 100644 (file)
@@ -185,8 +185,9 @@ acpi_ex_acquire_mutex_object(u16 timeout,
        if (obj_desc == acpi_gbl_global_lock_mutex) {
                status = acpi_ev_acquire_global_lock(timeout);
        } else {
-               status = acpi_ex_system_wait_mutex(obj_desc->mutex.os_mutex,
-                                                  timeout);
+               status =
+                   acpi_ex_system_wait_mutex(obj_desc->mutex.os_mutex,
+                                             timeout);
        }
 
        if (ACPI_FAILURE(status)) {
@@ -243,20 +244,30 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc,
        }
 
        /*
-        * Current sync level must be less than or equal to the sync level of the
-        * mutex. This mechanism provides some deadlock prevention
+        * Current sync level must be less than or equal to the sync level
+        * of the mutex. This mechanism provides some deadlock prevention.
         */
        if (walk_state->thread->current_sync_level > obj_desc->mutex.sync_level) {
                ACPI_ERROR((AE_INFO,
-                           "Cannot acquire Mutex [%4.4s], current SyncLevel is too large (%u)",
+                           "Cannot acquire Mutex [%4.4s], "
+                           "current SyncLevel is too large (%u)",
                            acpi_ut_get_node_name(obj_desc->mutex.node),
                            walk_state->thread->current_sync_level));
                return_ACPI_STATUS(AE_AML_MUTEX_ORDER);
        }
 
-       status = acpi_ex_acquire_mutex_object((u16) time_desc->integer.value,
+       ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+                         "Acquiring: Mutex SyncLevel %u, Thread SyncLevel %u, "
+                         "Depth %u TID %p\n",
+                         obj_desc->mutex.sync_level,
+                         walk_state->thread->current_sync_level,
+                         obj_desc->mutex.acquisition_depth,
+                         walk_state->thread));
+
+       status = acpi_ex_acquire_mutex_object((u16)time_desc->integer.value,
                                              obj_desc,
                                              walk_state->thread->thread_id);
+
        if (ACPI_SUCCESS(status) && obj_desc->mutex.acquisition_depth == 1) {
 
                /* Save Thread object, original/current sync levels */
@@ -272,6 +283,12 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc,
                acpi_ex_link_mutex(obj_desc, walk_state->thread);
        }
 
+       ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+                         "Acquired: Mutex SyncLevel %u, Thread SyncLevel %u, Depth %u\n",
+                         obj_desc->mutex.sync_level,
+                         walk_state->thread->current_sync_level,
+                         obj_desc->mutex.acquisition_depth));
+
        return_ACPI_STATUS(status);
 }
 
@@ -356,9 +373,9 @@ acpi_status
 acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
                      struct acpi_walk_state *walk_state)
 {
-       acpi_status status = AE_OK;
        u8 previous_sync_level;
        struct acpi_thread_state *owner_thread;
+       acpi_status status = AE_OK;
 
        ACPI_FUNCTION_TRACE(ex_release_mutex);
 
@@ -409,7 +426,8 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
         */
        if (obj_desc->mutex.sync_level != owner_thread->current_sync_level) {
                ACPI_ERROR((AE_INFO,
-                           "Cannot release Mutex [%4.4s], SyncLevel mismatch: mutex %u current %u",
+                           "Cannot release Mutex [%4.4s], SyncLevel mismatch: "
+                           "mutex %u current %u",
                            acpi_ut_get_node_name(obj_desc->mutex.node),
                            obj_desc->mutex.sync_level,
                            walk_state->thread->current_sync_level));
@@ -424,6 +442,15 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
        previous_sync_level =
            owner_thread->acquired_mutex_list->mutex.original_sync_level;
 
+       ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+                         "Releasing: Object SyncLevel %u, Thread SyncLevel %u, "
+                         "Prev SyncLevel %u, Depth %u TID %p\n",
+                         obj_desc->mutex.sync_level,
+                         walk_state->thread->current_sync_level,
+                         previous_sync_level,
+                         obj_desc->mutex.acquisition_depth,
+                         walk_state->thread));
+
        status = acpi_ex_release_mutex_object(obj_desc);
        if (ACPI_FAILURE(status)) {
                return_ACPI_STATUS(status);
@@ -436,6 +463,14 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
                owner_thread->current_sync_level = previous_sync_level;
        }
 
+       ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+                         "Released: Object SyncLevel %u, Thread SyncLevel, %u, "
+                         "Prev SyncLevel %u, Depth %u\n",
+                         obj_desc->mutex.sync_level,
+                         walk_state->thread->current_sync_level,
+                         previous_sync_level,
+                         obj_desc->mutex.acquisition_depth));
+
        return_ACPI_STATUS(status);
 }
 
@@ -462,21 +497,17 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread)
        union acpi_operand_object *next = thread->acquired_mutex_list;
        union acpi_operand_object *obj_desc;
 
-       ACPI_FUNCTION_NAME(ex_release_all_mutexes);
+       ACPI_FUNCTION_TRACE(ex_release_all_mutexes);
 
        /* Traverse the list of owned mutexes, releasing each one */
 
        while (next) {
                obj_desc = next;
-               next = obj_desc->mutex.next;
-
-               obj_desc->mutex.prev = NULL;
-               obj_desc->mutex.next = NULL;
-               obj_desc->mutex.acquisition_depth = 0;
-
                ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
-                                 "Force-releasing held mutex: %p\n",
-                                 obj_desc));
+                                 "Mutex [%4.4s] force-release, SyncLevel %u Depth %u\n",
+                                 obj_desc->mutex.node->name.ascii,
+                                 obj_desc->mutex.sync_level,
+                                 obj_desc->mutex.acquisition_depth));
 
                /* Release the mutex, special case for Global Lock */
 
@@ -489,14 +520,21 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread)
                        acpi_os_release_mutex(obj_desc->mutex.os_mutex);
                }
 
-               /* Mark mutex unowned */
-
-               obj_desc->mutex.owner_thread = NULL;
-               obj_desc->mutex.thread_id = 0;
-
                /* Update Thread sync_level (Last mutex is the important one) */
 
                thread->current_sync_level =
                    obj_desc->mutex.original_sync_level;
+
+               /* Mark mutex unowned */
+
+               next = obj_desc->mutex.next;
+
+               obj_desc->mutex.prev = NULL;
+               obj_desc->mutex.next = NULL;
+               obj_desc->mutex.acquisition_depth = 0;
+               obj_desc->mutex.owner_thread = NULL;
+               obj_desc->mutex.thread_id = 0;
        }
+
+       return_VOID;
 }
index 20e87813c7d7c6b304c2bc2cbebb6b2ec370eb13..b2e911a3586606862971fd8b23bcdba716e6b147 100644 (file)
@@ -164,8 +164,8 @@ static acpi_status acpi_ex_name_segment(u8 ** in_aml_address, char *name_string)
        ACPI_FUNCTION_TRACE(ex_name_segment);
 
        /*
-        * If first character is a digit, then we know that we aren't looking at a
-        * valid name segment
+        * If first character is a digit, then we know that we aren't looking
+        * at a valid name segment
         */
        char_buf[0] = *aml_address;
 
index 77930683ab7ddcf86620c3f3976bacb2faf85273..efe7ac319f654dd9deb36b5af6493bd423b021b2 100644 (file)
@@ -484,22 +484,26 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state)
 
        case AML_TO_DECSTRING_OP:       /* to_decimal_string (Data, Result) */
 
-               status = acpi_ex_convert_to_string(operand[0], &return_desc,
-                                                  ACPI_EXPLICIT_CONVERT_DECIMAL);
+               status =
+                   acpi_ex_convert_to_string(operand[0], &return_desc,
+                                             ACPI_EXPLICIT_CONVERT_DECIMAL);
                if (return_desc == operand[0]) {
 
                        /* No conversion performed, add ref to handle return value */
+
                        acpi_ut_add_reference(return_desc);
                }
                break;
 
        case AML_TO_HEXSTRING_OP:       /* to_hex_string (Data, Result) */
 
-               status = acpi_ex_convert_to_string(operand[0], &return_desc,
-                                                  ACPI_EXPLICIT_CONVERT_HEX);
+               status =
+                   acpi_ex_convert_to_string(operand[0], &return_desc,
+                                             ACPI_EXPLICIT_CONVERT_HEX);
                if (return_desc == operand[0]) {
 
                        /* No conversion performed, add ref to handle return value */
+
                        acpi_ut_add_reference(return_desc);
                }
                break;
@@ -510,17 +514,20 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state)
                if (return_desc == operand[0]) {
 
                        /* No conversion performed, add ref to handle return value */
+
                        acpi_ut_add_reference(return_desc);
                }
                break;
 
        case AML_TO_INTEGER_OP: /* to_integer (Data, Result) */
 
-               status = acpi_ex_convert_to_integer(operand[0], &return_desc,
-                                                   ACPI_ANY_BASE);
+               status =
+                   acpi_ex_convert_to_integer(operand[0], &return_desc,
+                                              ACPI_ANY_BASE);
                if (return_desc == operand[0]) {
 
                        /* No conversion performed, add ref to handle return value */
+
                        acpi_ut_add_reference(return_desc);
                }
                break;
@@ -679,7 +686,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
                status = acpi_ex_store(return_desc, operand[0], walk_state);
                break;
 
-       case AML_TYPE_OP:       /* object_type (source_object) */
+       case AML_OBJECT_TYPE_OP:        /* object_type (source_object) */
                /*
                 * Note: The operand is not resolved at this point because we want to
                 * get the associated object, not its value. For example, we don't
@@ -713,9 +720,9 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
 
                /* Get the base object */
 
-               status = acpi_ex_resolve_multiple(walk_state,
-                                                 operand[0], &type,
-                                                 &temp_desc);
+               status =
+                   acpi_ex_resolve_multiple(walk_state, operand[0], &type,
+                                            &temp_desc);
                if (ACPI_FAILURE(status)) {
                        goto cleanup;
                }
@@ -759,8 +766,10 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
                default:
 
                        ACPI_ERROR((AE_INFO,
-                                   "Operand must be Buffer/Integer/String/Package - found type %s",
+                                   "Operand must be Buffer/Integer/String/Package"
+                                   " - found type %s",
                                    acpi_ut_get_type_name(type)));
+
                        status = AE_AML_OPERAND_TYPE;
                        goto cleanup;
                }
@@ -981,6 +990,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
                                                    "Unknown Index TargetType 0x%X in reference object %p",
                                                    operand[0]->reference.
                                                    target_type, operand[0]));
+
                                        status = AE_AML_OPERAND_TYPE;
                                        goto cleanup;
                                }
@@ -1050,6 +1060,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
 
                ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
                            walk_state->opcode));
+
                status = AE_AML_BAD_OPCODE;
                goto cleanup;
        }
index b8944ebb108145aeb817f1b6f62774da4fb1c8ac..6dad2ca1c8c9c43f890c424fd83819b541824f1f 100644 (file)
@@ -199,6 +199,7 @@ acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state)
 
                ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
                            walk_state->opcode));
+
                status = AE_AML_BAD_OPCODE;
                goto cleanup;
        }
@@ -299,8 +300,9 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state)
 
        case AML_CONCAT_OP:     /* Concatenate (Data1, Data2, Result) */
 
-               status = acpi_ex_do_concatenate(operand[0], operand[1],
-                                               &return_desc, walk_state);
+               status =
+                   acpi_ex_do_concatenate(operand[0], operand[1], &return_desc,
+                                          walk_state);
                break;
 
        case AML_TO_STRING_OP:  /* to_string (Buffer, Length, Result) (ACPI 2.0) */
@@ -345,8 +347,9 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state)
 
                /* concatenate_res_template (Buffer, Buffer, Result) (ACPI 2.0) */
 
-               status = acpi_ex_concat_template(operand[0], operand[1],
-                                                &return_desc, walk_state);
+               status =
+                   acpi_ex_concat_template(operand[0], operand[1],
+                                           &return_desc, walk_state);
                break;
 
        case AML_INDEX_OP:      /* Index (Source Index Result) */
@@ -553,6 +556,7 @@ acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state)
 
                ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
                            walk_state->opcode));
+
                status = AE_AML_BAD_OPCODE;
                goto cleanup;
        }
index fa100b3b92ee8a4180c5ce8fe052e274ac26bce7..27fb0172fca20056f7e96fcba7c47b1f38fbeea1 100644 (file)
@@ -95,10 +95,11 @@ acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state)
        case AML_FATAL_OP:      /* Fatal (fatal_type fatal_code fatal_arg) */
 
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                                 "FatalOp: Type %X Code %X Arg %X <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n",
-                                 (u32) operand[0]->integer.value,
-                                 (u32) operand[1]->integer.value,
-                                 (u32) operand[2]->integer.value));
+                                 "FatalOp: Type %X Code %X Arg %X "
+                                 "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n",
+                                 (u32)operand[0]->integer.value,
+                                 (u32)operand[1]->integer.value,
+                                 (u32)operand[2]->integer.value));
 
                fatal = ACPI_ALLOCATE(sizeof(struct acpi_signal_fatal_info));
                if (fatal) {
@@ -131,6 +132,7 @@ acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state)
 
                ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
                            walk_state->opcode));
+
                status = AE_AML_BAD_OPCODE;
                goto cleanup;
        }
@@ -193,7 +195,8 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state)
                /* Truncate request if larger than the actual String/Buffer */
 
                else if ((index + length) > operand[0]->string.length) {
-                       length = (acpi_size) operand[0]->string.length -
+                       length =
+                           (acpi_size) operand[0]->string.length -
                            (acpi_size) index;
                }
 
@@ -237,8 +240,8 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state)
 
                        /* We have a buffer, copy the portion requested */
 
-                       memcpy(buffer, operand[0]->string.pointer + index,
-                              length);
+                       memcpy(buffer,
+                              operand[0]->string.pointer + index, length);
                }
 
                /* Set the length of the new String/Buffer */
@@ -255,6 +258,7 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state)
 
                ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
                            walk_state->opcode));
+
                status = AE_AML_BAD_OPCODE;
                goto cleanup;
        }
@@ -270,12 +274,11 @@ cleanup:
        if (ACPI_FAILURE(status) || walk_state->result_obj) {
                acpi_ut_remove_reference(return_desc);
                walk_state->result_obj = NULL;
-       }
+       } else {
+               /* Set the return object and exit */
 
-       /* Set the return object and exit */
-
-       else {
                walk_state->result_obj = return_desc;
        }
+
        return_ACPI_STATUS(status);
 }
index c930edda3f656321d110df599113f6bf0a539ee9..7efc9f47ffb913b6454e650831b89b532059b5ef 100644 (file)
@@ -310,6 +310,7 @@ acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state)
 
                ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
                            walk_state->opcode));
+
                status = AE_AML_BAD_OPCODE;
                goto cleanup;
        }
index 4c2836dc825bef2d175f6d898acb29c25fd3af86..1f111cc94c0096c166e884405fc68ba43c701e27 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Module Name: exprep - ACPI AML (p-code) execution - field prep utilities
+ * Module Name: exprep - ACPI AML field prep utilities
  *
  *****************************************************************************/
 
@@ -103,8 +103,10 @@ acpi_ex_generate_access(u32 field_bit_offset,
        /* Round Field start offset and length to "minimal" byte boundaries */
 
        field_byte_offset = ACPI_DIV_8(ACPI_ROUND_DOWN(field_bit_offset, 8));
-       field_byte_end_offset = ACPI_DIV_8(ACPI_ROUND_UP(field_bit_length +
-                                                        field_bit_offset, 8));
+
+       field_byte_end_offset =
+           ACPI_DIV_8(ACPI_ROUND_UP(field_bit_length + field_bit_offset, 8));
+
        field_byte_length = field_byte_end_offset - field_byte_offset;
 
        ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
@@ -159,7 +161,8 @@ acpi_ex_generate_access(u32 field_bit_offset,
 
                        if (accesses <= 1) {
                                ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
-                                                 "Entire field can be accessed with one operation of size %u\n",
+                                                 "Entire field can be accessed "
+                                                 "with one operation of size %u\n",
                                                  access_byte_width));
                                return_VALUE(access_byte_width);
                        }
@@ -202,6 +205,7 @@ acpi_ex_generate_access(u32 field_bit_offset,
         */
        ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
                          "Cannot access field in one operation, using width 8\n"));
+
        return_VALUE(8);
 }
 #endif                         /* ACPI_UNDER_DEVELOPMENT */
@@ -281,6 +285,7 @@ acpi_ex_decode_field_access(union acpi_operand_object *obj_desc,
                /* Invalid field access type */
 
                ACPI_ERROR((AE_INFO, "Unknown field access type 0x%X", access));
+
                return_UINT32(0);
        }
 
@@ -354,8 +359,8 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc,
         * For all other access types (Byte, Word, Dword, Qword), the Bitwidth is
         * the same (equivalent) as the byte_alignment.
         */
-       access_bit_width = acpi_ex_decode_field_access(obj_desc, field_flags,
-                                                      &byte_alignment);
+       access_bit_width =
+           acpi_ex_decode_field_access(obj_desc, field_flags, &byte_alignment);
        if (!access_bit_width) {
                return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
        }
@@ -595,7 +600,8 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
                                          access_byte_width);
 
                ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
-                                 "IndexField: BitOff %X, Off %X, Value %X, Gran %X, Index %p, Data %p\n",
+                                 "IndexField: BitOff %X, Off %X, Value %X, "
+                                 "Gran %X, Index %p, Data %p\n",
                                  obj_desc->index_field.start_field_bit_offset,
                                  obj_desc->index_field.base_byte_offset,
                                  obj_desc->index_field.value,
@@ -615,8 +621,9 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
         * Store the constructed descriptor (obj_desc) into the parent Node,
         * preserving the current type of that named_obj.
         */
-       status = acpi_ns_attach_object(info->field_node, obj_desc,
-                                      acpi_ns_get_type(info->field_node));
+       status =
+           acpi_ns_attach_object(info->field_node, obj_desc,
+                                 acpi_ns_get_type(info->field_node));
 
        ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
                          "Set NamedObj %p [%4.4s], ObjDesc %p\n",
index b4a5e44c00dd05df639b9d56d06ee44f04dcaf1a..1851a307544a353c3b1d3fc8cf0c35838e891614 100644 (file)
@@ -392,7 +392,8 @@ acpi_ex_pci_config_space_handler(u32 function,
        pci_register = (u16) (u32) address;
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                         "Pci-Config %u (%u) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n",
+                         "Pci-Config %u (%u) Seg(%04x) Bus(%04x) "
+                         "Dev(%04x) Func(%04x) Reg(%04x)\n",
                          function, bit_width, pci_id->segment, pci_id->bus,
                          pci_id->device, pci_id->function, pci_register));
 
@@ -400,14 +401,16 @@ acpi_ex_pci_config_space_handler(u32 function,
        case ACPI_READ:
 
                *value = 0;
-               status = acpi_os_read_pci_configuration(pci_id, pci_register,
-                                                       value, bit_width);
+               status =
+                   acpi_os_read_pci_configuration(pci_id, pci_register, value,
+                                                  bit_width);
                break;
 
        case ACPI_WRITE:
 
-               status = acpi_os_write_pci_configuration(pci_id, pci_register,
-                                                        *value, bit_width);
+               status =
+                   acpi_os_write_pci_configuration(pci_id, pci_register,
+                                                   *value, bit_width);
                break;
 
        default:
index 1b372ef693088a3e656003f966cfe798e2e280d8..6793dcc8a94611d706e6ff06ce3f33da7e63d059 100644 (file)
@@ -112,7 +112,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
 
        /*
         * Several object types require no further processing:
-        * 1) Device/Thermal objects don't have a "real" subobject, return the Node
+        * 1) Device/Thermal objects don't have a "real" subobject, return Node
         * 2) Method locals and arguments have a pseudo-Node
         * 3) 10/2007: Added method type to assist with Package construction.
         */
index a1afe1a1e7c2cada36b9a6763bd81f3efa205dfa..7f9260b129fc65ae72749f377298b683674d6ed0 100644 (file)
@@ -217,7 +217,8 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
                                         * the package, can't dereference it
                                         */
                                        ACPI_ERROR((AE_INFO,
-                                                   "Attempt to dereference an Index to NULL package element Idx=%p",
+                                                   "Attempt to dereference an Index to "
+                                                   "NULL package element Idx=%p",
                                                    stack_desc));
                                        status = AE_AML_UNINITIALIZED_ELEMENT;
                                }
@@ -361,10 +362,9 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
 
                if (type == ACPI_TYPE_LOCAL_ALIAS) {
                        type = ((struct acpi_namespace_node *)obj_desc)->type;
-                       obj_desc =
-                           acpi_ns_get_attached_object((struct
-                                                        acpi_namespace_node *)
-                                                       obj_desc);
+                       obj_desc = acpi_ns_get_attached_object((struct
+                                                               acpi_namespace_node
+                                                               *)obj_desc);
                }
 
                if (!obj_desc) {
index 424442d50b5e474c4a40eed1cb531af2aeede393..861453e58555ece76dd11f925c3aa2943b79a786 100644 (file)
@@ -90,8 +90,8 @@ acpi_ex_check_object_type(acpi_object_type type_needed,
                 * specification, a store to a constant is a noop.)
                 */
                if ((this_type == ACPI_TYPE_INTEGER) &&
-                   (((union acpi_operand_object *)object)->common.
-                    flags & AOPOBJ_AML_CONSTANT)) {
+                   (((union acpi_operand_object *)object)->common.flags &
+                    AOPOBJ_AML_CONSTANT)) {
                        return (AE_OK);
                }
        }
@@ -196,10 +196,10 @@ acpi_ex_resolve_operands(u16 opcode,
                         * thus, the attached object is always the aliased namespace node
                         */
                        if (object_type == ACPI_TYPE_LOCAL_ALIAS) {
-                               obj_desc =
-                                   acpi_ns_get_attached_object((struct
-                                                                acpi_namespace_node
-                                                                *)obj_desc);
+                               obj_desc = acpi_ns_get_attached_object((struct
+                                                                       acpi_namespace_node
+                                                                       *)
+                                                                      obj_desc);
                                *stack_ptr = obj_desc;
                                object_type =
                                    ((struct acpi_namespace_node *)obj_desc)->
@@ -285,8 +285,8 @@ acpi_ex_resolve_operands(u16 opcode,
                case ARGI_REF_OR_STRING:        /* Can be a String or Reference */
 
                        if ((ACPI_GET_DESCRIPTOR_TYPE(obj_desc) ==
-                            ACPI_DESC_TYPE_OPERAND)
-                           && (obj_desc->common.type == ACPI_TYPE_STRING)) {
+                            ACPI_DESC_TYPE_OPERAND) &&
+                           (obj_desc->common.type == ACPI_TYPE_STRING)) {
                                /*
                                 * String found - the string references a named object and
                                 * must be resolved to a node
@@ -465,8 +465,9 @@ acpi_ex_resolve_operands(u16 opcode,
                         * But we can implicitly convert from a BUFFER or INTEGER
                         * aka - "Implicit Source Operand Conversion"
                         */
-                       status = acpi_ex_convert_to_string(obj_desc, stack_ptr,
-                                                          ACPI_IMPLICIT_CONVERT_HEX);
+                       status =
+                           acpi_ex_convert_to_string(obj_desc, stack_ptr,
+                                                     ACPI_IMPLICIT_CONVERT_HEX);
                        if (ACPI_FAILURE(status)) {
                                if (status == AE_TYPE) {
                                        ACPI_ERROR((AE_INFO,
@@ -597,8 +598,10 @@ acpi_ex_resolve_operands(u16 opcode,
 
                case ARGI_REGION_OR_BUFFER:     /* Used by Load() only */
 
-                       /* Need an operand of type REGION or a BUFFER (which could be a resolved region field) */
-
+                       /*
+                        * Need an operand of type REGION or a BUFFER
+                        * (which could be a resolved region field)
+                        */
                        switch (obj_desc->common.type) {
                        case ACPI_TYPE_BUFFER:
                        case ACPI_TYPE_REGION:
@@ -640,9 +643,9 @@ acpi_ex_resolve_operands(u16 opcode,
 
                                if (acpi_gbl_enable_interpreter_slack) {
                                        /*
-                                        * Enable original behavior of Store(), allowing any and all
-                                        * objects as the source operand. The ACPI spec does not
-                                        * allow this, however.
+                                        * Enable original behavior of Store(), allowing any
+                                        * and all objects as the source operand. The ACPI
+                                        * spec does not allow this, however.
                                         */
                                        break;
                                }
@@ -655,7 +658,8 @@ acpi_ex_resolve_operands(u16 opcode,
                                }
 
                                ACPI_ERROR((AE_INFO,
-                                           "Needed Integer/Buffer/String/Package/Ref/Ddb], found [%s] %p",
+                                           "Needed Integer/Buffer/String/Package/Ref/Ddb]"
+                                           ", found [%s] %p",
                                            acpi_ut_get_object_type_name
                                            (obj_desc), obj_desc));
 
@@ -678,9 +682,10 @@ acpi_ex_resolve_operands(u16 opcode,
                 * Make sure that the original object was resolved to the
                 * required object type (Simple cases only).
                 */
-               status = acpi_ex_check_object_type(type_needed,
-                                                  (*stack_ptr)->common.type,
-                                                  *stack_ptr);
+               status =
+                   acpi_ex_check_object_type(type_needed,
+                                             (*stack_ptr)->common.type,
+                                             *stack_ptr);
                if (ACPI_FAILURE(status)) {
                        return_ACPI_STATUS(status);
                }
index c076e9100d66823d332e382ab05c7b694f56b82e..d3afbcbe78869d3b5f5505ee78ef787a503126fc 100644 (file)
@@ -467,7 +467,8 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc,
                case ACPI_TYPE_THERMAL:
 
                        ACPI_ERROR((AE_INFO,
-                                   "Target must be [Buffer/Integer/String/Reference], found [%s] (%4.4s)",
+                                   "Target must be [Buffer/Integer/String/Reference]"
+                                   ", found [%s] (%4.4s)",
                                    acpi_ut_get_type_name(node->type),
                                    node->name.ascii));
 
@@ -504,8 +505,9 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc,
                         * an implicit conversion, as per the ACPI specification.
                         * A direct store is performed instead.
                         */
-                       status = acpi_ex_store_direct_to_node(source_desc, node,
-                                                             walk_state);
+                       status =
+                           acpi_ex_store_direct_to_node(source_desc, node,
+                                                        walk_state);
                        break;
                }
 
@@ -528,8 +530,9 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc,
                         * store has been performed such that the node/object type
                         * has been changed.
                         */
-                       status = acpi_ns_attach_object(node, new_desc,
-                                                      new_desc->common.type);
+                       status =
+                           acpi_ns_attach_object(node, new_desc,
+                                                 new_desc->common.type);
 
                        ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
                                          "Store type [%s] into [%s] via Convert/Attach\n",
@@ -563,8 +566,8 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc,
                 * operator. (Note, for this default case, all normal
                 * Store/Target operations exited above with an error).
                 */
-               status = acpi_ex_store_direct_to_node(source_desc, node,
-                                                     walk_state);
+               status =
+                   acpi_ex_store_direct_to_node(source_desc, node, walk_state);
                break;
        }
 
index e1d4f4d51b97a41703546fdd71d6efb5770e3544..ad3bc92af2e68f6562453862a18d827846ffb29b 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Module Name: exstorob - AML Interpreter object store support, store to object
+ * Module Name: exstorob - AML object store support, store to object
  *
  *****************************************************************************/
 
@@ -203,8 +203,9 @@ acpi_ex_store_string_to_string(union acpi_operand_object *source_desc,
                        ACPI_FREE(target_desc->string.pointer);
                }
 
-               target_desc->string.pointer = ACPI_ALLOCATE_ZEROED((acpi_size)
-                                                                  length + 1);
+               target_desc->string.pointer =
+                   ACPI_ALLOCATE_ZEROED((acpi_size) length + 1);
+
                if (!target_desc->string.pointer) {
                        return_ACPI_STATUS(AE_NO_MEMORY);
                }
index 05450656fe3d1606f9b432308910ee1a303e3f51..7c91c1f799a56ba51395101e6dc7e4cc3817d03a 100644 (file)
@@ -78,7 +78,6 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout)
                /* We must wait, so unlock the interpreter */
 
                acpi_ex_exit_interpreter();
-
                status = acpi_os_wait_semaphore(semaphore, 1, timeout);
 
                ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
@@ -124,7 +123,6 @@ acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout)
                /* We must wait, so unlock the interpreter */
 
                acpi_ex_exit_interpreter();
-
                status = acpi_os_acquire_mutex(mutex, timeout);
 
                ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
@@ -169,8 +167,8 @@ acpi_status acpi_ex_system_do_stall(u32 how_long)
                 * (ACPI specifies 100 usec as max, but this gives some slack in
                 * order to support existing BIOSs)
                 */
-               ACPI_ERROR((AE_INFO, "Time parameter is too large (%u)",
-                           how_long));
+               ACPI_ERROR((AE_INFO,
+                           "Time parameter is too large (%u)", how_long));
                status = AE_AML_OPERAND_VALUE;
        } else {
                acpi_os_stall(how_long);
diff --git a/drivers/acpi/acpica/extrace.c b/drivers/acpi/acpica/extrace.c
new file mode 100644 (file)
index 0000000..e4a185e
--- /dev/null
@@ -0,0 +1,377 @@
+/******************************************************************************
+ *
+ * Module Name: extrace - Support for interpreter execution tracing
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2015, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    substantially similar to the "NO WARRANTY" disclaimer below
+ *    ("Disclaimer") and any redistribution must be conditioned upon
+ *    including a substantially similar Disclaimer requirement for further
+ *    binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+#include "acnamesp.h"
+#include "acinterp.h"
+
+#define _COMPONENT          ACPI_EXECUTER
+ACPI_MODULE_NAME("extrace")
+
+static union acpi_operand_object *acpi_gbl_trace_method_object = NULL;
+
+/* Local prototypes */
+
+#ifdef ACPI_DEBUG_OUTPUT
+static const char *acpi_ex_get_trace_event_name(acpi_trace_event_type type);
+#endif
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ex_interpreter_trace_enabled
+ *
+ * PARAMETERS:  name                - Whether method name should be matched,
+ *                                    this should be checked before starting
+ *                                    the tracer
+ *
+ * RETURN:      TRUE if interpreter trace is enabled.
+ *
+ * DESCRIPTION: Check whether interpreter trace is enabled
+ *
+ ******************************************************************************/
+
+static u8 acpi_ex_interpreter_trace_enabled(char *name)
+{
+
+       /* Check if tracing is enabled */
+
+       if (!(acpi_gbl_trace_flags & ACPI_TRACE_ENABLED)) {
+               return (FALSE);
+       }
+
+       /*
+        * Check if tracing is filtered:
+        *
+        * 1. If the tracer is started, acpi_gbl_trace_method_object should have
+        *    been filled by the trace starter
+        * 2. If the tracer is not started, acpi_gbl_trace_method_name should be
+        *    matched if it is specified
+        * 3. If the tracer is oneshot style, acpi_gbl_trace_method_name should
+        *    not be cleared by the trace stopper during the first match
+        */
+       if (acpi_gbl_trace_method_object) {
+               return (TRUE);
+       }
+
+       if (name &&
+           (acpi_gbl_trace_method_name &&
+            strcmp(acpi_gbl_trace_method_name, name))) {
+               return (FALSE);
+       }
+
+       if ((acpi_gbl_trace_flags & ACPI_TRACE_ONESHOT) &&
+           !acpi_gbl_trace_method_name) {
+               return (FALSE);
+       }
+
+       return (TRUE);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ex_get_trace_event_name
+ *
+ * PARAMETERS:  type            - Trace event type
+ *
+ * RETURN:      Trace event name.
+ *
+ * DESCRIPTION: Used to obtain the full trace event name.
+ *
+ ******************************************************************************/
+
+#ifdef ACPI_DEBUG_OUTPUT
+
+static const char *acpi_ex_get_trace_event_name(acpi_trace_event_type type)
+{
+
+       switch (type) {
+       case ACPI_TRACE_AML_METHOD:
+
+               return "Method";
+
+       case ACPI_TRACE_AML_OPCODE:
+
+               return "Opcode";
+
+       case ACPI_TRACE_AML_REGION:
+
+               return "Region";
+
+       default:
+
+               return "";
+       }
+}
+
+#endif
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ex_trace_point
+ *
+ * PARAMETERS:  type                - Trace event type
+ *              begin               - TRUE if before execution
+ *              aml                 - Executed AML address
+ *              pathname            - Object path
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Internal interpreter execution trace.
+ *
+ ******************************************************************************/
+
+void
+acpi_ex_trace_point(acpi_trace_event_type type,
+                   u8 begin, u8 *aml, char *pathname)
+{
+
+       ACPI_FUNCTION_NAME(ex_trace_point);
+
+       if (pathname) {
+               ACPI_DEBUG_PRINT((ACPI_DB_TRACE_POINT,
+                                 "%s %s [0x%p:%s] execution.\n",
+                                 acpi_ex_get_trace_event_name(type),
+                                 begin ? "Begin" : "End", aml, pathname));
+       } else {
+               ACPI_DEBUG_PRINT((ACPI_DB_TRACE_POINT,
+                                 "%s %s [0x%p] execution.\n",
+                                 acpi_ex_get_trace_event_name(type),
+                                 begin ? "Begin" : "End", aml));
+       }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ex_start_trace_method
+ *
+ * PARAMETERS:  method_node         - Node of the method
+ *              obj_desc            - The method object
+ *              walk_state          - current state, NULL if not yet executing
+ *                                    a method.
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Start control method execution trace
+ *
+ ******************************************************************************/
+
+void
+acpi_ex_start_trace_method(struct acpi_namespace_node *method_node,
+                          union acpi_operand_object *obj_desc,
+                          struct acpi_walk_state *walk_state)
+{
+       acpi_status status;
+       char *pathname = NULL;
+       u8 enabled = FALSE;
+
+       ACPI_FUNCTION_NAME(ex_start_trace_method);
+
+       if (method_node) {
+               pathname = acpi_ns_get_normalized_pathname(method_node, TRUE);
+       }
+
+       status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+       if (ACPI_FAILURE(status)) {
+               goto exit;
+       }
+
+       enabled = acpi_ex_interpreter_trace_enabled(pathname);
+       if (enabled && !acpi_gbl_trace_method_object) {
+               acpi_gbl_trace_method_object = obj_desc;
+               acpi_gbl_original_dbg_level = acpi_dbg_level;
+               acpi_gbl_original_dbg_layer = acpi_dbg_layer;
+               acpi_dbg_level = ACPI_TRACE_LEVEL_ALL;
+               acpi_dbg_layer = ACPI_TRACE_LAYER_ALL;
+
+               if (acpi_gbl_trace_dbg_level) {
+                       acpi_dbg_level = acpi_gbl_trace_dbg_level;
+               }
+
+               if (acpi_gbl_trace_dbg_layer) {
+                       acpi_dbg_layer = acpi_gbl_trace_dbg_layer;
+               }
+       }
+
+       (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+
+exit:
+       if (enabled) {
+               ACPI_TRACE_POINT(ACPI_TRACE_AML_METHOD, TRUE,
+                                obj_desc ? obj_desc->method.aml_start : NULL,
+                                pathname);
+       }
+
+       if (pathname) {
+               ACPI_FREE(pathname);
+       }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ex_stop_trace_method
+ *
+ * PARAMETERS:  method_node         - Node of the method
+ *              obj_desc            - The method object
+ *              walk_state          - current state, NULL if not yet executing
+ *                                    a method.
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Stop control method execution trace
+ *
+ ******************************************************************************/
+
+void
+acpi_ex_stop_trace_method(struct acpi_namespace_node *method_node,
+                         union acpi_operand_object *obj_desc,
+                         struct acpi_walk_state *walk_state)
+{
+       acpi_status status;
+       char *pathname = NULL;
+       u8 enabled;
+
+       ACPI_FUNCTION_NAME(ex_stop_trace_method);
+
+       if (method_node) {
+               pathname = acpi_ns_get_normalized_pathname(method_node, TRUE);
+       }
+
+       status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+       if (ACPI_FAILURE(status)) {
+               goto exit_path;
+       }
+
+       enabled = acpi_ex_interpreter_trace_enabled(NULL);
+
+       (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+
+       if (enabled) {
+               ACPI_TRACE_POINT(ACPI_TRACE_AML_METHOD, FALSE,
+                                obj_desc ? obj_desc->method.aml_start : NULL,
+                                pathname);
+       }
+
+       status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+       if (ACPI_FAILURE(status)) {
+               goto exit_path;
+       }
+
+       /* Check whether the tracer should be stopped */
+
+       if (acpi_gbl_trace_method_object == obj_desc) {
+
+               /* Disable further tracing if type is one-shot */
+
+               if (acpi_gbl_trace_flags & ACPI_TRACE_ONESHOT) {
+                       acpi_gbl_trace_method_name = NULL;
+               }
+
+               acpi_dbg_level = acpi_gbl_original_dbg_level;
+               acpi_dbg_layer = acpi_gbl_original_dbg_layer;
+               acpi_gbl_trace_method_object = NULL;
+       }
+
+       (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+
+exit_path:
+       if (pathname) {
+               ACPI_FREE(pathname);
+       }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ex_start_trace_opcode
+ *
+ * PARAMETERS:  op                  - The parser opcode object
+ *              walk_state          - current state, NULL if not yet executing
+ *                                    a method.
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Start opcode execution trace
+ *
+ ******************************************************************************/
+
+void
+acpi_ex_start_trace_opcode(union acpi_parse_object *op,
+                          struct acpi_walk_state *walk_state)
+{
+
+       ACPI_FUNCTION_NAME(ex_start_trace_opcode);
+
+       if (acpi_ex_interpreter_trace_enabled(NULL) &&
+           (acpi_gbl_trace_flags & ACPI_TRACE_OPCODE)) {
+               ACPI_TRACE_POINT(ACPI_TRACE_AML_OPCODE, TRUE,
+                                op->common.aml, op->common.aml_op_name);
+       }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ex_stop_trace_opcode
+ *
+ * PARAMETERS:  op                  - The parser opcode object
+ *              walk_state          - current state, NULL if not yet executing
+ *                                    a method.
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Stop opcode execution trace
+ *
+ ******************************************************************************/
+
+void
+acpi_ex_stop_trace_opcode(union acpi_parse_object *op,
+                         struct acpi_walk_state *walk_state)
+{
+
+       ACPI_FUNCTION_NAME(ex_stop_trace_opcode);
+
+       if (acpi_ex_interpreter_trace_enabled(NULL) &&
+           (acpi_gbl_trace_flags & ACPI_TRACE_OPCODE)) {
+               ACPI_TRACE_POINT(ACPI_TRACE_AML_OPCODE, FALSE,
+                                op->common.aml, op->common.aml_op_name);
+       }
+}
index 30c3f464fda5bcae5e98c7dd323fb963acea217d..8ae7634bd7d266f430f378cc2188e3c65f8e06b4 100644 (file)
@@ -167,8 +167,8 @@ u8 acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc)
        if ((acpi_gbl_integer_byte_width == 4) &&
            (obj_desc->integer.value > (u64)ACPI_UINT32_MAX)) {
                /*
-                * We are executing in a 32-bit ACPI table.
-                * Truncate the value to 32 bits by zeroing out the upper 32-bit field
+                * We are executing in a 32-bit ACPI table. Truncate
+                * the value to 32 bits by zeroing out the upper 32-bit field
                 */
                obj_desc->integer.value &= (u64)ACPI_UINT32_MAX;
                return (TRUE);
@@ -323,7 +323,8 @@ void acpi_ex_eisa_id_to_string(char *out_string, u64 compressed_id)
 
        if (compressed_id > ACPI_UINT32_MAX) {
                ACPI_WARNING((AE_INFO,
-                             "Expected EISAID is larger than 32 bits: 0x%8.8X%8.8X, truncating",
+                             "Expected EISAID is larger than 32 bits: "
+                             "0x%8.8X%8.8X, truncating",
                              ACPI_FORMAT_UINT64(compressed_id)));
        }
 
index e5599f610808373cd4e2ded7684a539227365e4f..d0319a228ef77728b21cac0e226d9fa03bc9562c 100644 (file)
@@ -117,8 +117,8 @@ acpi_status acpi_hw_extended_sleep(u8 sleep_state)
 
        /* Clear wake status (WAK_STS) */
 
-       status =
-           acpi_write((u64)ACPI_X_WAKE_STATUS, &acpi_gbl_FADT.sleep_status);
+       status = acpi_write((u64)ACPI_X_WAKE_STATUS,
+                           &acpi_gbl_FADT.sleep_status);
        if (ACPI_FAILURE(status)) {
                return_ACPI_STATUS(status);
        }
index 73cfa5947ff33618307c662fdc450d104445804a..8272f966382ac015a572af534870b38586784574 100644 (file)
@@ -187,9 +187,8 @@ acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info)
         */
        register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
 
-       status = acpi_hw_write(register_bit,
-                              &gpe_register_info->status_address);
-
+       status =
+           acpi_hw_write(register_bit, &gpe_register_info->status_address);
        return (status);
 }
 
@@ -297,6 +296,7 @@ acpi_hw_gpe_enable_write(u8 enable_mask,
        acpi_status status;
 
        gpe_register_info->enable_mask = enable_mask;
+
        status = acpi_hw_write(enable_mask, &gpe_register_info->enable_address);
        return (status);
 }
index 7d21cae6d60287b06640d20c5a6dda97a5e3f6d0..ac5b7f768d4b27a3b4d255cd2bb5a4a9d1b5a6bd 100644 (file)
@@ -80,8 +80,8 @@ acpi_status acpi_hw_legacy_sleep(u8 sleep_state)
 
        /* Clear wake status */
 
-       status =
-           acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS);
+       status = acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS,
+                                        ACPI_CLEAR_STATUS);
        if (ACPI_FAILURE(status)) {
                return_ACPI_STATUS(status);
        }
index 5f97468df8ff04e6bf0856a7b64324c16992cfb8..b2e50d8007fe6fa20a9a1ea5809292175a4a3dbf 100644 (file)
@@ -504,11 +504,20 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b)
         * Evaluate the \_Sx namespace object containing the register values
         * for this state
         */
-       info->relative_pathname =
-           ACPI_CAST_PTR(char, acpi_gbl_sleep_state_names[sleep_state]);
+       info->relative_pathname = ACPI_CAST_PTR(char,
+                                               acpi_gbl_sleep_state_names
+                                               [sleep_state]);
+
        status = acpi_ns_evaluate(info);
        if (ACPI_FAILURE(status)) {
-               goto cleanup;
+               if (status == AE_NOT_FOUND) {
+
+                       /* The _Sx states are optional, ignore NOT_FOUND */
+
+                       goto final_cleanup;
+               }
+
+               goto warning_cleanup;
        }
 
        /* Must have a return object */
@@ -517,7 +526,7 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b)
                ACPI_ERROR((AE_INFO, "No Sleep State object returned from [%s]",
                            info->relative_pathname));
                status = AE_AML_NO_RETURN_VALUE;
-               goto cleanup;
+               goto warning_cleanup;
        }
 
        /* Return object must be of type Package */
@@ -526,7 +535,7 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b)
                ACPI_ERROR((AE_INFO,
                            "Sleep State return object is not a Package"));
                status = AE_AML_OPERAND_TYPE;
-               goto cleanup1;
+               goto return_value_cleanup;
        }
 
        /*
@@ -570,16 +579,17 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b)
                break;
        }
 
-cleanup1:
+return_value_cleanup:
        acpi_ut_remove_reference(info->return_object);
 
-cleanup:
+warning_cleanup:
        if (ACPI_FAILURE(status)) {
                ACPI_EXCEPTION((AE_INFO, status,
                                "While evaluating Sleep State [%s]",
                                info->relative_pathname));
        }
 
+final_cleanup:
        ACPI_FREE(info);
        return_ACPI_STATUS(status);
 }
index d62a61612b3f1428be0c21efd5ff1bbc0f851038..1ce4efa1a2bd26aa1501a4d2ac50361d82e0a0fb 100644 (file)
@@ -52,9 +52,9 @@ ACPI_MODULE_NAME("hwxfsleep")
 /* Local prototypes */
 #if (!ACPI_REDUCED_HARDWARE)
 static acpi_status
-acpi_hw_set_firmware_waking_vectors(struct acpi_table_facs *facs,
-                                   acpi_physical_address physical_address,
-                                   acpi_physical_address physical_address64);
+acpi_hw_set_firmware_waking_vector(struct acpi_table_facs *facs,
+                                  acpi_physical_address physical_address,
+                                  acpi_physical_address physical_address64);
 #endif
 
 static acpi_status acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id);
@@ -79,22 +79,20 @@ static struct acpi_sleep_functions acpi_sleep_dispatch[] = {
 
 /*
  * These functions are removed for the ACPI_REDUCED_HARDWARE case:
- *      acpi_set_firmware_waking_vectors
  *      acpi_set_firmware_waking_vector
- *      acpi_set_firmware_waking_vector64
  *      acpi_enter_sleep_state_s4bios
  */
 
 #if (!ACPI_REDUCED_HARDWARE)
 /*******************************************************************************
  *
- * FUNCTION:    acpi_hw_set_firmware_waking_vectors
+ * FUNCTION:    acpi_hw_set_firmware_waking_vector
  *
  * PARAMETERS:  facs                - Pointer to FACS table
  *              physical_address    - 32-bit physical address of ACPI real mode
- *                                    entry point.
+ *                                    entry point
  *              physical_address64  - 64-bit physical address of ACPI protected
- *                                    mode entry point.
+ *                                    mode entry point
  *
  * RETURN:      Status
  *
@@ -103,11 +101,11 @@ static struct acpi_sleep_functions acpi_sleep_dispatch[] = {
  ******************************************************************************/
 
 static acpi_status
-acpi_hw_set_firmware_waking_vectors(struct acpi_table_facs *facs,
-                                   acpi_physical_address physical_address,
-                                   acpi_physical_address physical_address64)
+acpi_hw_set_firmware_waking_vector(struct acpi_table_facs *facs,
+                                  acpi_physical_address physical_address,
+                                  acpi_physical_address physical_address64)
 {
-       ACPI_FUNCTION_TRACE(acpi_hw_set_firmware_waking_vectors);
+       ACPI_FUNCTION_TRACE(acpi_hw_set_firmware_waking_vector);
 
 
        /*
@@ -140,12 +138,12 @@ acpi_hw_set_firmware_waking_vectors(struct acpi_table_facs *facs,
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_set_firmware_waking_vectors
+ * FUNCTION:    acpi_set_firmware_waking_vector
  *
  * PARAMETERS:  physical_address    - 32-bit physical address of ACPI real mode
- *                                    entry point.
+ *                                    entry point
  *              physical_address64  - 64-bit physical address of ACPI protected
- *                                    mode entry point.
+ *                                    mode entry point
  *
  * RETURN:      Status
  *
@@ -154,79 +152,23 @@ acpi_hw_set_firmware_waking_vectors(struct acpi_table_facs *facs,
  ******************************************************************************/
 
 acpi_status
-acpi_set_firmware_waking_vectors(acpi_physical_address physical_address,
-                                acpi_physical_address physical_address64)
+acpi_set_firmware_waking_vector(acpi_physical_address physical_address,
+                               acpi_physical_address physical_address64)
 {
 
-       ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vectors);
+       ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector);
 
        if (acpi_gbl_FACS) {
-               (void)acpi_hw_set_firmware_waking_vectors(acpi_gbl_FACS,
-                                                         physical_address,
-                                                         physical_address64);
+               (void)acpi_hw_set_firmware_waking_vector(acpi_gbl_FACS,
+                                                        physical_address,
+                                                        physical_address64);
        }
 
        return_ACPI_STATUS(AE_OK);
 }
 
-ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vectors)
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_set_firmware_waking_vector
- *
- * PARAMETERS:  physical_address    - 32-bit physical address of ACPI real mode
- *                                    entry point.
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Sets the 32-bit firmware_waking_vector field of the FACS
- *
- ******************************************************************************/
-acpi_status acpi_set_firmware_waking_vector(u32 physical_address)
-{
-       acpi_status status;
-
-       ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector);
-
-       status = acpi_set_firmware_waking_vectors((acpi_physical_address)
-                                                 physical_address, 0);
-
-       return_ACPI_STATUS(status);
-}
-
 ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector)
 
-#if ACPI_MACHINE_WIDTH == 64
-/*******************************************************************************
- *
- * FUNCTION:    acpi_set_firmware_waking_vector64
- *
- * PARAMETERS:  physical_address    - 64-bit physical address of ACPI protected
- *                                    mode entry point.
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Sets the 64-bit X_firmware_waking_vector field of the FACS, if
- *              it exists in the table. This function is intended for use with
- *              64-bit host operating systems.
- *
- ******************************************************************************/
-acpi_status acpi_set_firmware_waking_vector64(u64 physical_address)
-{
-       acpi_status status;
-
-       ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector64);
-
-       status = acpi_set_firmware_waking_vectors(0,
-                                                 (acpi_physical_address)
-                                                 physical_address);
-
-       return_ACPI_STATUS(status);
-}
-
-ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector64)
-#endif
 /*******************************************************************************
  *
  * FUNCTION:    acpi_enter_sleep_state_s4bios
@@ -286,6 +228,7 @@ acpi_status acpi_enter_sleep_state_s4bios(void)
                if (ACPI_FAILURE(status)) {
                        return_ACPI_STATUS(status);
                }
+
        } while (!in_value);
 
        return_ACPI_STATUS(AE_OK);
index da55a1c60da180cf4f2aeec66f1dd0f41e22d974..f21568ba325b2f53f2dd82569ecffb8271d9214d 100644 (file)
@@ -96,9 +96,9 @@ acpi_ns_convert_to_integer(union acpi_operand_object *original_object,
                /* Extract each buffer byte to create the integer */
 
                for (i = 0; i < original_object->buffer.length; i++) {
-                       value |=
-                           ((u64)original_object->buffer.
-                            pointer[i] << (i * 8));
+                       value |= ((u64)
+                                 original_object->buffer.pointer[i] << (i *
+                                                                        8));
                }
                break;
 
@@ -153,10 +153,9 @@ acpi_ns_convert_to_string(union acpi_operand_object *original_object,
                                return (AE_NO_MEMORY);
                        }
                } else {
-                       status =
-                           acpi_ex_convert_to_string(original_object,
-                                                     &new_object,
-                                                     ACPI_IMPLICIT_CONVERT_HEX);
+                       status = acpi_ex_convert_to_string(original_object,
+                                                          &new_object,
+                                                          ACPI_IMPLICIT_CONVERT_HEX);
                        if (ACPI_FAILURE(status)) {
                                return (status);
                        }
@@ -244,9 +243,8 @@ acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
 
                /* String-to-Buffer conversion. Simple data copy */
 
-               new_object =
-                   acpi_ut_create_buffer_object(original_object->string.
-                                                length);
+               new_object = acpi_ut_create_buffer_object
+                   (original_object->string.length);
                if (!new_object) {
                        return (AE_NO_MEMORY);
                }
@@ -308,7 +306,8 @@ acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
  *
  * FUNCTION:    acpi_ns_convert_to_unicode
  *
- * PARAMETERS:  original_object     - ASCII String Object to be converted
+ * PARAMETERS:  scope               - Namespace node for the method/object
+ *              original_object     - ASCII String Object to be converted
  *              return_object       - Where the new converted object is returned
  *
  * RETURN:      Status. AE_OK if conversion was successful.
@@ -318,7 +317,8 @@ acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
  ******************************************************************************/
 
 acpi_status
-acpi_ns_convert_to_unicode(union acpi_operand_object *original_object,
+acpi_ns_convert_to_unicode(struct acpi_namespace_node * scope,
+                          union acpi_operand_object *original_object,
                           union acpi_operand_object **return_object)
 {
        union acpi_operand_object *new_object;
@@ -372,7 +372,8 @@ acpi_ns_convert_to_unicode(union acpi_operand_object *original_object,
  *
  * FUNCTION:    acpi_ns_convert_to_resource
  *
- * PARAMETERS:  original_object     - Object to be converted
+ * PARAMETERS:  scope               - Namespace node for the method/object
+ *              original_object     - Object to be converted
  *              return_object       - Where the new converted object is returned
  *
  * RETURN:      Status. AE_OK if conversion was successful
@@ -383,7 +384,8 @@ acpi_ns_convert_to_unicode(union acpi_operand_object *original_object,
  ******************************************************************************/
 
 acpi_status
-acpi_ns_convert_to_resource(union acpi_operand_object *original_object,
+acpi_ns_convert_to_resource(struct acpi_namespace_node * scope,
+                           union acpi_operand_object *original_object,
                            union acpi_operand_object **return_object)
 {
        union acpi_operand_object *new_object;
@@ -444,3 +446,78 @@ acpi_ns_convert_to_resource(union acpi_operand_object *original_object,
        *return_object = new_object;
        return (AE_OK);
 }
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ns_convert_to_reference
+ *
+ * PARAMETERS:  scope               - Namespace node for the method/object
+ *              original_object     - Object to be converted
+ *              return_object       - Where the new converted object is returned
+ *
+ * RETURN:      Status. AE_OK if conversion was successful
+ *
+ * DESCRIPTION: Attempt to convert a Integer object to a object_reference.
+ *              Buffer.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ns_convert_to_reference(struct acpi_namespace_node * scope,
+                            union acpi_operand_object *original_object,
+                            union acpi_operand_object **return_object)
+{
+       union acpi_operand_object *new_object = NULL;
+       acpi_status status;
+       struct acpi_namespace_node *node;
+       union acpi_generic_state scope_info;
+       char *name;
+
+       ACPI_FUNCTION_NAME(ns_convert_to_reference);
+
+       /* Convert path into internal presentation */
+
+       status =
+           acpi_ns_internalize_name(original_object->string.pointer, &name);
+       if (ACPI_FAILURE(status)) {
+               return_ACPI_STATUS(status);
+       }
+
+       /* Find the namespace node */
+
+       scope_info.scope.node =
+           ACPI_CAST_PTR(struct acpi_namespace_node, scope);
+       status =
+           acpi_ns_lookup(&scope_info, name, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
+                          ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
+                          NULL, &node);
+       if (ACPI_FAILURE(status)) {
+
+               /* Check if we are resolving a named reference within a package */
+
+               ACPI_ERROR_NAMESPACE(original_object->string.pointer, status);
+               goto error_exit;
+       }
+
+       /* Create and init a new internal ACPI object */
+
+       new_object = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE);
+       if (!new_object) {
+               status = AE_NO_MEMORY;
+               goto error_exit;
+       }
+       new_object->reference.node = node;
+       new_object->reference.object = node->object;
+       new_object->reference.class = ACPI_REFCLASS_NAME;
+
+       /*
+        * Increase reference of the object if needed (the object is likely a
+        * null for device nodes).
+        */
+       acpi_ut_add_reference(node->object);
+
+error_exit:
+       ACPI_FREE(name);
+       *return_object = new_object;
+       return (AE_OK);
+}
index 37aa5c45ca4b1936dbf18a00a4c40537505c3e2f..bc5ff358b2a72a3201bb9be1e4478869a832cf3e 100644 (file)
@@ -539,11 +539,13 @@ acpi_ns_dump_one_object(acpi_handle obj_handle,
                                acpi_os_printf
                                    ("(Pointer to ACPI Object type %.2X [UNKNOWN])\n",
                                     obj_type);
+
                                bytes_to_dump = 32;
                        } else {
                                acpi_os_printf
                                    ("(Pointer to ACPI Object type %.2X [%s])\n",
                                     obj_type, acpi_ut_get_type_name(obj_type));
+
                                bytes_to_dump =
                                    sizeof(union acpi_operand_object);
                        }
@@ -573,6 +575,7 @@ acpi_ns_dump_one_object(acpi_handle obj_handle,
                         */
                        bytes_to_dump = obj_desc->string.length;
                        obj_desc = (void *)obj_desc->string.pointer;
+
                        acpi_os_printf("(Buffer/String pointer %p length %X)\n",
                                       obj_desc, bytes_to_dump);
                        ACPI_DUMP_BUFFER(obj_desc, bytes_to_dump);
@@ -717,7 +720,7 @@ acpi_ns_dump_one_object_path(acpi_handle obj_handle,
                return (AE_OK);
        }
 
-       pathname = acpi_ns_get_external_pathname(node);
+       pathname = acpi_ns_get_normalized_pathname(node, TRUE);
 
        path_indent = 1;
        if (level <= max_level) {
index 7eba578d36f36d91443f706cd32eb5050b841a13..15e0b2ec5d659f0874876c5ab4e154fd298dcc51 100644 (file)
@@ -135,7 +135,7 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info)
 
        /* Get the full pathname to the object, for use in warning messages */
 
-       info->full_pathname = acpi_ns_get_external_pathname(info->node);
+       info->full_pathname = acpi_ns_get_normalized_pathname(info->node, TRUE);
        if (!info->full_pathname) {
                return_ACPI_STATUS(AE_NO_MEMORY);
        }
index b744a53618eb3977663ab75a6a31e808e96b5aeb..ac59929c3ee947bbb3a527b8e13cb0a7f4e87cf9 100644 (file)
@@ -582,7 +582,8 @@ acpi_ns_init_one_device(acpi_handle obj_handle,
 
                /* Ignore error and move on to next device */
 
-               char *scope_name = acpi_ns_get_external_pathname(info->node);
+               char *scope_name =
+                   acpi_ns_get_normalized_pathname(device_node, TRUE);
 
                ACPI_EXCEPTION((AE_INFO, status, "during %s._INI execution",
                                scope_name));
index 14ab83668207eb389b7edfe6860a472c5a6007ad..14c953e6fe9e27e279a891383d7146c098c854b3 100644 (file)
@@ -149,6 +149,23 @@ unlock:
        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                          "**** Completed Table Object Initialization\n"));
 
+       /*
+        * Execute any module-level code that was detected during the table load
+        * phase. Although illegal since ACPI 2.0, there are many machines that
+        * contain this type of code. Each block of detected executable AML code
+        * outside of any control method is wrapped with a temporary control
+        * method object and placed on a global list. The methods on this list
+        * are executed below.
+        *
+        * This case executes the module-level code for each table immediately
+        * after the table has been loaded. This provides compatibility with
+        * other ACPI implementations. Optionally, the execution can be deferred
+        * until later, see acpi_initialize_objects.
+        */
+       if (!acpi_gbl_group_module_level_code) {
+               acpi_ns_exec_module_code_list();
+       }
+
        return_ACPI_STATUS(status);
 }
 
@@ -321,7 +338,6 @@ acpi_status acpi_ns_unload_namespace(acpi_handle handle)
        /* This function does the real work */
 
        status = acpi_ns_delete_subtree(handle);
-
        return_ACPI_STATUS(status);
 }
 #endif
index 8934b4eddb731eacd5797e9059f4b49eab65c085..521031f9b6c6cd0bf02a860a0707d54d213d8134 100644 (file)
@@ -70,7 +70,6 @@ char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node)
        ACPI_FUNCTION_TRACE_PTR(ns_get_external_pathname, node);
 
        name_buffer = acpi_ns_get_normalized_pathname(node, FALSE);
-
        return_PTR(name_buffer);
 }
 
@@ -93,7 +92,6 @@ acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node)
        ACPI_FUNCTION_ENTRY();
 
        size = acpi_ns_build_normalized_path(node, NULL, 0, FALSE);
-
        return (size);
 }
 
@@ -217,6 +215,7 @@ acpi_ns_build_normalized_path(struct acpi_namespace_node *node,
                        ACPI_PATH_PUT8(full_path, path_size,
                                       AML_DUAL_NAME_PREFIX, length);
                }
+
                ACPI_MOVE_32_TO_32(name, &next_node->name);
                do_no_trailing = no_trailing;
                for (i = 0; i < 4; i++) {
@@ -228,8 +227,10 @@ acpi_ns_build_normalized_path(struct acpi_namespace_node *node,
                                ACPI_PATH_PUT8(full_path, path_size, c, length);
                        }
                }
+
                next_node = next_node->parent;
        }
+
        ACPI_PATH_PUT8(full_path, path_size, AML_ROOT_PREFIX, length);
 
        /* Reverse the path string */
@@ -237,6 +238,7 @@ acpi_ns_build_normalized_path(struct acpi_namespace_node *node,
        if (length <= path_size) {
                left = full_path;
                right = full_path + length - 1;
+
                while (left < right) {
                        c = *left;
                        *left++ = *right;
index 3736d43b18b94aaf45bf5f7dddcc9d2f4ec570c4..43b45a8c2fe48490e5e0dca3c7302654a3cbe9fd 100644 (file)
@@ -141,8 +141,8 @@ acpi_ns_one_complete_parse(u32 pass_number,
 
        /* Parse the AML */
 
-       ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "*PARSE* pass %u parse\n",
-                         pass_number));
+       ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+                         "*PARSE* pass %u parse\n", pass_number));
        status = acpi_ps_parse_aml(walk_state);
 
 cleanup:
@@ -181,6 +181,7 @@ acpi_ns_parse_table(u32 table_index, struct acpi_namespace_node *start_node)
         * performs another complete parse of the AML.
         */
        ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 1\n"));
+
        status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS1,
                                            table_index, start_node);
        if (ACPI_FAILURE(status)) {
index 9bb251932b45c88a7deb186d9e8b2e3abadecee4..c05a83be5c1185023298d3305736d2ee2b5a10f8 100644 (file)
@@ -233,8 +233,9 @@ acpi_ns_check_package(struct acpi_evaluate_info *info,
 
                /* First element is the (Integer) revision */
 
-               status = acpi_ns_check_object_type(info, elements,
-                                                  ACPI_RTYPE_INTEGER, 0);
+               status =
+                   acpi_ns_check_object_type(info, elements,
+                                             ACPI_RTYPE_INTEGER, 0);
                if (ACPI_FAILURE(status)) {
                        return (status);
                }
@@ -252,8 +253,9 @@ acpi_ns_check_package(struct acpi_evaluate_info *info,
 
                /* First element is the (Integer) count of subpackages to follow */
 
-               status = acpi_ns_check_object_type(info, elements,
-                                                  ACPI_RTYPE_INTEGER, 0);
+               status =
+                   acpi_ns_check_object_type(info, elements,
+                                             ACPI_RTYPE_INTEGER, 0);
                if (ACPI_FAILURE(status)) {
                        return (status);
                }
index 77d8103d0094287c27ca7362a3a072ab9e458b2e..6418863f93d50591789b4cec503ce01f98cea185 100644 (file)
@@ -116,6 +116,11 @@ static const struct acpi_simple_repair_info acpi_object_repair_info[] = {
         ACPI_NOT_PACKAGE_ELEMENT,
         acpi_ns_convert_to_resource},
 
+       /* Object reference conversions */
+
+       {"_DEP", ACPI_RTYPE_STRING, ACPI_ALL_PACKAGE_ELEMENTS,
+        acpi_ns_convert_to_reference},
+
        /* Unicode conversions */
 
        {"_MLS", ACPI_RTYPE_STRING, 1,
@@ -172,8 +177,8 @@ acpi_ns_simple_repair(struct acpi_evaluate_info *info,
                                              "Missing expected return value"));
                }
 
-               status =
-                   predefined->object_converter(return_object, &new_object);
+               status = predefined->object_converter(info->node, return_object,
+                                                     &new_object);
                if (ACPI_FAILURE(status)) {
 
                        /* A fatal error occurred during a conversion */
@@ -360,12 +365,15 @@ static const struct acpi_simple_repair_info *acpi_ns_match_simple_repair(struct
                        /* Check if we can actually repair this name/type combination */
 
                        if ((return_btype & this_name->unexpected_btypes) &&
-                           (package_index == this_name->package_index)) {
+                           (this_name->package_index ==
+                            ACPI_ALL_PACKAGE_ELEMENTS
+                            || package_index == this_name->package_index)) {
                                return (this_name);
                        }
 
                        return (NULL);
                }
+
                this_name++;
        }
 
@@ -521,6 +529,7 @@ acpi_ns_remove_null_elements(struct acpi_evaluate_info *info,
                        *dest = *source;
                        dest++;
                }
+
                source++;
        }
 
@@ -572,8 +581,8 @@ acpi_ns_wrap_with_package(struct acpi_evaluate_info *info,
        ACPI_FUNCTION_NAME(ns_wrap_with_package);
 
        /*
-        * Create the new outer package and populate it. The new package will
-        * have a single element, the lone sub-object.
+        * Create the new outer package and populate it. The new
+        * package will have a single element, the lone sub-object.
         */
        pkg_obj_desc = acpi_ut_create_package_object(1);
        if (!pkg_obj_desc) {
index 0515a70f42a4fb6f27a78466b004d34517c8b51c..f6dd2a83ea63b094a8ab850ccf3cb4f6ef08741d 100644 (file)
@@ -225,6 +225,7 @@ static const struct acpi_repair_info *acpi_ns_match_complex_repair(struct
                if (ACPI_COMPARE_NAME(node->name.ascii, this_name->name)) {
                        return (this_name);
                }
+
                this_name++;
        }
 
@@ -301,7 +302,8 @@ acpi_ns_repair_FDE(struct acpi_evaluate_info *info,
                /* We can only repair if we have exactly 5 BYTEs */
 
                if (return_object->buffer.length != ACPI_FDE_BYTE_BUFFER_SIZE) {
-                       ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
+                       ACPI_WARN_PREDEFINED((AE_INFO,
+                                             info->full_pathname,
                                              info->node_flags,
                                              "Incorrect return buffer length %u, expected %u",
                                              return_object->buffer.length,
@@ -321,8 +323,8 @@ acpi_ns_repair_FDE(struct acpi_evaluate_info *info,
                /* Expand each byte to a DWORD */
 
                byte_buffer = return_object->buffer.pointer;
-               dword_buffer =
-                   ACPI_CAST_PTR(u32, buffer_object->buffer.pointer);
+               dword_buffer = ACPI_CAST_PTR(u32,
+                                            buffer_object->buffer.pointer);
 
                for (i = 0; i < ACPI_FDE_FIELD_COUNT; i++) {
                        *dword_buffer = (u32) *byte_buffer;
@@ -461,7 +463,8 @@ acpi_ns_repair_CST(struct acpi_evaluate_info *info,
                removing = FALSE;
 
                if ((*outer_elements)->package.count == 0) {
-                       ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
+                       ACPI_WARN_PREDEFINED((AE_INFO,
+                                             info->full_pathname,
                                              info->node_flags,
                                              "SubPackage[%u] - removing entry due to zero count",
                                              i));
@@ -471,7 +474,8 @@ acpi_ns_repair_CST(struct acpi_evaluate_info *info,
 
                obj_desc = (*outer_elements)->package.elements[1];      /* Index1 = Type */
                if ((u32)obj_desc->integer.value == 0) {
-                       ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
+                       ACPI_WARN_PREDEFINED((AE_INFO,
+                                             info->full_pathname,
                                              info->node_flags,
                                              "SubPackage[%u] - removing entry due to invalid Type(0)",
                                              i));
@@ -538,8 +542,8 @@ acpi_ns_repair_HID(struct acpi_evaluate_info *info,
        }
 
        if (return_object->string.length == 0) {
-               ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
-                                     info->node_flags,
+               ACPI_WARN_PREDEFINED((AE_INFO,
+                                     info->full_pathname, info->node_flags,
                                      "Invalid zero-length _HID or _CID string"));
 
                /* Return AE_OK anyway, let driver handle it */
@@ -710,8 +714,9 @@ acpi_ns_repair_PSS(struct acpi_evaluate_info *info,
                elements = (*outer_elements)->package.elements;
                obj_desc = elements[1]; /* Index1 = power_dissipation */
 
-               if ((u32) obj_desc->integer.value > previous_value) {
-                       ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
+               if ((u32)obj_desc->integer.value > previous_value) {
+                       ACPI_WARN_PREDEFINED((AE_INFO,
+                                             info->full_pathname,
                                              info->node_flags,
                                              "SubPackage[%u,%u] - suspicious power dissipation values",
                                              i - 1, i));
@@ -969,6 +974,7 @@ acpi_ns_remove_element(union acpi_operand_object *obj_desc, u32 index)
                        *dest = *source;
                        dest++;
                }
+
                source++;
        }
 
index d7390401383043d7af82cf51233cdfea4f825566..9cc3564de37ed03e6ea8d01962db55f045ba4b2a 100644 (file)
@@ -105,7 +105,7 @@ acpi_ns_search_one_scope(u32 target_name,
        if (ACPI_LV_NAMES & acpi_dbg_level) {
                char *scope_name;
 
-               scope_name = acpi_ns_get_external_pathname(parent_node);
+               scope_name = acpi_ns_get_normalized_pathname(parent_node, TRUE);
                if (scope_name) {
                        ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
                                          "Searching %s (%p) For [%4.4s] (%s)\n",
index de325ae04ce1cc80ad4a8d2e2f4353af8b011ac8..32f1d956eb7f32fbfd118db11a95cd94e3757f65 100644 (file)
@@ -173,9 +173,10 @@ void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info)
        info->fully_qualified = FALSE;
 
        /*
-        * For the internal name, the required length is 4 bytes per segment, plus
-        * 1 each for root_prefix, multi_name_prefix_op, segment count, trailing null
-        * (which is not really needed, but no there's harm in putting it there)
+        * For the internal name, the required length is 4 bytes per segment,
+        * plus 1 each for root_prefix, multi_name_prefix_op, segment count,
+        * trailing null (which is not really needed, but no there's harm in
+        * putting it there)
         *
         * strlen() + 1 covers the first name_seg, which has no path separator
         */
@@ -699,6 +700,7 @@ acpi_ns_get_node(struct acpi_namespace_node *prefix_node,
                if (!prefix_node) {
                        *return_node = acpi_gbl_root_node;
                }
+
                return_ACPI_STATUS(AE_OK);
        }
 
index 6ee1e52b903d344d31ed5b140f8385204cb5c94c..429f0d27bef06c4ed0381ad49e53f90dc1e8fff6 100644 (file)
@@ -750,8 +750,8 @@ acpi_ns_get_device_callback(acpi_handle obj_handle,
 
        /* We have a valid device, invoke the user function */
 
-       status = info->user_function(obj_handle, nesting_level, info->context,
-                                    return_value);
+       status = info->user_function(obj_handle, nesting_level,
+                                    info->context, return_value);
        return (status);
 }
 
index 4b4d2f43d406f75d9df1853b304eecd89820ffec..669e0f1b09671fe8270ad357108c97372e4c2f7b 100644 (file)
@@ -159,7 +159,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;
+       const char *node_name;
 
        /* Parameter validation */
 
@@ -238,7 +238,6 @@ static char *acpi_ns_copy_device_id(struct acpi_pnp_device_id *dest,
                                    struct acpi_pnp_device_id *source,
                                    char *string_area)
 {
-
        /* Create the destination PNP_DEVICE_ID */
 
        dest->string = string_area;
@@ -263,11 +262,18 @@ static char *acpi_ns_copy_device_id(struct acpi_pnp_device_id *dest,
  *              namespace node and possibly by running several standard
  *              control methods (Such as in the case of a device.)
  *
- * For Device and Processor objects, run the Device _HID, _UID, _CID, _SUB,
- * _CLS, _STA, _ADR, _sx_w, and _sx_d methods.
+ * For Device and Processor objects, run the Device _HID, _UID, _CID, _STA,
+ * _CLS, _ADR, _sx_w, and _sx_d methods.
  *
  * Note: Allocates the return buffer, must be freed by the caller.
  *
+ * Note: This interface is intended to be used during the initial device
+ * discovery namespace traversal. Therefore, no complex methods can be
+ * executed, especially those that access operation regions. Therefore, do
+ * not add any additional methods that could cause problems in this area.
+ * this was the fate of the _SUB method which was found to cause such
+ * problems and was removed (11/2015).
+ *
  ******************************************************************************/
 
 acpi_status
@@ -279,7 +285,6 @@ acpi_get_object_info(acpi_handle handle,
        struct acpi_pnp_device_id_list *cid_list = NULL;
        struct acpi_pnp_device_id *hid = NULL;
        struct acpi_pnp_device_id *uid = NULL;
-       struct acpi_pnp_device_id *sub = NULL;
        struct acpi_pnp_device_id *cls = NULL;
        char *next_id_string;
        acpi_object_type type;
@@ -325,7 +330,7 @@ acpi_get_object_info(acpi_handle handle,
        if ((type == ACPI_TYPE_DEVICE) || (type == ACPI_TYPE_PROCESSOR)) {
                /*
                 * Get extra info for ACPI Device/Processor objects only:
-                * Run the Device _HID, _UID, _SUB, _CID, and _CLS methods.
+                * Run the Device _HID, _UID, _CLS, and _CID methods.
                 *
                 * Note: none of these methods are required, so they may or may
                 * not be present for this device. The Info->Valid bitfield is used
@@ -348,14 +353,6 @@ acpi_get_object_info(acpi_handle handle,
                        valid |= ACPI_VALID_UID;
                }
 
-               /* Execute the Device._SUB method */
-
-               status = acpi_ut_execute_SUB(node, &sub);
-               if (ACPI_SUCCESS(status)) {
-                       info_size += sub->length;
-                       valid |= ACPI_VALID_SUB;
-               }
-
                /* Execute the Device._CID method */
 
                status = acpi_ut_execute_CID(node, &cid_list);
@@ -456,9 +453,8 @@ acpi_get_object_info(acpi_handle handle,
        }
 
        /*
-        * Copy the HID, UID, SUB, and CIDs to the return buffer.
-        * The variable-length strings are copied to the reserved area
-        * at the end of the buffer.
+        * Copy the HID, UID, and CIDs to the return buffer. The variable-length
+        * strings are copied to the reserved area at the end of the buffer.
         *
         * For HID and CID, check if the ID is a PCI Root Bridge.
         */
@@ -476,11 +472,6 @@ acpi_get_object_info(acpi_handle handle,
                                                        uid, next_id_string);
        }
 
-       if (sub) {
-               next_id_string = acpi_ns_copy_device_id(&info->subsystem_id,
-                                                       sub, next_id_string);
-       }
-
        if (cid_list) {
                info->compatible_id_list.count = cid_list->count;
                info->compatible_id_list.list_size = cid_list->list_size;
@@ -522,9 +513,6 @@ cleanup:
        if (uid) {
                ACPI_FREE(uid);
        }
-       if (sub) {
-               ACPI_FREE(sub);
-       }
        if (cid_list) {
                ACPI_FREE(cid_list);
        }
@@ -591,6 +579,7 @@ acpi_status acpi_install_method(u8 *buffer)
        parser_state.aml += acpi_ps_get_opcode_size(opcode);
        parser_state.pkg_end = acpi_ps_get_next_package_end(&parser_state);
        path = acpi_ps_get_next_namestring(&parser_state);
+
        method_flags = *parser_state.aml++;
        aml_start = parser_state.aml;
        aml_length = ACPI_PTR_DIFF(parser_state.pkg_end, aml_start);
index 793383501f81f05cffd099559a0b6d8787f53880..6e1389babb479dd845ce268b86a42e7ef82d5b1b 100644 (file)
@@ -74,10 +74,8 @@ acpi_status acpi_get_type(acpi_handle handle, acpi_object_type * ret_type)
                return (AE_BAD_PARAMETER);
        }
 
-       /*
-        * Special case for the predefined Root Node
-        * (return type ANY)
-        */
+       /* Special case for the predefined Root Node (return type ANY) */
+
        if (handle == ACPI_ROOT_OBJECT) {
                *ret_type = ACPI_TYPE_ANY;
                return (AE_OK);
index 29d8b7b01dca74ad55169e5de786b1b7dc0f476b..f3bcfa20b0ae7e53d425507f70b15cbe8f0427f5 100644 (file)
@@ -269,7 +269,8 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state,
         */
        if (ACPI_SUCCESS(status) &&
            possible_method_call && (node->type == ACPI_TYPE_METHOD)) {
-               if (walk_state->opcode == AML_UNLOAD_OP) {
+               if (GET_CURRENT_ARG_TYPE(walk_state->arg_types) ==
+                   ARGP_SUPERNAME) {
                        /*
                         * acpi_ps_get_next_namestring has increased the AML pointer,
                         * so we need to restore the saved AML pointer for method call.
@@ -696,7 +697,7 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
  *
  * PARAMETERS:  walk_state          - Current state
  *              parser_state        - Current parser state object
- *              arg_type            - The argument type (AML_*_ARG)
+ *              arg_type            - The parser argument type (ARGP_*)
  *              return_arg          - Where the next arg is returned
  *
  * RETURN:      Status, and an op object containing the next argument.
@@ -733,6 +734,7 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
                if (!arg) {
                        return_ACPI_STATUS(AE_NO_MEMORY);
                }
+
                acpi_ps_get_next_simple_arg(parser_state, arg_type, arg);
                break;
 
@@ -798,6 +800,7 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
        case ARGP_TARGET:
        case ARGP_SUPERNAME:
        case ARGP_SIMPLENAME:
+       case ARGP_NAME_OR_REF:
 
                subop = acpi_ps_peek_opcode(parser_state);
                if (subop == 0 ||
@@ -814,17 +817,17 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
                                return_ACPI_STATUS(AE_NO_MEMORY);
                        }
 
-                       /* To support super_name arg of Unload */
+                       /* super_name allows argument to be a method call */
 
-                       if (walk_state->opcode == AML_UNLOAD_OP) {
+                       if (arg_type == ARGP_SUPERNAME) {
                                status =
                                    acpi_ps_get_next_namepath(walk_state,
                                                              parser_state, arg,
-                                                             1);
+                                                             ACPI_POSSIBLE_METHOD_CALL);
 
                                /*
-                                * If the super_name arg of Unload is a method call,
-                                * we have restored the AML pointer, just free this Arg
+                                * If the super_name argument is a method call, we have
+                                * already restored the AML pointer, just free this Arg
                                 */
                                if (arg->common.aml_opcode ==
                                    AML_INT_METHODCALL_OP) {
@@ -835,7 +838,7 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
                                status =
                                    acpi_ps_get_next_namepath(walk_state,
                                                              parser_state, arg,
-                                                             0);
+                                                             ACPI_NOT_METHOD_CALL);
                        }
                } else {
                        /* Single complex argument, nothing returned */
index 03ac8c9a67ab042bc7d5b80348314d659e2ac33c..a57f473bac83006b8cba99cbe86ac5ab390e3242 100644 (file)
@@ -109,10 +109,10 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
 
        case AML_INT_NAMEPATH_OP:       /* AML_NAMESTRING_ARG */
 
-               status =
-                   acpi_ps_get_next_namepath(walk_state,
-                                             &(walk_state->parser_state), op,
-                                             1);
+               status = acpi_ps_get_next_namepath(walk_state,
+                                                  &(walk_state->parser_state),
+                                                  op,
+                                                  ACPI_POSSIBLE_METHOD_CALL);
                if (ACPI_FAILURE(status)) {
                        return_ACPI_STATUS(status);
                }
@@ -124,8 +124,8 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
                /*
                 * Op is not a constant or string, append each argument to the Op
                 */
-               while (GET_CURRENT_ARG_TYPE(walk_state->arg_types)
-                      && !walk_state->arg_count) {
+               while (GET_CURRENT_ARG_TYPE(walk_state->arg_types) &&
+                      !walk_state->arg_count) {
                        walk_state->aml = walk_state->parser_state.aml;
 
                        status =
index ed90fddf2487b205dc17a6cce45a27d89b2c18ee..40909ddeebb3e7dcd11687009748650e827e0ffe 100644 (file)
@@ -185,458 +185,458 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = {
 /* Index           Name                 Parser Args               Interpreter Args                ObjectType                    Class                      Type                  Flags */
 
 /* 00 */ ACPI_OP("Zero", ARGP_ZERO_OP, ARGI_ZERO_OP, ACPI_TYPE_INTEGER,
-                AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT),
+                        AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT),
 /* 01 */ ACPI_OP("One", ARGP_ONE_OP, ARGI_ONE_OP, ACPI_TYPE_INTEGER,
-                AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT),
+                        AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT),
 /* 02 */ ACPI_OP("Alias", ARGP_ALIAS_OP, ARGI_ALIAS_OP,
-                ACPI_TYPE_LOCAL_ALIAS, AML_CLASS_NAMED_OBJECT,
-                AML_TYPE_NAMED_SIMPLE,
-                AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
-                AML_NSNODE | AML_NAMED),
+                        ACPI_TYPE_LOCAL_ALIAS, AML_CLASS_NAMED_OBJECT,
+                        AML_TYPE_NAMED_SIMPLE,
+                        AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+                        AML_NSNODE | AML_NAMED),
 /* 03 */ ACPI_OP("Name", ARGP_NAME_OP, ARGI_NAME_OP, ACPI_TYPE_ANY,
-                AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX,
-                AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
-                AML_NSNODE | AML_NAMED),
+                        AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX,
+                        AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+                        AML_NSNODE | AML_NAMED),
 /* 04 */ ACPI_OP("ByteConst", ARGP_BYTE_OP, ARGI_BYTE_OP,
-                ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
-                AML_TYPE_LITERAL, AML_CONSTANT),
+                        ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
+                        AML_TYPE_LITERAL, AML_CONSTANT),
 /* 05 */ ACPI_OP("WordConst", ARGP_WORD_OP, ARGI_WORD_OP,
-                ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
-                AML_TYPE_LITERAL, AML_CONSTANT),
+                        ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
+                        AML_TYPE_LITERAL, AML_CONSTANT),
 /* 06 */ ACPI_OP("DwordConst", ARGP_DWORD_OP, ARGI_DWORD_OP,
-                ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
-                AML_TYPE_LITERAL, AML_CONSTANT),
+                        ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
+                        AML_TYPE_LITERAL, AML_CONSTANT),
 /* 07 */ ACPI_OP("String", ARGP_STRING_OP, ARGI_STRING_OP,
-                ACPI_TYPE_STRING, AML_CLASS_ARGUMENT,
-                AML_TYPE_LITERAL, AML_CONSTANT),
+                        ACPI_TYPE_STRING, AML_CLASS_ARGUMENT,
+                        AML_TYPE_LITERAL, AML_CONSTANT),
 /* 08 */ ACPI_OP("Scope", ARGP_SCOPE_OP, ARGI_SCOPE_OP,
-                ACPI_TYPE_LOCAL_SCOPE, AML_CLASS_NAMED_OBJECT,
-                AML_TYPE_NAMED_NO_OBJ,
-                AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
-                AML_NSNODE | AML_NAMED),
+                        ACPI_TYPE_LOCAL_SCOPE, AML_CLASS_NAMED_OBJECT,
+                        AML_TYPE_NAMED_NO_OBJ,
+                        AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+                        AML_NSNODE | AML_NAMED),
 /* 09 */ ACPI_OP("Buffer", ARGP_BUFFER_OP, ARGI_BUFFER_OP,
-                ACPI_TYPE_BUFFER, AML_CLASS_CREATE,
-                AML_TYPE_CREATE_OBJECT,
-                AML_HAS_ARGS | AML_DEFER | AML_CONSTANT),
+                        ACPI_TYPE_BUFFER, AML_CLASS_CREATE,
+                        AML_TYPE_CREATE_OBJECT,
+                        AML_HAS_ARGS | AML_DEFER | AML_CONSTANT),
 /* 0A */ ACPI_OP("Package", ARGP_PACKAGE_OP, ARGI_PACKAGE_OP,
-                ACPI_TYPE_PACKAGE, AML_CLASS_CREATE,
-                AML_TYPE_CREATE_OBJECT,
-                AML_HAS_ARGS | AML_DEFER | AML_CONSTANT),
+                        ACPI_TYPE_PACKAGE, AML_CLASS_CREATE,
+                        AML_TYPE_CREATE_OBJECT,
+                        AML_HAS_ARGS | AML_DEFER | AML_CONSTANT),
 /* 0B */ ACPI_OP("Method", ARGP_METHOD_OP, ARGI_METHOD_OP,
-                ACPI_TYPE_METHOD, AML_CLASS_NAMED_OBJECT,
-                AML_TYPE_NAMED_COMPLEX,
-                AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
-                AML_NSNODE | AML_NAMED | AML_DEFER),
+                        ACPI_TYPE_METHOD, AML_CLASS_NAMED_OBJECT,
+                        AML_TYPE_NAMED_COMPLEX,
+                        AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+                        AML_NSNODE | AML_NAMED | AML_DEFER),
 /* 0C */ ACPI_OP("Local0", ARGP_LOCAL0, ARGI_LOCAL0,
-                ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
-                AML_TYPE_LOCAL_VARIABLE, 0),
+                        ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+                        AML_TYPE_LOCAL_VARIABLE, 0),
 /* 0D */ ACPI_OP("Local1", ARGP_LOCAL1, ARGI_LOCAL1,
-                ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
-                AML_TYPE_LOCAL_VARIABLE, 0),
+                        ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+                        AML_TYPE_LOCAL_VARIABLE, 0),
 /* 0E */ ACPI_OP("Local2", ARGP_LOCAL2, ARGI_LOCAL2,
-                ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
-                AML_TYPE_LOCAL_VARIABLE, 0),
+                        ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+                        AML_TYPE_LOCAL_VARIABLE, 0),
 /* 0F */ ACPI_OP("Local3", ARGP_LOCAL3, ARGI_LOCAL3,
-                ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
-                AML_TYPE_LOCAL_VARIABLE, 0),
+                        ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+                        AML_TYPE_LOCAL_VARIABLE, 0),
 /* 10 */ ACPI_OP("Local4", ARGP_LOCAL4, ARGI_LOCAL4,
-                ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
-                AML_TYPE_LOCAL_VARIABLE, 0),
+                        ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+                        AML_TYPE_LOCAL_VARIABLE, 0),
 /* 11 */ ACPI_OP("Local5", ARGP_LOCAL5, ARGI_LOCAL5,
-                ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
-                AML_TYPE_LOCAL_VARIABLE, 0),
+                        ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+                        AML_TYPE_LOCAL_VARIABLE, 0),
 /* 12 */ ACPI_OP("Local6", ARGP_LOCAL6, ARGI_LOCAL6,
-                ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
-                AML_TYPE_LOCAL_VARIABLE, 0),
+                        ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+                        AML_TYPE_LOCAL_VARIABLE, 0),
 /* 13 */ ACPI_OP("Local7", ARGP_LOCAL7, ARGI_LOCAL7,
-                ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
-                AML_TYPE_LOCAL_VARIABLE, 0),
+                        ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+                        AML_TYPE_LOCAL_VARIABLE, 0),
 /* 14 */ ACPI_OP("Arg0", ARGP_ARG0, ARGI_ARG0,
-                ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
-                AML_TYPE_METHOD_ARGUMENT, 0),
+                        ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+                        AML_TYPE_METHOD_ARGUMENT, 0),
 /* 15 */ ACPI_OP("Arg1", ARGP_ARG1, ARGI_ARG1,
-                ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
-                AML_TYPE_METHOD_ARGUMENT, 0),
+                        ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+                        AML_TYPE_METHOD_ARGUMENT, 0),
 /* 16 */ ACPI_OP("Arg2", ARGP_ARG2, ARGI_ARG2,
-                ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
-                AML_TYPE_METHOD_ARGUMENT, 0),
+                        ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+                        AML_TYPE_METHOD_ARGUMENT, 0),
 /* 17 */ ACPI_OP("Arg3", ARGP_ARG3, ARGI_ARG3,
-                ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
-                AML_TYPE_METHOD_ARGUMENT, 0),
+                        ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+                        AML_TYPE_METHOD_ARGUMENT, 0),
 /* 18 */ ACPI_OP("Arg4", ARGP_ARG4, ARGI_ARG4,
-                ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
-                AML_TYPE_METHOD_ARGUMENT, 0),
+                        ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+                        AML_TYPE_METHOD_ARGUMENT, 0),
 /* 19 */ ACPI_OP("Arg5", ARGP_ARG5, ARGI_ARG5,
-                ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
-                AML_TYPE_METHOD_ARGUMENT, 0),
+                        ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+                        AML_TYPE_METHOD_ARGUMENT, 0),
 /* 1A */ ACPI_OP("Arg6", ARGP_ARG6, ARGI_ARG6,
-                ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
-                AML_TYPE_METHOD_ARGUMENT, 0),
+                        ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+                        AML_TYPE_METHOD_ARGUMENT, 0),
 /* 1B */ ACPI_OP("Store", ARGP_STORE_OP, ARGI_STORE_OP, ACPI_TYPE_ANY,
-                AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
-                AML_FLAGS_EXEC_1A_1T_1R),
+                        AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
+                        AML_FLAGS_EXEC_1A_1T_1R),
 /* 1C */ ACPI_OP("RefOf", ARGP_REF_OF_OP, ARGI_REF_OF_OP, ACPI_TYPE_ANY,
-                AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R,
-                AML_FLAGS_EXEC_1A_0T_1R),
+                        AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R,
+                        AML_FLAGS_EXEC_1A_0T_1R),
 /* 1D */ ACPI_OP("Add", ARGP_ADD_OP, ARGI_ADD_OP, ACPI_TYPE_ANY,
-                AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
-                AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+                        AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+                        AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
 /* 1E */ ACPI_OP("Concatenate", ARGP_CONCAT_OP, ARGI_CONCAT_OP,
-                ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-                AML_TYPE_EXEC_2A_1T_1R,
-                AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
+                        ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+                        AML_TYPE_EXEC_2A_1T_1R,
+                        AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
 /* 1F */ ACPI_OP("Subtract", ARGP_SUBTRACT_OP, ARGI_SUBTRACT_OP,
-                ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-                AML_TYPE_EXEC_2A_1T_1R,
-                AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+                        ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+                        AML_TYPE_EXEC_2A_1T_1R,
+                        AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
 /* 20 */ ACPI_OP("Increment", ARGP_INCREMENT_OP, ARGI_INCREMENT_OP,
-                ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-                AML_TYPE_EXEC_1A_0T_1R,
-                AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
+                        ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+                        AML_TYPE_EXEC_1A_0T_1R,
+                        AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
 /* 21 */ ACPI_OP("Decrement", ARGP_DECREMENT_OP, ARGI_DECREMENT_OP,
-                ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-                AML_TYPE_EXEC_1A_0T_1R,
-                AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
+                        ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+                        AML_TYPE_EXEC_1A_0T_1R,
+                        AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
 /* 22 */ ACPI_OP("Multiply", ARGP_MULTIPLY_OP, ARGI_MULTIPLY_OP,
-                ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-                AML_TYPE_EXEC_2A_1T_1R,
-                AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+                        ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+                        AML_TYPE_EXEC_2A_1T_1R,
+                        AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
 /* 23 */ ACPI_OP("Divide", ARGP_DIVIDE_OP, ARGI_DIVIDE_OP,
-                ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-                AML_TYPE_EXEC_2A_2T_1R,
-                AML_FLAGS_EXEC_2A_2T_1R | AML_CONSTANT),
+                        ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+                        AML_TYPE_EXEC_2A_2T_1R,
+                        AML_FLAGS_EXEC_2A_2T_1R | AML_CONSTANT),
 /* 24 */ ACPI_OP("ShiftLeft", ARGP_SHIFT_LEFT_OP, ARGI_SHIFT_LEFT_OP,
-                ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-                AML_TYPE_EXEC_2A_1T_1R,
-                AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+                        ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+                        AML_TYPE_EXEC_2A_1T_1R,
+                        AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
 /* 25 */ ACPI_OP("ShiftRight", ARGP_SHIFT_RIGHT_OP, ARGI_SHIFT_RIGHT_OP,
-                ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-                AML_TYPE_EXEC_2A_1T_1R,
-                AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+                        ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+                        AML_TYPE_EXEC_2A_1T_1R,
+                        AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
 /* 26 */ ACPI_OP("And", ARGP_BIT_AND_OP, ARGI_BIT_AND_OP, ACPI_TYPE_ANY,
-                AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
-                AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+                        AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+                        AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
 /* 27 */ ACPI_OP("NAnd", ARGP_BIT_NAND_OP, ARGI_BIT_NAND_OP,
-                ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-                AML_TYPE_EXEC_2A_1T_1R,
-                AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+                        ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+                        AML_TYPE_EXEC_2A_1T_1R,
+                        AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
 /* 28 */ ACPI_OP("Or", ARGP_BIT_OR_OP, ARGI_BIT_OR_OP, ACPI_TYPE_ANY,
-                AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
-                AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+                        AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+                        AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
 /* 29 */ ACPI_OP("NOr", ARGP_BIT_NOR_OP, ARGI_BIT_NOR_OP, ACPI_TYPE_ANY,
-                AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
-                AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+                        AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+                        AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
 /* 2A */ ACPI_OP("XOr", ARGP_BIT_XOR_OP, ARGI_BIT_XOR_OP, ACPI_TYPE_ANY,
-                AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
-                AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+                        AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+                        AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
 /* 2B */ ACPI_OP("Not", ARGP_BIT_NOT_OP, ARGI_BIT_NOT_OP, ACPI_TYPE_ANY,
-                AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
-                AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+                        AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
+                        AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
 /* 2C */ ACPI_OP("FindSetLeftBit", ARGP_FIND_SET_LEFT_BIT_OP,
-                ARGI_FIND_SET_LEFT_BIT_OP, ACPI_TYPE_ANY,
-                AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
-                AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+                        ARGI_FIND_SET_LEFT_BIT_OP, ACPI_TYPE_ANY,
+                        AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
+                        AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
 /* 2D */ ACPI_OP("FindSetRightBit", ARGP_FIND_SET_RIGHT_BIT_OP,
-                ARGI_FIND_SET_RIGHT_BIT_OP, ACPI_TYPE_ANY,
-                AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
-                AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+                        ARGI_FIND_SET_RIGHT_BIT_OP, ACPI_TYPE_ANY,
+                        AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
+                        AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
 /* 2E */ ACPI_OP("DerefOf", ARGP_DEREF_OF_OP, ARGI_DEREF_OF_OP,
-                ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-                AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R),
+                        ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+                        AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R),
 /* 2F */ ACPI_OP("Notify", ARGP_NOTIFY_OP, ARGI_NOTIFY_OP,
-                ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-                AML_TYPE_EXEC_2A_0T_0R, AML_FLAGS_EXEC_2A_0T_0R),
+                        ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+                        AML_TYPE_EXEC_2A_0T_0R, AML_FLAGS_EXEC_2A_0T_0R),
 /* 30 */ ACPI_OP("SizeOf", ARGP_SIZE_OF_OP, ARGI_SIZE_OF_OP,
-                ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-                AML_TYPE_EXEC_1A_0T_1R,
-                AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE),
+                        ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+                        AML_TYPE_EXEC_1A_0T_1R,
+                        AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE),
 /* 31 */ ACPI_OP("Index", ARGP_INDEX_OP, ARGI_INDEX_OP, ACPI_TYPE_ANY,
-                AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
-                AML_FLAGS_EXEC_2A_1T_1R),
+                        AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+                        AML_FLAGS_EXEC_2A_1T_1R),
 /* 32 */ ACPI_OP("Match", ARGP_MATCH_OP, ARGI_MATCH_OP, ACPI_TYPE_ANY,
-                AML_CLASS_EXECUTE, AML_TYPE_EXEC_6A_0T_1R,
-                AML_FLAGS_EXEC_6A_0T_1R | AML_CONSTANT),
+                        AML_CLASS_EXECUTE, AML_TYPE_EXEC_6A_0T_1R,
+                        AML_FLAGS_EXEC_6A_0T_1R | AML_CONSTANT),
 /* 33 */ ACPI_OP("CreateDWordField", ARGP_CREATE_DWORD_FIELD_OP,
-                ARGI_CREATE_DWORD_FIELD_OP,
-                ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
-                AML_TYPE_CREATE_FIELD,
-                AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
-                AML_DEFER | AML_CREATE),
+                        ARGI_CREATE_DWORD_FIELD_OP,
+                        ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
+                        AML_TYPE_CREATE_FIELD,
+                        AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
+                        AML_DEFER | AML_CREATE),
 /* 34 */ ACPI_OP("CreateWordField", ARGP_CREATE_WORD_FIELD_OP,
-                ARGI_CREATE_WORD_FIELD_OP,
-                ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
-                AML_TYPE_CREATE_FIELD,
-                AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
-                AML_DEFER | AML_CREATE),
+                        ARGI_CREATE_WORD_FIELD_OP,
+                        ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
+                        AML_TYPE_CREATE_FIELD,
+                        AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
+                        AML_DEFER | AML_CREATE),
 /* 35 */ ACPI_OP("CreateByteField", ARGP_CREATE_BYTE_FIELD_OP,
-                ARGI_CREATE_BYTE_FIELD_OP,
-                ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
-                AML_TYPE_CREATE_FIELD,
-                AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
-                AML_DEFER | AML_CREATE),
+                        ARGI_CREATE_BYTE_FIELD_OP,
+                        ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
+                        AML_TYPE_CREATE_FIELD,
+                        AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
+                        AML_DEFER | AML_CREATE),
 /* 36 */ ACPI_OP("CreateBitField", ARGP_CREATE_BIT_FIELD_OP,
-                ARGI_CREATE_BIT_FIELD_OP,
-                ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
-                AML_TYPE_CREATE_FIELD,
-                AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
-                AML_DEFER | AML_CREATE),
-/* 37 */ ACPI_OP("ObjectType", ARGP_TYPE_OP, ARGI_TYPE_OP,
-                ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-                AML_TYPE_EXEC_1A_0T_1R,
-                AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE),
+                        ARGI_CREATE_BIT_FIELD_OP,
+                        ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
+                        AML_TYPE_CREATE_FIELD,
+                        AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
+                        AML_DEFER | AML_CREATE),
+/* 37 */ ACPI_OP("ObjectType", ARGP_OBJECT_TYPE_OP, ARGI_OBJECT_TYPE_OP,
+                        ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+                        AML_TYPE_EXEC_1A_0T_1R,
+                        AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE),
 /* 38 */ ACPI_OP("LAnd", ARGP_LAND_OP, ARGI_LAND_OP, ACPI_TYPE_ANY,
-                AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
+                        AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
                         AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC |
                         AML_CONSTANT),
 /* 39 */ ACPI_OP("LOr", ARGP_LOR_OP, ARGI_LOR_OP, ACPI_TYPE_ANY,
-                AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
-                        AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC |
+                        AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
+                        AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC |
                         AML_CONSTANT),
 /* 3A */ ACPI_OP("LNot", ARGP_LNOT_OP, ARGI_LNOT_OP, ACPI_TYPE_ANY,
-                AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R,
-                AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
+                        AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R,
+                        AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
 /* 3B */ ACPI_OP("LEqual", ARGP_LEQUAL_OP, ARGI_LEQUAL_OP,
-                ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-                AML_TYPE_EXEC_2A_0T_1R,
-                AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT),
+                        ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+                        AML_TYPE_EXEC_2A_0T_1R,
+                        AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT),
 /* 3C */ ACPI_OP("LGreater", ARGP_LGREATER_OP, ARGI_LGREATER_OP,
-                ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-                AML_TYPE_EXEC_2A_0T_1R,
-                AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT),
+                        ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+                        AML_TYPE_EXEC_2A_0T_1R,
+                        AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT),
 /* 3D */ ACPI_OP("LLess", ARGP_LLESS_OP, ARGI_LLESS_OP, ACPI_TYPE_ANY,
-                AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
-                AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT),
+                        AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
+                        AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT),
 /* 3E */ ACPI_OP("If", ARGP_IF_OP, ARGI_IF_OP, ACPI_TYPE_ANY,
-                AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
+                        AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
 /* 3F */ ACPI_OP("Else", ARGP_ELSE_OP, ARGI_ELSE_OP, ACPI_TYPE_ANY,
-                AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
+                        AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
 /* 40 */ ACPI_OP("While", ARGP_WHILE_OP, ARGI_WHILE_OP, ACPI_TYPE_ANY,
-                AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
+                        AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
 /* 41 */ ACPI_OP("Noop", ARGP_NOOP_OP, ARGI_NOOP_OP, ACPI_TYPE_ANY,
-                AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
+                        AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
 /* 42 */ ACPI_OP("Return", ARGP_RETURN_OP, ARGI_RETURN_OP,
-                ACPI_TYPE_ANY, AML_CLASS_CONTROL,
-                AML_TYPE_CONTROL, AML_HAS_ARGS),
+                        ACPI_TYPE_ANY, AML_CLASS_CONTROL,
+                        AML_TYPE_CONTROL, AML_HAS_ARGS),
 /* 43 */ ACPI_OP("Break", ARGP_BREAK_OP, ARGI_BREAK_OP, ACPI_TYPE_ANY,
-                AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
+                        AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
 /* 44 */ ACPI_OP("BreakPoint", ARGP_BREAK_POINT_OP, ARGI_BREAK_POINT_OP,
-                ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
+                        ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
 /* 45 */ ACPI_OP("Ones", ARGP_ONES_OP, ARGI_ONES_OP, ACPI_TYPE_INTEGER,
-                AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT),
+                        AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT),
 
 /* Prefixed opcodes (Two-byte opcodes with a prefix op) */
 
 /* 46 */ ACPI_OP("Mutex", ARGP_MUTEX_OP, ARGI_MUTEX_OP, ACPI_TYPE_MUTEX,
-                AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE,
-                AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
-                AML_NSNODE | AML_NAMED),
+                        AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE,
+                        AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+                        AML_NSNODE | AML_NAMED),
 /* 47 */ ACPI_OP("Event", ARGP_EVENT_OP, ARGI_EVENT_OP, ACPI_TYPE_EVENT,
-                AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE,
-                AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
+                        AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE,
+                        AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
 /* 48 */ ACPI_OP("CondRefOf", ARGP_COND_REF_OF_OP, ARGI_COND_REF_OF_OP,
-                ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-                AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R),
+                        ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+                        AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R),
 /* 49 */ ACPI_OP("CreateField", ARGP_CREATE_FIELD_OP,
-                ARGI_CREATE_FIELD_OP, ACPI_TYPE_BUFFER_FIELD,
-                AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD,
-                AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
-                AML_DEFER | AML_FIELD | AML_CREATE),
+                        ARGI_CREATE_FIELD_OP, ACPI_TYPE_BUFFER_FIELD,
+                        AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD,
+                        AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
+                        AML_DEFER | AML_FIELD | AML_CREATE),
 /* 4A */ ACPI_OP("Load", ARGP_LOAD_OP, ARGI_LOAD_OP, ACPI_TYPE_ANY,
-                AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_0R,
-                AML_FLAGS_EXEC_1A_1T_0R),
+                        AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_0R,
+                        AML_FLAGS_EXEC_1A_1T_0R),
 /* 4B */ ACPI_OP("Stall", ARGP_STALL_OP, ARGI_STALL_OP, ACPI_TYPE_ANY,
-                AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R,
-                AML_FLAGS_EXEC_1A_0T_0R),
+                        AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R,
+                        AML_FLAGS_EXEC_1A_0T_0R),
 /* 4C */ ACPI_OP("Sleep", ARGP_SLEEP_OP, ARGI_SLEEP_OP, ACPI_TYPE_ANY,
-                AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R,
-                AML_FLAGS_EXEC_1A_0T_0R),
+                        AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R,
+                        AML_FLAGS_EXEC_1A_0T_0R),
 /* 4D */ ACPI_OP("Acquire", ARGP_ACQUIRE_OP, ARGI_ACQUIRE_OP,
-                ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-                AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R),
+                        ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+                        AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R),
 /* 4E */ ACPI_OP("Signal", ARGP_SIGNAL_OP, ARGI_SIGNAL_OP,
-                ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-                AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
+                        ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+                        AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
 /* 4F */ ACPI_OP("Wait", ARGP_WAIT_OP, ARGI_WAIT_OP, ACPI_TYPE_ANY,
-                AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
-                AML_FLAGS_EXEC_2A_0T_1R),
+                        AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
+                        AML_FLAGS_EXEC_2A_0T_1R),
 /* 50 */ ACPI_OP("Reset", ARGP_RESET_OP, ARGI_RESET_OP, ACPI_TYPE_ANY,
-                AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R,
-                AML_FLAGS_EXEC_1A_0T_0R),
+                        AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R,
+                        AML_FLAGS_EXEC_1A_0T_0R),
 /* 51 */ ACPI_OP("Release", ARGP_RELEASE_OP, ARGI_RELEASE_OP,
-                ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-                AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
+                        ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+                        AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
 /* 52 */ ACPI_OP("FromBCD", ARGP_FROM_BCD_OP, ARGI_FROM_BCD_OP,
-                ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-                AML_TYPE_EXEC_1A_1T_1R,
-                AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+                        ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+                        AML_TYPE_EXEC_1A_1T_1R,
+                        AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
 /* 53 */ ACPI_OP("ToBCD", ARGP_TO_BCD_OP, ARGI_TO_BCD_OP, ACPI_TYPE_ANY,
-                AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
-                AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+                        AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
+                        AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
 /* 54 */ ACPI_OP("Unload", ARGP_UNLOAD_OP, ARGI_UNLOAD_OP,
-                ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-                AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
+                        ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+                        AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
 /* 55 */ ACPI_OP("Revision", ARGP_REVISION_OP, ARGI_REVISION_OP,
-                ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
-                AML_TYPE_CONSTANT, 0),
+                        ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
+                        AML_TYPE_CONSTANT, 0),
 /* 56 */ ACPI_OP("Debug", ARGP_DEBUG_OP, ARGI_DEBUG_OP,
-                ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
-                AML_TYPE_CONSTANT, 0),
+                        ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+                        AML_TYPE_CONSTANT, 0),
 /* 57 */ ACPI_OP("Fatal", ARGP_FATAL_OP, ARGI_FATAL_OP, ACPI_TYPE_ANY,
-                AML_CLASS_EXECUTE, AML_TYPE_EXEC_3A_0T_0R,
-                AML_FLAGS_EXEC_3A_0T_0R),
+                        AML_CLASS_EXECUTE, AML_TYPE_EXEC_3A_0T_0R,
+                        AML_FLAGS_EXEC_3A_0T_0R),
 /* 58 */ ACPI_OP("OperationRegion", ARGP_REGION_OP, ARGI_REGION_OP,
-                ACPI_TYPE_REGION, AML_CLASS_NAMED_OBJECT,
-                AML_TYPE_NAMED_COMPLEX,
-                AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
-                AML_NSNODE | AML_NAMED | AML_DEFER),
+                        ACPI_TYPE_REGION, AML_CLASS_NAMED_OBJECT,
+                        AML_TYPE_NAMED_COMPLEX,
+                        AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+                        AML_NSNODE | AML_NAMED | AML_DEFER),
 /* 59 */ ACPI_OP("Field", ARGP_FIELD_OP, ARGI_FIELD_OP, ACPI_TYPE_ANY,
-                AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD,
+                        AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD,
                         AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
                         AML_FIELD),
 /* 5A */ ACPI_OP("Device", ARGP_DEVICE_OP, ARGI_DEVICE_OP,
-                ACPI_TYPE_DEVICE, AML_CLASS_NAMED_OBJECT,
-                AML_TYPE_NAMED_NO_OBJ,
-                AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
-                AML_NSNODE | AML_NAMED),
+                        ACPI_TYPE_DEVICE, AML_CLASS_NAMED_OBJECT,
+                        AML_TYPE_NAMED_NO_OBJ,
+                        AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+                        AML_NSNODE | AML_NAMED),
 /* 5B */ ACPI_OP("Processor", ARGP_PROCESSOR_OP, ARGI_PROCESSOR_OP,
-                ACPI_TYPE_PROCESSOR, AML_CLASS_NAMED_OBJECT,
-                AML_TYPE_NAMED_SIMPLE,
-                AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
-                AML_NSNODE | AML_NAMED),
+                        ACPI_TYPE_PROCESSOR, AML_CLASS_NAMED_OBJECT,
+                        AML_TYPE_NAMED_SIMPLE,
+                        AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+                        AML_NSNODE | AML_NAMED),
 /* 5C */ ACPI_OP("PowerResource", ARGP_POWER_RES_OP, ARGI_POWER_RES_OP,
-                ACPI_TYPE_POWER, AML_CLASS_NAMED_OBJECT,
-                AML_TYPE_NAMED_SIMPLE,
-                AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
-                AML_NSNODE | AML_NAMED),
+                        ACPI_TYPE_POWER, AML_CLASS_NAMED_OBJECT,
+                        AML_TYPE_NAMED_SIMPLE,
+                        AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+                        AML_NSNODE | AML_NAMED),
 /* 5D */ ACPI_OP("ThermalZone", ARGP_THERMAL_ZONE_OP,
-                ARGI_THERMAL_ZONE_OP, ACPI_TYPE_THERMAL,
-                AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ,
-                AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
-                AML_NSNODE | AML_NAMED),
+                        ARGI_THERMAL_ZONE_OP, ACPI_TYPE_THERMAL,
+                        AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ,
+                        AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+                        AML_NSNODE | AML_NAMED),
 /* 5E */ ACPI_OP("IndexField", ARGP_INDEX_FIELD_OP, ARGI_INDEX_FIELD_OP,
-                ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT,
-                AML_TYPE_NAMED_FIELD,
-                        AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+                        ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT,
+                        AML_TYPE_NAMED_FIELD,
+                        AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
                         AML_FIELD),
 /* 5F */ ACPI_OP("BankField", ARGP_BANK_FIELD_OP, ARGI_BANK_FIELD_OP,
-                        ACPI_TYPE_LOCAL_BANK_FIELD,
+                        ACPI_TYPE_LOCAL_BANK_FIELD,
                         AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD,
-                        AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+                        AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
                         AML_FIELD | AML_DEFER),
 
 /* Internal opcodes that map to invalid AML opcodes */
 
 /* 60 */ ACPI_OP("LNotEqual", ARGP_LNOTEQUAL_OP, ARGI_LNOTEQUAL_OP,
-                ACPI_TYPE_ANY, AML_CLASS_INTERNAL,
-                AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT),
+                        ACPI_TYPE_ANY, AML_CLASS_INTERNAL,
+                        AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT),
 /* 61 */ ACPI_OP("LLessEqual", ARGP_LLESSEQUAL_OP, ARGI_LLESSEQUAL_OP,
-                ACPI_TYPE_ANY, AML_CLASS_INTERNAL,
-                AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT),
+                        ACPI_TYPE_ANY, AML_CLASS_INTERNAL,
+                        AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT),
 /* 62 */ ACPI_OP("LGreaterEqual", ARGP_LGREATEREQUAL_OP,
-                ARGI_LGREATEREQUAL_OP, ACPI_TYPE_ANY,
-                AML_CLASS_INTERNAL, AML_TYPE_BOGUS,
-                AML_HAS_ARGS | AML_CONSTANT),
+                        ARGI_LGREATEREQUAL_OP, ACPI_TYPE_ANY,
+                        AML_CLASS_INTERNAL, AML_TYPE_BOGUS,
+                        AML_HAS_ARGS | AML_CONSTANT),
 /* 63 */ ACPI_OP("-NamePath-", ARGP_NAMEPATH_OP, ARGI_NAMEPATH_OP,
-                ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
-                AML_TYPE_LITERAL, AML_NSOBJECT | AML_NSNODE),
+                        ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+                        AML_TYPE_LITERAL, AML_NSOBJECT | AML_NSNODE),
 /* 64 */ ACPI_OP("-MethodCall-", ARGP_METHODCALL_OP, ARGI_METHODCALL_OP,
-                ACPI_TYPE_METHOD, AML_CLASS_METHOD_CALL,
-                AML_TYPE_METHOD_CALL,
-                AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE),
+                        ACPI_TYPE_METHOD, AML_CLASS_METHOD_CALL,
+                        AML_TYPE_METHOD_CALL,
+                        AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE),
 /* 65 */ ACPI_OP("-ByteList-", ARGP_BYTELIST_OP, ARGI_BYTELIST_OP,
-                ACPI_TYPE_ANY, AML_CLASS_ARGUMENT,
-                AML_TYPE_LITERAL, 0),
+                        ACPI_TYPE_ANY, AML_CLASS_ARGUMENT,
+                        AML_TYPE_LITERAL, 0),
 /* 66 */ ACPI_OP("-ReservedField-", ARGP_RESERVEDFIELD_OP,
-                ARGI_RESERVEDFIELD_OP, ACPI_TYPE_ANY,
-                AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0),
+                        ARGI_RESERVEDFIELD_OP, ACPI_TYPE_ANY,
+                        AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0),
 /* 67 */ ACPI_OP("-NamedField-", ARGP_NAMEDFIELD_OP, ARGI_NAMEDFIELD_OP,
-                ACPI_TYPE_ANY, AML_CLASS_INTERNAL,
-                AML_TYPE_BOGUS,
-                AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
+                        ACPI_TYPE_ANY, AML_CLASS_INTERNAL,
+                        AML_TYPE_BOGUS,
+                        AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
 /* 68 */ ACPI_OP("-AccessField-", ARGP_ACCESSFIELD_OP,
-                ARGI_ACCESSFIELD_OP, ACPI_TYPE_ANY,
-                AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0),
+                        ARGI_ACCESSFIELD_OP, ACPI_TYPE_ANY,
+                        AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0),
 /* 69 */ ACPI_OP("-StaticString", ARGP_STATICSTRING_OP,
-                ARGI_STATICSTRING_OP, ACPI_TYPE_ANY,
-                AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0),
+                        ARGI_STATICSTRING_OP, ACPI_TYPE_ANY,
+                        AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0),
 /* 6A */ ACPI_OP("-Return Value-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY,
-                AML_CLASS_RETURN_VALUE, AML_TYPE_RETURN,
-                AML_HAS_ARGS | AML_HAS_RETVAL),
+                        AML_CLASS_RETURN_VALUE, AML_TYPE_RETURN,
+                        AML_HAS_ARGS | AML_HAS_RETVAL),
 /* 6B */ ACPI_OP("-UNKNOWN_OP-", ARG_NONE, ARG_NONE, ACPI_TYPE_INVALID,
-                AML_CLASS_UNKNOWN, AML_TYPE_BOGUS, AML_HAS_ARGS),
+                        AML_CLASS_UNKNOWN, AML_TYPE_BOGUS, AML_HAS_ARGS),
 /* 6C */ ACPI_OP("-ASCII_ONLY-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY,
-                AML_CLASS_ASCII, AML_TYPE_BOGUS, AML_HAS_ARGS),
+                        AML_CLASS_ASCII, AML_TYPE_BOGUS, AML_HAS_ARGS),
 /* 6D */ ACPI_OP("-PREFIX_ONLY-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY,
-                AML_CLASS_PREFIX, AML_TYPE_BOGUS, AML_HAS_ARGS),
+                        AML_CLASS_PREFIX, AML_TYPE_BOGUS, AML_HAS_ARGS),
 
 /* ACPI 2.0 opcodes */
 
 /* 6E */ ACPI_OP("QwordConst", ARGP_QWORD_OP, ARGI_QWORD_OP,
-                ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
-                AML_TYPE_LITERAL, AML_CONSTANT),
+                        ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
+                        AML_TYPE_LITERAL, AML_CONSTANT),
        /* 6F */ ACPI_OP("Package", /* Var */ ARGP_VAR_PACKAGE_OP,
                         ARGI_VAR_PACKAGE_OP, ACPI_TYPE_PACKAGE,
                         AML_CLASS_CREATE, AML_TYPE_CREATE_OBJECT,
                         AML_HAS_ARGS | AML_DEFER),
 /* 70 */ ACPI_OP("ConcatenateResTemplate", ARGP_CONCAT_RES_OP,
-                ARGI_CONCAT_RES_OP, ACPI_TYPE_ANY,
-                AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
-                AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
+                        ARGI_CONCAT_RES_OP, ACPI_TYPE_ANY,
+                        AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+                        AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
 /* 71 */ ACPI_OP("Mod", ARGP_MOD_OP, ARGI_MOD_OP, ACPI_TYPE_ANY,
-                AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
-                AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
+                        AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+                        AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
 /* 72 */ ACPI_OP("CreateQWordField", ARGP_CREATE_QWORD_FIELD_OP,
-                ARGI_CREATE_QWORD_FIELD_OP,
-                ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
-                AML_TYPE_CREATE_FIELD,
-                AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
-                AML_DEFER | AML_CREATE),
+                        ARGI_CREATE_QWORD_FIELD_OP,
+                        ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
+                        AML_TYPE_CREATE_FIELD,
+                        AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
+                        AML_DEFER | AML_CREATE),
 /* 73 */ ACPI_OP("ToBuffer", ARGP_TO_BUFFER_OP, ARGI_TO_BUFFER_OP,
-                ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-                AML_TYPE_EXEC_1A_1T_1R,
-                AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+                        ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+                        AML_TYPE_EXEC_1A_1T_1R,
+                        AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
 /* 74 */ ACPI_OP("ToDecimalString", ARGP_TO_DEC_STR_OP,
-                ARGI_TO_DEC_STR_OP, ACPI_TYPE_ANY,
-                AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
-                AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+                        ARGI_TO_DEC_STR_OP, ACPI_TYPE_ANY,
+                        AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
+                        AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
 /* 75 */ ACPI_OP("ToHexString", ARGP_TO_HEX_STR_OP, ARGI_TO_HEX_STR_OP,
-                ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-                AML_TYPE_EXEC_1A_1T_1R,
-                AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+                        ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+                        AML_TYPE_EXEC_1A_1T_1R,
+                        AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
 /* 76 */ ACPI_OP("ToInteger", ARGP_TO_INTEGER_OP, ARGI_TO_INTEGER_OP,
-                ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-                AML_TYPE_EXEC_1A_1T_1R,
-                AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+                        ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+                        AML_TYPE_EXEC_1A_1T_1R,
+                        AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
 /* 77 */ ACPI_OP("ToString", ARGP_TO_STRING_OP, ARGI_TO_STRING_OP,
-                ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-                AML_TYPE_EXEC_2A_1T_1R,
-                AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
+                        ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+                        AML_TYPE_EXEC_2A_1T_1R,
+                        AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
 /* 78 */ ACPI_OP("CopyObject", ARGP_COPY_OP, ARGI_COPY_OP,
-                ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-                AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R),
+                        ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+                        AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R),
 /* 79 */ ACPI_OP("Mid", ARGP_MID_OP, ARGI_MID_OP, ACPI_TYPE_ANY,
-                AML_CLASS_EXECUTE, AML_TYPE_EXEC_3A_1T_1R,
-                AML_FLAGS_EXEC_3A_1T_1R | AML_CONSTANT),
+                        AML_CLASS_EXECUTE, AML_TYPE_EXEC_3A_1T_1R,
+                        AML_FLAGS_EXEC_3A_1T_1R | AML_CONSTANT),
 /* 7A */ ACPI_OP("Continue", ARGP_CONTINUE_OP, ARGI_CONTINUE_OP,
-                ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
+                        ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
 /* 7B */ ACPI_OP("LoadTable", ARGP_LOAD_TABLE_OP, ARGI_LOAD_TABLE_OP,
-                ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-                AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R),
+                        ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+                        AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R),
 /* 7C */ ACPI_OP("DataTableRegion", ARGP_DATA_REGION_OP,
-                ARGI_DATA_REGION_OP, ACPI_TYPE_REGION,
-                AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX,
-                AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
-                AML_NSNODE | AML_NAMED | AML_DEFER),
+                        ARGI_DATA_REGION_OP, ACPI_TYPE_REGION,
+                        AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX,
+                        AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+                        AML_NSNODE | AML_NAMED | AML_DEFER),
 /* 7D */ ACPI_OP("[EvalSubTree]", ARGP_SCOPE_OP, ARGI_SCOPE_OP,
-                ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT,
-                AML_TYPE_NAMED_NO_OBJ,
-                        AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+                        ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT,
+                        AML_TYPE_NAMED_NO_OBJ,
+                        AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
                         AML_NSNODE),
 
 /* ACPI 3.0 opcodes */
 
 /* 7E */ ACPI_OP("Timer", ARGP_TIMER_OP, ARGI_TIMER_OP, ACPI_TYPE_ANY,
-                AML_CLASS_EXECUTE, AML_TYPE_EXEC_0A_0T_1R,
+                        AML_CLASS_EXECUTE, AML_TYPE_EXEC_0A_0T_1R,
                         AML_FLAGS_EXEC_0A_0T_1R),
 
 /* ACPI 5.0 opcodes */
index 98001d7f6f8035534bb4f2d700b2f47415b8a1dd..b729d9b291d0a511be77233165388d8944345e4b 100644 (file)
@@ -526,8 +526,8 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state)
                        }
 
                        /*
-                        * If the transfer to the new method method call worked, a new walk
-                        * state was created -- get it
+                        * If the transfer to the new method method call worked
+                        *, a new walk state was created -- get it
                         */
                        walk_state = acpi_ds_get_current_walk_state(thread);
                        continue;
@@ -544,8 +544,8 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state)
                        /* Check for possible multi-thread reentrancy problem */
 
                        if ((status == AE_ALREADY_EXISTS) &&
-                           (!(walk_state->method_desc->method.
-                              info_flags & ACPI_METHOD_SERIALIZED))) {
+                           (!(walk_state->method_desc->method.info_flags &
+                              ACPI_METHOD_SERIALIZED))) {
                                /*
                                 * Method is not serialized and tried to create an object
                                 * twice. The probable cause is that the method cannot
index 71d2877cd2cefa9c1a98bcae4e3dbb686a20ffea..6cb02a2a1468219928e90767cfd0cfb462d8d73e 100644 (file)
@@ -175,8 +175,8 @@ void acpi_ps_free_op(union acpi_parse_object *op)
        ACPI_FUNCTION_NAME(ps_free_op);
 
        if (op->common.aml_opcode == AML_INT_RETURN_VALUE_OP) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Free retval op: %p\n",
-                                 op));
+               ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+                                 "Free retval op: %p\n", op));
        }
 
        if (op->common.flags & ACPI_PARSEOP_GENERIC) {
index ba5f691712882673fe76d83384fe29ec360dcda3..f620d4395b66b7bbff604199aea97270cb8b516e 100644 (file)
@@ -99,6 +99,7 @@ void acpi_ps_delete_parse_tree(union acpi_parse_object *subtree_root)
                if (op == subtree_root) {
                        return_VOID;
                }
+
                if (next) {
                        op = next;
                } else {
index 66d406e8fe366a28430158dc7b3d9165e930b607..bdb7e73cdf4a447c54eecac48e305d15c7092fc3 100644 (file)
@@ -312,8 +312,8 @@ acpi_rs_get_address_common(struct acpi_resource *resource,
 
        /* Validate the Resource Type */
 
-       if ((aml->address.resource_type > 2)
-           && (aml->address.resource_type < 0xC0)) {
+       if ((aml->address.resource_type > 2) &&
+           (aml->address.resource_type < 0xC0)) {
                return (FALSE);
        }
 
index cb739a6949311d771c9113b645b48989fcfce0b4..88fce58cc54583a911d022ab3d0f0f7355fd44ef 100644 (file)
@@ -143,16 +143,17 @@ acpi_rs_stream_option_length(u32 resource_length,
        ACPI_FUNCTION_ENTRY();
 
        /*
-        * The resource_source_index and resource_source are optional elements of some
-        * Large-type resource descriptors.
+        * The resource_source_index and resource_source are optional elements of
+        * some Large-type resource descriptors.
         */
 
        /*
-        * If the length of the actual resource descriptor is greater than the ACPI
-        * spec-defined minimum length, it means that a resource_source_index exists
-        * and is followed by a (required) null terminated string. The string length
-        * (including the null terminator) is the resource length minus the minimum
-        * length, minus one byte for the resource_source_index itself.
+        * If the length of the actual resource descriptor is greater than the
+        * ACPI spec-defined minimum length, it means that a resource_source_index
+        * exists and is followed by a (required) null terminated string. The
+        * string length (including the null terminator) is the resource length
+        * minus the minimum length, minus one byte for the resource_source_index
+        * itself.
         */
        if (resource_length > minimum_aml_resource_length) {
 
@@ -277,11 +278,11 @@ acpi_rs_get_aml_length(struct acpi_resource *resource,
                         * 16-Bit Address Resource:
                         * Add the size of the optional resource_source info
                         */
-                       total_size = (acpi_rs_length)
-                           (total_size +
-                            acpi_rs_struct_option_length(&resource->data.
-                                                         address16.
-                                                         resource_source));
+                       total_size = (acpi_rs_length) (total_size +
+                                                      acpi_rs_struct_option_length
+                                                      (&resource->data.
+                                                       address16.
+                                                       resource_source));
                        break;
 
                case ACPI_RESOURCE_TYPE_ADDRESS32:
@@ -289,11 +290,11 @@ acpi_rs_get_aml_length(struct acpi_resource *resource,
                         * 32-Bit Address Resource:
                         * Add the size of the optional resource_source info
                         */
-                       total_size = (acpi_rs_length)
-                           (total_size +
-                            acpi_rs_struct_option_length(&resource->data.
-                                                         address32.
-                                                         resource_source));
+                       total_size = (acpi_rs_length) (total_size +
+                                                      acpi_rs_struct_option_length
+                                                      (&resource->data.
+                                                       address32.
+                                                       resource_source));
                        break;
 
                case ACPI_RESOURCE_TYPE_ADDRESS64:
@@ -301,11 +302,11 @@ acpi_rs_get_aml_length(struct acpi_resource *resource,
                         * 64-Bit Address Resource:
                         * Add the size of the optional resource_source info
                         */
-                       total_size = (acpi_rs_length)
-                           (total_size +
-                            acpi_rs_struct_option_length(&resource->data.
-                                                         address64.
-                                                         resource_source));
+                       total_size = (acpi_rs_length) (total_size +
+                                                      acpi_rs_struct_option_length
+                                                      (&resource->data.
+                                                       address64.
+                                                       resource_source));
                        break;
 
                case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
@@ -314,26 +315,28 @@ acpi_rs_get_aml_length(struct acpi_resource *resource,
                         * Add the size of each additional optional interrupt beyond the
                         * required 1 (4 bytes for each u32 interrupt number)
                         */
-                       total_size = (acpi_rs_length)
-                           (total_size +
-                            ((resource->data.extended_irq.interrupt_count -
-                              1) * 4) +
-                            /* Add the size of the optional resource_source info */
-                            acpi_rs_struct_option_length(&resource->data.
-                                                         extended_irq.
-                                                         resource_source));
+                       total_size = (acpi_rs_length) (total_size +
+                                                      ((resource->data.
+                                                        extended_irq.
+                                                        interrupt_count -
+                                                        1) * 4) +
+                                                      /* Add the size of the optional resource_source info */
+                                                      acpi_rs_struct_option_length
+                                                      (&resource->data.
+                                                       extended_irq.
+                                                       resource_source));
                        break;
 
                case ACPI_RESOURCE_TYPE_GPIO:
 
-                       total_size =
-                           (acpi_rs_length) (total_size +
-                                             (resource->data.gpio.
-                                              pin_table_length * 2) +
-                                             resource->data.gpio.
-                                             resource_source.string_length +
-                                             resource->data.gpio.
-                                             vendor_length);
+                       total_size = (acpi_rs_length) (total_size +
+                                                      (resource->data.gpio.
+                                                       pin_table_length * 2) +
+                                                      resource->data.gpio.
+                                                      resource_source.
+                                                      string_length +
+                                                      resource->data.gpio.
+                                                      vendor_length);
 
                        break;
 
@@ -566,8 +569,8 @@ acpi_rs_get_list_length(u8 * aml_buffer,
                            acpi_gbl_resource_struct_sizes[resource_index] +
                            extra_struct_bytes;
                }
-               buffer_size = (u32)ACPI_ROUND_UP_TO_NATIVE_WORD(buffer_size);
 
+               buffer_size = (u32)ACPI_ROUND_UP_TO_NATIVE_WORD(buffer_size);
                *size_needed += buffer_size;
 
                ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
index a5344428f3ae7985668f1a0b52eeca2ac0710d46..603e544e3f641c68702ce8f6d8117a5ee4cf9128 100644 (file)
@@ -81,8 +81,9 @@ acpi_buffer_to_resource(u8 *aml_buffer,
 
        /* Get the required length for the converted resource */
 
-       status = acpi_rs_get_list_length(aml_buffer, aml_buffer_length,
-                                        &list_size_needed);
+       status =
+           acpi_rs_get_list_length(aml_buffer, aml_buffer_length,
+                                   &list_size_needed);
        if (status == AE_AML_NO_RESOURCE_END_TAG) {
                status = AE_OK;
        }
@@ -232,8 +233,9 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
 
        /* Get the required buffer length */
 
-       status = acpi_rs_get_pci_routing_table_length(package_object,
-                                                     &buffer_size_needed);
+       status =
+           acpi_rs_get_pci_routing_table_length(package_object,
+                                                &buffer_size_needed);
        if (ACPI_FAILURE(status)) {
                return_ACPI_STATUS(status);
        }
@@ -270,9 +272,9 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
                user_prt = ACPI_CAST_PTR(struct acpi_pci_routing_table, buffer);
 
                /*
-                * Fill in the Length field with the information we have at this point.
-                * The minus four is to subtract the size of the u8 Source[4] member
-                * because it is added below.
+                * Fill in the Length field with the information we have at this
+                * point. The minus four is to subtract the size of the u8
+                * Source[4] member because it is added below.
                 */
                user_prt->length = (sizeof(struct acpi_pci_routing_table) - 4);
 
@@ -345,11 +347,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
                                           (u8 *) output_buffer->pointer);
                                path_buffer.pointer = user_prt->source;
 
-                               status =
-                                   acpi_ns_handle_to_pathname((acpi_handle)
-                                                              node,
-                                                              &path_buffer,
-                                                              FALSE);
+                               status = acpi_ns_handle_to_pathname((acpi_handle) node, &path_buffer, FALSE);
 
                                /* +1 to include null terminator */
 
@@ -371,8 +369,8 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
 
                        case ACPI_TYPE_INTEGER:
                                /*
-                                * If this is a number, then the Source Name is NULL, since the
-                                * entire buffer was zeroed out, we can leave this alone.
+                                * If this is a number, then the Source Name is NULL, since
+                                * the entire buffer was zeroed out, we can leave this alone.
                                 *
                                 * Add to the Length field the length of the u32 NULL
                                 */
@@ -451,9 +449,9 @@ acpi_rs_create_aml_resources(struct acpi_buffer *resource_list,
 
        /* Get the buffer size needed for the AML byte stream */
 
-       status = acpi_rs_get_aml_length(resource_list->pointer,
-                                       resource_list->length,
-                                       &aml_size_needed);
+       status =
+           acpi_rs_get_aml_length(resource_list->pointer,
+                                  resource_list->length, &aml_size_needed);
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "AmlSizeNeeded=%X, %s\n",
                          (u32)aml_size_needed, acpi_format_exception(status)));
index 2a09288e7c57c3d1a6df3a0f93dc9a3b49ed24ac..05cc560699e11697029471d616c48ba1da51f08b 100644 (file)
@@ -483,6 +483,7 @@ static void acpi_rs_dump_address_common(union acpi_resource_data *resource)
 
 static void acpi_rs_out_string(char *title, char *value)
 {
+
        acpi_os_printf("%27s : %s", title, value);
        if (!*value) {
                acpi_os_printf("[NULL NAMESTRING]");
@@ -497,21 +498,25 @@ static void acpi_rs_out_integer8(char *title, u8 value)
 
 static void acpi_rs_out_integer16(char *title, u16 value)
 {
+
        acpi_os_printf("%27s : %4.4X\n", title, value);
 }
 
 static void acpi_rs_out_integer32(char *title, u32 value)
 {
+
        acpi_os_printf("%27s : %8.8X\n", title, value);
 }
 
 static void acpi_rs_out_integer64(char *title, u64 value)
 {
+
        acpi_os_printf("%27s : %8.8X%8.8X\n", title, ACPI_FORMAT_UINT64(value));
 }
 
 static void acpi_rs_out_title(char *title)
 {
+
        acpi_os_printf("%27s : ", title);
 }
 
@@ -544,6 +549,7 @@ static void acpi_rs_dump_short_byte_list(u8 length, u8 * data)
        for (i = 0; i < length; i++) {
                acpi_os_printf("%X ", data[i]);
        }
+
        acpi_os_printf("\n");
 }
 
index 50d5be2ee0622f28e12fb6f60176fef99c6ed4da..286ccb461a20cc2e087fa11f8da12dbd2d79b8ea 100644 (file)
@@ -89,6 +89,7 @@ acpi_rs_convert_aml_to_resources(u8 * aml,
        /* Get the appropriate conversion info table */
 
        aml_resource = ACPI_CAST_PTR(union aml_resource, aml);
+
        if (acpi_ut_get_resource_type(aml) == ACPI_RESOURCE_NAME_SERIAL_BUS) {
                if (aml_resource->common_serial_bus.type >
                    AML_RESOURCE_MAX_SERIALBUSTYPE) {
@@ -225,10 +226,10 @@ acpi_rs_convert_resources_to_aml(struct acpi_resource *resource,
 
                /* Perform final sanity check on the new AML resource descriptor */
 
-               status = acpi_ut_validate_resource(NULL,
-                                                  ACPI_CAST_PTR(union
-                                                                aml_resource,
-                                                                aml), NULL);
+               status =
+                   acpi_ut_validate_resource(NULL,
+                                             ACPI_CAST_PTR(union aml_resource,
+                                                           aml), NULL);
                if (ACPI_FAILURE(status)) {
                        return_ACPI_STATUS(status);
                }
index ac37852e082173869fef4cc872e6734451d0419f..b112c7b1abbf73ab86cb27c48285e0b2e475f3a3 100644 (file)
@@ -189,8 +189,8 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource,
                        item_count = ACPI_GET8(source);
                        ACPI_SET8(destination, item_count);
 
-                       resource->length = resource->length +
-                           (info->value * item_count);
+                       resource->length =
+                           resource->length + (info->value * item_count);
                        break;
 
                case ACPI_RSC_COUNT_GPIO_RES:
@@ -445,8 +445,8 @@ exit:
 
                /* Round the resource struct length up to the next boundary (32 or 64) */
 
-               resource->length =
-                   (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(resource->length);
+               resource->length = (u32)
+                   ACPI_ROUND_UP_TO_NATIVE_WORD(resource->length);
        }
        return_ACPI_STATUS(AE_OK);
 }
@@ -550,9 +550,8 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource,
                        item_count = ACPI_GET8(source);
                        ACPI_SET8(destination, item_count);
 
-                       aml_length =
-                           (u16) (aml_length +
-                                  (info->value * (item_count - 1)));
+                       aml_length = (u16)
+                           (aml_length + (info->value * (item_count - 1)));
                        break;
 
                case ACPI_RSC_COUNT16:
@@ -723,11 +722,10 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource,
                        /*
                         * 16-bit encoded bitmask (IRQ macro)
                         */
-                       temp16 = acpi_rs_encode_bitmask(source,
-                                                       *ACPI_ADD_PTR(u8,
-                                                                     resource,
-                                                                     info->
-                                                                     value));
+                       temp16 =
+                           acpi_rs_encode_bitmask(source,
+                                                  *ACPI_ADD_PTR(u8, resource,
+                                                                info->value));
                        ACPI_MOVE_16_TO_16(destination, &temp16);
                        break;
 
index 9486992edbb82b5c29094352b6d0eea536f7046d..33e558c9434f7b50ee4bc7bf835c2cdad443f9b5 100644 (file)
@@ -221,14 +221,13 @@ acpi_rs_set_resource_length(acpi_rsdesc_size total_length,
                ACPI_MOVE_16_TO_16(&aml->large_header.resource_length,
                                   &resource_length);
        } else {
-               /* Small descriptor -- bits 2:0 of byte 0 contain the length */
-
+               /*
+                * Small descriptor -- bits 2:0 of byte 0 contain the length
+                * Clear any existing length, preserving descriptor type bits
+                */
                aml->small_header.descriptor_type = (u8)
-
-                   /* Clear any existing length, preserving descriptor type bits */
-                   ((aml->small_header.
-                     descriptor_type & ~ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK)
-
+                   ((aml->small_header.descriptor_type &
+                     ~ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK)
                     | resource_length);
        }
 }
@@ -333,8 +332,8 @@ acpi_rs_get_resource_source(acpi_rs_length resource_length,
        aml_resource_source = ACPI_ADD_PTR(u8, aml, minimum_length);
 
        /*
-        * resource_source is present if the length of the descriptor is longer than
-        * the minimum length.
+        * resource_source is present if the length of the descriptor is longer
+        * than the minimum length.
         *
         * Note: Some resource descriptors will have an additional null, so
         * we add 1 to the minimum length.
@@ -366,6 +365,7 @@ acpi_rs_get_resource_source(acpi_rs_length resource_length,
                total_length =
                    (u32)strlen(ACPI_CAST_PTR(char, &aml_resource_source[1])) +
                    1;
+
                total_length = (u32)ACPI_ROUND_UP_TO_NATIVE_WORD(total_length);
 
                memset(resource_source->string_ptr, 0, total_length);
@@ -438,8 +438,8 @@ acpi_rs_set_resource_source(union aml_resource * aml,
                 * Add the length of the string (+ 1 for null terminator) to the
                 * final descriptor length
                 */
-               descriptor_length +=
-                   ((acpi_rsdesc_size) resource_source->string_length + 1);
+               descriptor_length += ((acpi_rsdesc_size)
+                                     resource_source->string_length + 1);
        }
 
        /* Return the new total length of the AML descriptor */
@@ -478,8 +478,9 @@ acpi_rs_get_prt_method_data(struct acpi_namespace_node * node,
 
        /* Execute the method, no parameters */
 
-       status = acpi_ut_evaluate_object(node, METHOD_NAME__PRT,
-                                        ACPI_BTYPE_PACKAGE, &obj_desc);
+       status =
+           acpi_ut_evaluate_object(node, METHOD_NAME__PRT, ACPI_BTYPE_PACKAGE,
+                                   &obj_desc);
        if (ACPI_FAILURE(status)) {
                return_ACPI_STATUS(status);
        }
@@ -527,8 +528,9 @@ acpi_rs_get_crs_method_data(struct acpi_namespace_node *node,
 
        /* Execute the method, no parameters */
 
-       status = acpi_ut_evaluate_object(node, METHOD_NAME__CRS,
-                                        ACPI_BTYPE_BUFFER, &obj_desc);
+       status =
+           acpi_ut_evaluate_object(node, METHOD_NAME__CRS, ACPI_BTYPE_BUFFER,
+                                   &obj_desc);
        if (ACPI_FAILURE(status)) {
                return_ACPI_STATUS(status);
        }
@@ -577,8 +579,9 @@ acpi_rs_get_prs_method_data(struct acpi_namespace_node *node,
 
        /* Execute the method, no parameters */
 
-       status = acpi_ut_evaluate_object(node, METHOD_NAME__PRS,
-                                        ACPI_BTYPE_BUFFER, &obj_desc);
+       status =
+           acpi_ut_evaluate_object(node, METHOD_NAME__PRS, ACPI_BTYPE_BUFFER,
+                                   &obj_desc);
        if (ACPI_FAILURE(status)) {
                return_ACPI_STATUS(status);
        }
@@ -627,8 +630,9 @@ acpi_rs_get_aei_method_data(struct acpi_namespace_node *node,
 
        /* Execute the method, no parameters */
 
-       status = acpi_ut_evaluate_object(node, METHOD_NAME__AEI,
-                                        ACPI_BTYPE_BUFFER, &obj_desc);
+       status =
+           acpi_ut_evaluate_object(node, METHOD_NAME__AEI, ACPI_BTYPE_BUFFER,
+                                   &obj_desc);
        if (ACPI_FAILURE(status)) {
                return_ACPI_STATUS(status);
        }
index 1e8cd572332640fe5a6faa9db3a64f3ff0b56b07..308bfd6bff5f49244cfd97ede42ac97f2664b498 100644 (file)
@@ -53,7 +53,7 @@ ACPI_MODULE_NAME("rsxface")
 
 /* Local macros for 16,32-bit to 64-bit conversion */
 #define ACPI_COPY_FIELD(out, in, field)  ((out)->field = (in)->field)
-#define ACPI_COPY_ADDRESS(out, in)                      \
+#define ACPI_COPY_ADDRESS(out, in)                       \
        ACPI_COPY_FIELD(out, in, resource_type);             \
        ACPI_COPY_FIELD(out, in, producer_consumer);         \
        ACPI_COPY_FIELD(out, in, decode);                    \
index 5c9d5abf15887e4e5d42f3e8651eee0876bb1697..4a8152777767abdb8c0cce6fad256cf729839307 100644 (file)
@@ -407,6 +407,7 @@ acpi_tb_verify_temp_table(struct acpi_table_desc * table_desc, char *signature)
                                        table_desc->signature.ascii : "????",
                                        ACPI_FORMAT_UINT64(table_desc->
                                                           address)));
+
                        goto invalidate_and_exit;
                }
        }
index 6319b42420c61aed6548be77cb7001cceb65c352..bd87801acedfe06b5c31695127e385878f50298e 100644 (file)
@@ -337,8 +337,8 @@ acpi_tb_install_standard_table(acpi_physical_address address,
                         * need to be unregistered when they are unloaded, and slots in the
                         * root table list should be reused when empty.
                         */
-                       if (acpi_gbl_root_table_list.tables[i].
-                           flags & ACPI_TABLE_IS_LOADED) {
+                       if (acpi_gbl_root_table_list.tables[i].flags &
+                           ACPI_TABLE_IS_LOADED) {
 
                                /* Table is still loaded, this is an error */
 
index 709d5112fc1679db4a6ff28412a27bbe5c334d81..d0d12596cfc9aa4a4950b138adf146348c623733 100644 (file)
@@ -76,6 +76,7 @@ static void acpi_tb_fix_string(char *string, acpi_size length)
                if (!isprint((int)*string)) {
                        *string = '?';
                }
+
                string++;
                length--;
        }
index d8ddef38c947f750a226cee1b69fa373c9e1bf8f..7c1b5f8a5cbf2f9fc8727f64eb6b305474320924 100644 (file)
@@ -121,6 +121,7 @@ void acpi_tb_check_dsdt_header(void)
                ACPI_BIOS_ERROR((AE_INFO,
                                 "The DSDT has been corrupted or replaced - "
                                 "old, new headers below"));
+
                acpi_tb_print_table_header(0, &acpi_gbl_original_dsdt_header);
                acpi_tb_print_table_header(0, acpi_gbl_DSDT);
 
@@ -379,7 +380,6 @@ next_table:
        }
 
        acpi_os_unmap_memory(table, length);
-
        return_ACPI_STATUS(AE_OK);
 }
 
@@ -389,7 +389,7 @@ next_table:
  *
  * PARAMETERS:  signature           - Sig string to be validated
  *
- * RETURN:      TRUE if signature is correct length and has valid characters
+ * RETURN:      TRUE if signature is has 4 valid ACPI characters
  *
  * DESCRIPTION: Validate an ACPI table signature.
  *
@@ -399,12 +399,6 @@ u8 acpi_is_valid_signature(char *signature)
 {
        u32 i;
 
-       /* Validate the signature length */
-
-       if (strlen(signature) != ACPI_NAME_SIZE) {
-               return (FALSE);
-       }
-
        /* Validate each character in the signature */
 
        for (i = 0; i < ACPI_NAME_SIZE; i++) {
index 55ee14ca94181ea3ce0d901eaef54e6f5aa8aa2b..ca2f1366b498dc71af83fafde84acbb1da580234 100644 (file)
@@ -191,6 +191,7 @@ acpi_status acpi_tb_load_namespace(void)
                                        "(%4.4s:%8.8s) while loading table",
                                        table->signature.ascii,
                                        table->pointer->oem_table_id));
+
                        tables_failed++;
 
                        ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
@@ -206,7 +207,7 @@ acpi_status acpi_tb_load_namespace(void)
 
        if (!tables_failed) {
                ACPI_INFO((AE_INFO,
-                          "%u ACPI AML tables successfully acquired and loaded",
+                          "%u ACPI AML tables successfully acquired and loaded\n",
                           tables_loaded));
        } else {
                ACPI_ERROR((AE_INFO,
index 911ea8e7fe8700f451cef7b2597b82c30870ca8f..38a29e235b74435e4c4764205e1abd2f2fbecf37 100644 (file)
@@ -239,8 +239,9 @@ acpi_ut_check_address_range(acpi_adr_space_type space_id,
                        overlap_count++;
                        if (warn) {     /* Optional warning message */
                                pathname =
-                                   acpi_ns_get_external_pathname(range_info->
-                                                                 region_node);
+                                   acpi_ns_get_normalized_pathname(range_info->
+                                                                   region_node,
+                                                                   TRUE);
 
                                ACPI_WARNING((AE_INFO,
                                              "%s range 0x%8.8X%8.8X-0x%8.8X%8.8X conflicts with OpRegion 0x%8.8X%8.8X-0x%8.8X%8.8X (%s)",
index 257221d452c8839262faf80465969b0ec75d8a54..ade8acf3f3a5808b88298cd346e5392f320b0109 100644 (file)
@@ -257,9 +257,9 @@ acpi_ut_copy_ielement_to_eelement(u8 object_type,
        ACPI_FUNCTION_ENTRY();
 
        this_index = state->pkg.index;
-       target_object = (union acpi_object *)
-           &((union acpi_object *)(state->pkg.dest_object))->package.
-           elements[this_index];
+       target_object = (union acpi_object *)&((union acpi_object *)
+                                              (state->pkg.dest_object))->
+           package.elements[this_index];
 
        switch (object_type) {
        case ACPI_COPY_TYPE_SIMPLE:
@@ -348,15 +348,15 @@ acpi_ut_copy_ipackage_to_epackage(union acpi_operand_object *internal_object,
         * Free space begins right after the first package
         */
        info.length = ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
-       info.free_space =
-           buffer + ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
+       info.free_space = buffer +
+           ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
        info.object_space = 0;
        info.num_packages = 1;
 
        external_object->type = internal_object->common.type;
        external_object->package.count = internal_object->package.count;
-       external_object->package.elements = ACPI_CAST_PTR(union acpi_object,
-                                                         info.free_space);
+       external_object->package.elements =
+           ACPI_CAST_PTR(union acpi_object, info.free_space);
 
        /*
         * Leave room for an array of ACPI_OBJECTS in the buffer
@@ -593,8 +593,8 @@ acpi_ut_copy_epackage_to_ipackage(union acpi_object *external_object,
        package_elements = package_object->package.elements;
 
        /*
-        * Recursive implementation. Probably ok, since nested external packages
-        * as parameters should be very rare.
+        * Recursive implementation. Probably ok, since nested external
+        * packages as parameters should be very rare.
         */
        for (i = 0; i < external_object->package.count; i++) {
                status =
@@ -649,9 +649,8 @@ acpi_ut_copy_eobject_to_iobject(union acpi_object *external_object,
                /*
                 * Build a simple object (no nested objects)
                 */
-               status =
-                   acpi_ut_copy_esimple_to_isimple(external_object,
-                                                   internal_object);
+               status = acpi_ut_copy_esimple_to_isimple(external_object,
+                                                        internal_object);
        }
 
        return_ACPI_STATUS(status);
index ecaaaffc078813a2429ce86470e3fbe7e0c5544c..3533135dbd4d1ee51b12b009d6b11c4f4ca1f52f 100644 (file)
@@ -114,7 +114,7 @@ const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] = {
        "PCC"                   /* 0x0A */
 };
 
-char *acpi_ut_get_region_name(u8 space_id)
+const char *acpi_ut_get_region_name(u8 space_id)
 {
 
        if (space_id >= ACPI_USER_REGION_BEGIN) {
@@ -127,7 +127,7 @@ char *acpi_ut_get_region_name(u8 space_id)
                return ("InvalidSpaceId");
        }
 
-       return (ACPI_CAST_PTR(char, acpi_gbl_region_types[space_id]));
+       return (acpi_gbl_region_types[space_id]);
 }
 
 /*******************************************************************************
@@ -152,14 +152,14 @@ static const char *acpi_gbl_event_types[ACPI_NUM_FIXED_EVENTS] = {
        "RealTimeClock",
 };
 
-char *acpi_ut_get_event_name(u32 event_id)
+const char *acpi_ut_get_event_name(u32 event_id)
 {
 
        if (event_id > ACPI_EVENT_MAX) {
                return ("InvalidEventID");
        }
 
-       return (ACPI_CAST_PTR(char, acpi_gbl_event_types[event_id]));
+       return (acpi_gbl_event_types[event_id]);
 }
 
 /*******************************************************************************
@@ -180,7 +180,8 @@ char *acpi_ut_get_event_name(u32 event_id)
  *
  * The type ACPI_TYPE_ANY (Untyped) is used as a "don't care" when searching;
  * when stored in a table it really means that we have thus far seen no
- * evidence to indicate what type is actually going to be stored for this entry.
+ * evidence to indicate what type is actually going to be stored for this
+ & entry.
  */
 static const char acpi_gbl_bad_type[] = "UNDEFINED";
 
@@ -220,17 +221,17 @@ static const char *acpi_gbl_ns_type_names[] = {
        /* 30 */ "Invalid"
 };
 
-char *acpi_ut_get_type_name(acpi_object_type type)
+const char *acpi_ut_get_type_name(acpi_object_type type)
 {
 
        if (type > ACPI_TYPE_INVALID) {
-               return (ACPI_CAST_PTR(char, acpi_gbl_bad_type));
+               return (acpi_gbl_bad_type);
        }
 
-       return (ACPI_CAST_PTR(char, acpi_gbl_ns_type_names[type]));
+       return (acpi_gbl_ns_type_names[type]);
 }
 
-char *acpi_ut_get_object_type_name(union acpi_operand_object *obj_desc)
+const char *acpi_ut_get_object_type_name(union acpi_operand_object *obj_desc)
 {
        ACPI_FUNCTION_TRACE(ut_get_object_type_name);
 
@@ -267,7 +268,7 @@ char *acpi_ut_get_object_type_name(union acpi_operand_object *obj_desc)
  *
  ******************************************************************************/
 
-char *acpi_ut_get_node_name(void *object)
+const char *acpi_ut_get_node_name(void *object)
 {
        struct acpi_namespace_node *node = (struct acpi_namespace_node *)object;
 
@@ -333,7 +334,7 @@ static const char *acpi_gbl_desc_type_names[] = {
        /* 15 */ "Node"
 };
 
-char *acpi_ut_get_descriptor_name(void *object)
+const char *acpi_ut_get_descriptor_name(void *object)
 {
 
        if (!object) {
@@ -344,10 +345,7 @@ char *acpi_ut_get_descriptor_name(void *object)
                return ("Not a Descriptor");
        }
 
-       return (ACPI_CAST_PTR(char,
-                             acpi_gbl_desc_type_names[ACPI_GET_DESCRIPTOR_TYPE
-                                                      (object)]));
-
+       return (acpi_gbl_desc_type_names[ACPI_GET_DESCRIPTOR_TYPE(object)]);
 }
 
 /*******************************************************************************
@@ -415,7 +413,7 @@ const char *acpi_ut_get_reference_name(union acpi_operand_object *object)
 
 /* Names for internal mutex objects, used for debug output */
 
-static char *acpi_gbl_mutex_names[ACPI_NUM_MUTEX] = {
+static const char *acpi_gbl_mutex_names[ACPI_NUM_MUTEX] = {
        "ACPI_MTX_Interpreter",
        "ACPI_MTX_Namespace",
        "ACPI_MTX_Tables",
@@ -424,7 +422,7 @@ static char *acpi_gbl_mutex_names[ACPI_NUM_MUTEX] = {
        "ACPI_MTX_Memory",
 };
 
-char *acpi_ut_get_mutex_name(u32 mutex_id)
+const char *acpi_ut_get_mutex_name(u32 mutex_id)
 {
 
        if (mutex_id > ACPI_MAX_MUTEX) {
index 1638312e3d8f97c6235360f630473fb5277d39b6..1afd7427a90ccd1b7eabdff548284fa7425ecfaf 100644 (file)
@@ -209,6 +209,7 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object)
                        acpi_ut_delete_object_desc(object->method.mutex);
                        object->method.mutex = NULL;
                }
+
                if (object->method.node) {
                        object->method.node = NULL;
                }
@@ -515,8 +516,8 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action)
                }
 
                /*
-                * All sub-objects must have their reference count incremented also.
-                * Different object types have different subobjects.
+                * All sub-objects must have their reference count incremented
+                * also. Different object types have different subobjects.
                 */
                switch (object->common.type) {
                case ACPI_TYPE_DEVICE:
index 9ef80f2828e321a951666061239a8960fea531b3..f93bb90ea72ae3b5e58cb79988767b38833e935b 100644 (file)
@@ -217,8 +217,9 @@ acpi_ut_namespace_error(const char *module_name,
        } else {
                /* Convert path to external format */
 
-               status = acpi_ns_externalize_name(ACPI_UINT32_MAX,
-                                                 internal_name, NULL, &name);
+               status =
+                   acpi_ns_externalize_name(ACPI_UINT32_MAX, internal_name,
+                                            NULL, &name);
 
                /* Print target name */
 
@@ -271,9 +272,8 @@ acpi_ut_method_error(const char *module_name,
        acpi_os_printf(ACPI_MSG_ERROR);
 
        if (path) {
-               status =
-                   acpi_ns_get_node(prefix_node, path, ACPI_NS_NO_UPSEARCH,
-                                    &node);
+               status = acpi_ns_get_node(prefix_node, path,
+                                         ACPI_NS_NO_UPSEARCH, &node);
                if (ACPI_FAILURE(status)) {
                        acpi_os_printf("[Could not get node by pathname]");
                }
diff --git a/drivers/acpi/acpica/utfileio.c b/drivers/acpi/acpica/utfileio.c
deleted file mode 100644 (file)
index d435b7b..0000000
+++ /dev/null
@@ -1,334 +0,0 @@
-/*******************************************************************************
- *
- * Module Name: utfileio - simple file I/O routines
- *
- ******************************************************************************/
-
-/*
- * Copyright (C) 2000 - 2015, Intel Corp.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions, and the following disclaimer,
- *    without modification.
- * 2. Redistributions in binary form must reproduce at minimum a disclaimer
- *    substantially similar to the "NO WARRANTY" disclaimer below
- *    ("Disclaimer") and any redistribution must be conditioned upon
- *    including a substantially similar Disclaimer requirement for further
- *    binary redistribution.
- * 3. Neither the names of the above-listed copyright holders nor the names
- *    of any contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
- *
- * Alternatively, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2 as published by the Free
- * Software Foundation.
- *
- * NO WARRANTY
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGES.
- */
-
-#include <acpi/acpi.h>
-#include "accommon.h"
-#include "actables.h"
-#include "acapps.h"
-#include "errno.h"
-
-#ifdef ACPI_ASL_COMPILER
-#include "aslcompiler.h"
-#endif
-
-#define _COMPONENT          ACPI_CA_DEBUGGER
-ACPI_MODULE_NAME("utfileio")
-
-#ifdef ACPI_APPLICATION
-/* Local prototypes */
-static acpi_status
-acpi_ut_check_text_mode_corruption(u8 *table,
-                                  u32 table_length, u32 file_length);
-
-static acpi_status
-acpi_ut_read_table(FILE * fp,
-                  struct acpi_table_header **table, u32 *table_length);
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_check_text_mode_corruption
- *
- * PARAMETERS:  table           - Table buffer
- *              table_length    - Length of table from the table header
- *              file_length     - Length of the file that contains the table
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Check table for text mode file corruption where all linefeed
- *              characters (LF) have been replaced by carriage return linefeed
- *              pairs (CR/LF).
- *
- ******************************************************************************/
-
-static acpi_status
-acpi_ut_check_text_mode_corruption(u8 *table, u32 table_length, u32 file_length)
-{
-       u32 i;
-       u32 pairs = 0;
-
-       if (table_length != file_length) {
-               ACPI_WARNING((AE_INFO,
-                             "File length (0x%X) is not the same as the table length (0x%X)",
-                             file_length, table_length));
-       }
-
-       /* Scan entire table to determine if each LF has been prefixed with a CR */
-
-       for (i = 1; i < file_length; i++) {
-               if (table[i] == 0x0A) {
-                       if (table[i - 1] != 0x0D) {
-
-                               /* The LF does not have a preceding CR, table not corrupted */
-
-                               return (AE_OK);
-                       } else {
-                               /* Found a CR/LF pair */
-
-                               pairs++;
-                       }
-                       i++;
-               }
-       }
-
-       if (!pairs) {
-               return (AE_OK);
-       }
-
-       /*
-        * Entire table scanned, each CR is part of a CR/LF pair --
-        * meaning that the table was treated as a text file somewhere.
-        *
-        * NOTE: We can't "fix" the table, because any existing CR/LF pairs in the
-        * original table are left untouched by the text conversion process --
-        * meaning that we cannot simply replace CR/LF pairs with LFs.
-        */
-       acpi_os_printf("Table has been corrupted by text mode conversion\n");
-       acpi_os_printf("All LFs (%u) were changed to CR/LF pairs\n", pairs);
-       acpi_os_printf("Table cannot be repaired!\n");
-       return (AE_BAD_VALUE);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_read_table
- *
- * PARAMETERS:  fp              - File that contains table
- *              table           - Return value, buffer with table
- *              table_length    - Return value, length of table
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Load the DSDT from the file pointer
- *
- ******************************************************************************/
-
-static acpi_status
-acpi_ut_read_table(FILE * fp,
-                  struct acpi_table_header **table, u32 *table_length)
-{
-       struct acpi_table_header table_header;
-       u32 actual;
-       acpi_status status;
-       u32 file_size;
-       u8 standard_header = TRUE;
-       s32 count;
-
-       /* Get the file size */
-
-       file_size = cm_get_file_size(fp);
-       if (file_size == ACPI_UINT32_MAX) {
-               return (AE_ERROR);
-       }
-
-       if (file_size < 4) {
-               return (AE_BAD_HEADER);
-       }
-
-       /* Read the signature */
-
-       fseek(fp, 0, SEEK_SET);
-
-       count = fread(&table_header, 1, sizeof(struct acpi_table_header), fp);
-       if (count != sizeof(struct acpi_table_header)) {
-               acpi_os_printf("Could not read the table header\n");
-               return (AE_BAD_HEADER);
-       }
-
-       /* The RSDP table does not have standard ACPI header */
-
-       if (ACPI_VALIDATE_RSDP_SIG(table_header.signature)) {
-               *table_length = file_size;
-               standard_header = FALSE;
-       } else {
-
-#if 0
-               /* Validate the table header/length */
-
-               status = acpi_tb_validate_table_header(&table_header);
-               if (ACPI_FAILURE(status)) {
-                       acpi_os_printf("Table header is invalid!\n");
-                       return (status);
-               }
-#endif
-
-               /* File size must be at least as long as the Header-specified length */
-
-               if (table_header.length > file_size) {
-                       acpi_os_printf
-                           ("TableHeader length [0x%X] greater than the input file size [0x%X]\n",
-                            table_header.length, file_size);
-
-#ifdef ACPI_ASL_COMPILER
-                       acpi_os_printf("File is corrupt or is ASCII text -- "
-                                      "it must be a binary file\n");
-#endif
-                       return (AE_BAD_HEADER);
-               }
-#ifdef ACPI_OBSOLETE_CODE
-               /* We only support a limited number of table types */
-
-               if (!ACPI_COMPARE_NAME
-                   ((char *)table_header.signature, ACPI_SIG_DSDT)
-                   && !ACPI_COMPARE_NAME((char *)table_header.signature,
-                                         ACPI_SIG_PSDT)
-                   && !ACPI_COMPARE_NAME((char *)table_header.signature,
-                                         ACPI_SIG_SSDT)) {
-                       acpi_os_printf
-                           ("Table signature [%4.4s] is invalid or not supported\n",
-                            (char *)table_header.signature);
-                       ACPI_DUMP_BUFFER(&table_header,
-                                        sizeof(struct acpi_table_header));
-                       return (AE_ERROR);
-               }
-#endif
-
-               *table_length = table_header.length;
-       }
-
-       /* Allocate a buffer for the table */
-
-       *table = acpi_os_allocate((size_t) file_size);
-       if (!*table) {
-               acpi_os_printf
-                   ("Could not allocate memory for ACPI table %4.4s (size=0x%X)\n",
-                    table_header.signature, *table_length);
-               return (AE_NO_MEMORY);
-       }
-
-       /* Get the rest of the table */
-
-       fseek(fp, 0, SEEK_SET);
-       actual = fread(*table, 1, (size_t) file_size, fp);
-       if (actual == file_size) {
-               if (standard_header) {
-
-                       /* Now validate the checksum */
-
-                       status = acpi_tb_verify_checksum((void *)*table,
-                                                        ACPI_CAST_PTR(struct
-                                                                      acpi_table_header,
-                                                                      *table)->
-                                                        length);
-
-                       if (status == AE_BAD_CHECKSUM) {
-                               status =
-                                   acpi_ut_check_text_mode_corruption((u8 *)
-                                                                      *table,
-                                                                      file_size,
-                                                                      (*table)->
-                                                                      length);
-                               return (status);
-                       }
-               }
-               return (AE_OK);
-       }
-
-       if (actual > 0) {
-               acpi_os_printf("Warning - reading table, asked for %X got %X\n",
-                              file_size, actual);
-               return (AE_OK);
-       }
-
-       acpi_os_printf("Error - could not read the table file\n");
-       acpi_os_free(*table);
-       *table = NULL;
-       *table_length = 0;
-       return (AE_ERROR);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_read_table_from_file
- *
- * PARAMETERS:  filename         - File where table is located
- *              table            - Where a pointer to the table is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Get an ACPI table from a file
- *
- ******************************************************************************/
-
-acpi_status
-acpi_ut_read_table_from_file(char *filename, struct acpi_table_header ** table)
-{
-       FILE *file;
-       u32 file_size;
-       u32 table_length;
-       acpi_status status = AE_ERROR;
-
-       /* Open the file, get current size */
-
-       file = fopen(filename, "rb");
-       if (!file) {
-               perror("Could not open input file");
-
-               if (errno == ENOENT) {
-                       return (AE_NOT_EXIST);
-               }
-
-               return (status);
-       }
-
-       file_size = cm_get_file_size(file);
-       if (file_size == ACPI_UINT32_MAX) {
-               goto exit;
-       }
-
-       /* Get the entire file */
-
-       fprintf(stderr,
-               "Reading ACPI table from file %12s - Length %.8u (0x%06X)\n",
-               filename, file_size, file_size);
-
-       status = acpi_ut_read_table(file, table, &table_length);
-       if (ACPI_FAILURE(status)) {
-               acpi_os_printf("Could not get table from the file\n");
-       }
-
-exit:
-       fclose(file);
-       return (status);
-}
-
-#endif
index fda8b3def81c64d9d18ca81373dd2836bafa1658..8ad086ed1a064e0f90df85c0af9a0557e5af3281 100644 (file)
@@ -48,7 +48,7 @@
 ACPI_MODULE_NAME("uthex")
 
 /* Hex to ASCII conversion table */
-static char acpi_gbl_hex_to_ascii[] = {
+static const char acpi_gbl_hex_to_ascii[] = {
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
            'E', 'F'
 };
index 7956df1e263c1cb1271614cdba965d1592d9a18a..05ee76eec314f88a14b4abc2db14e5c5105ecb2f 100644 (file)
@@ -125,73 +125,6 @@ cleanup:
        return_ACPI_STATUS(status);
 }
 
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_execute_SUB
- *
- * PARAMETERS:  device_node         - Node for the device
- *              return_id           - Where the _SUB is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Executes the _SUB control method that returns the subsystem
- *              ID of the device. The _SUB value is always a string containing
- *              either a valid PNP or ACPI ID.
- *
- *              NOTE: Internal function, no parameter validation
- *
- ******************************************************************************/
-
-acpi_status
-acpi_ut_execute_SUB(struct acpi_namespace_node *device_node,
-                   struct acpi_pnp_device_id **return_id)
-{
-       union acpi_operand_object *obj_desc;
-       struct acpi_pnp_device_id *sub;
-       u32 length;
-       acpi_status status;
-
-       ACPI_FUNCTION_TRACE(ut_execute_SUB);
-
-       status = acpi_ut_evaluate_object(device_node, METHOD_NAME__SUB,
-                                        ACPI_BTYPE_STRING, &obj_desc);
-       if (ACPI_FAILURE(status)) {
-               return_ACPI_STATUS(status);
-       }
-
-       /* Get the size of the String to be returned, includes null terminator */
-
-       length = obj_desc->string.length + 1;
-
-       /* Allocate a buffer for the SUB */
-
-       sub =
-           ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) +
-                                (acpi_size) length);
-       if (!sub) {
-               status = AE_NO_MEMORY;
-               goto cleanup;
-       }
-
-       /* Area for the string starts after PNP_DEVICE_ID struct */
-
-       sub->string =
-           ACPI_ADD_PTR(char, sub, sizeof(struct acpi_pnp_device_id));
-
-       /* Simply copy existing string */
-
-       strcpy(sub->string, obj_desc->string.pointer);
-       sub->length = length;
-       *return_id = sub;
-
-cleanup:
-
-       /* On exit, we must delete the return object */
-
-       acpi_ut_remove_reference(obj_desc);
-       return_ACPI_STATUS(status);
-}
-
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ut_execute_UID
index ccd0745f011e886619dd2b891e51d23df372e08a..fd82a122785e5207fe244966514ec715206544d6 100644 (file)
@@ -206,7 +206,6 @@ acpi_status acpi_ut_init_globals(void)
        acpi_gbl_next_owner_id_offset = 0;
        acpi_gbl_debugger_configuration = DEBUGGER_THREADING;
        acpi_gbl_osi_mutex = NULL;
-       acpi_gbl_reg_methods_executed = FALSE;
        acpi_gbl_max_loop_iterations = 0xFFFF;
 
        /* Hardware oriented */
index f9ff100f0159b89a9e208fdde6759711f6107151..58b5d423642985ea5209051e8e29eec9c8854a96 100644 (file)
@@ -111,6 +111,7 @@ acpi_ut_short_divide(u64 dividend,
         */
        ACPI_DIV_64_BY_32(0, dividend_ovl.part.hi, divisor,
                          quotient.part.hi, remainder32);
+
        ACPI_DIV_64_BY_32(remainder32, dividend_ovl.part.lo, divisor,
                          quotient.part.lo, remainder32);
 
@@ -179,6 +180,7 @@ acpi_ut_divide(u64 in_dividend,
                 */
                ACPI_DIV_64_BY_32(0, dividend.part.hi, divisor.part.lo,
                                  quotient.part.hi, partial1);
+
                ACPI_DIV_64_BY_32(partial1, dividend.part.lo, divisor.part.lo,
                                  quotient.part.lo, remainder.part.lo);
        }
@@ -206,12 +208,12 @@ acpi_ut_divide(u64 in_dividend,
 
                ACPI_DIV_64_BY_32(normalized_dividend.part.hi,
                                  normalized_dividend.part.lo,
-                                 normalized_divisor.part.lo,
-                                 quotient.part.lo, partial1);
+                                 normalized_divisor.part.lo, quotient.part.lo,
+                                 partial1);
 
                /*
-                * The quotient is always 32 bits, and simply requires adjustment.
-                * The 64-bit remainder must be generated.
+                * The quotient is always 32 bits, and simply requires
+                * adjustment. The 64-bit remainder must be generated.
                 */
                partial1 = quotient.part.lo * divisor.part.hi;
                partial2.full = (u64) quotient.part.lo * divisor.part.lo;
index bd4443bdcbad8cd1e285487e81c522d53f76b1fb..eab1cfeb52cc92ebe815d34d4f8495f97e87cc73 100644 (file)
@@ -264,8 +264,8 @@ acpi_ut_walk_package_tree(union acpi_operand_object *source_object,
                 */
                if ((!this_source_obj) ||
                    (ACPI_GET_DESCRIPTOR_TYPE(this_source_obj) !=
-                    ACPI_DESC_TYPE_OPERAND)
-                   || (this_source_obj->common.type != ACPI_TYPE_PACKAGE)) {
+                    ACPI_DESC_TYPE_OPERAND) ||
+                   (this_source_obj->common.type != ACPI_TYPE_PACKAGE)) {
                        status =
                            walk_callback(ACPI_COPY_TYPE_SIMPLE,
                                          this_source_obj, state, context);
@@ -318,9 +318,10 @@ acpi_ut_walk_package_tree(union acpi_operand_object *source_object,
                         * The callback above returned a new target package object.
                         */
                        acpi_ut_push_generic_state(&state_list, state);
-                       state = acpi_ut_create_pkg_state(this_source_obj,
-                                                        state->pkg.
-                                                        this_target_obj, 0);
+                       state =
+                           acpi_ut_create_pkg_state(this_source_obj,
+                                                    state->pkg.this_target_obj,
+                                                    0);
                        if (!state) {
 
                                /* Free any stacked Update State objects */
index ce406e39b669cd336b95b7b39c73dfa1c317b361..038ff849ad2045ef03414159b4875b33f91fd3a2 100644 (file)
@@ -111,17 +111,6 @@ acpi_status acpi_ut_mutex_initialize(void)
        if (ACPI_FAILURE(status)) {
                return_ACPI_STATUS(status);
        }
-#ifdef ACPI_DEBUGGER
-
-       /* Debugger Support */
-
-       status = acpi_os_create_mutex(&acpi_gbl_db_command_ready);
-       if (ACPI_FAILURE(status)) {
-               return_ACPI_STATUS(status);
-       }
-
-       status = acpi_os_create_mutex(&acpi_gbl_db_command_complete);
-#endif
 
        return_ACPI_STATUS(status);
 }
@@ -162,12 +151,6 @@ void acpi_ut_mutex_terminate(void)
        /* Delete the reader/writer lock */
 
        acpi_ut_delete_rw_lock(&acpi_gbl_namespace_rw_lock);
-
-#ifdef ACPI_DEBUGGER
-       acpi_os_delete_mutex(acpi_gbl_db_command_ready);
-       acpi_os_delete_mutex(acpi_gbl_db_command_complete);
-#endif
-
        return_VOID;
 }
 
@@ -290,8 +273,9 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id)
                          (u32)this_thread_id,
                          acpi_ut_get_mutex_name(mutex_id)));
 
-       status = acpi_os_acquire_mutex(acpi_gbl_mutex_info[mutex_id].mutex,
-                                      ACPI_WAIT_FOREVER);
+       status =
+           acpi_os_acquire_mutex(acpi_gbl_mutex_info[mutex_id].mutex,
+                                 ACPI_WAIT_FOREVER);
        if (ACPI_SUCCESS(status)) {
                ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
                                  "Thread %u acquired Mutex [%s]\n",
index 1d5f6b17b766421bfcb5b4c30e46cbfc0fef1a0d..9c3cadc27fb82f50fb98e9089750a22caa017871 100644 (file)
@@ -282,8 +282,8 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer)
 
                /* Divide the digit into the correct position */
 
-               (void)acpi_ut_short_divide((dividend - (u64)this_digit),
-                                          base, &quotient, NULL);
+               (void)acpi_ut_short_divide((dividend - (u64)this_digit), base,
+                                          &quotient, NULL);
 
                if (return_value > quotient) {
                        if (to_integer_op) {
index 7d83efe1ea296415bf7f57318a239a64d6e856a4..787eccf6a1d5f2282a5117ccb2ca91efc8cc0924 100644 (file)
@@ -112,9 +112,9 @@ union acpi_operand_object *acpi_ut_create_internal_object_dbg(const char
 
                /* These types require a secondary object */
 
-               second_object = acpi_ut_allocate_object_desc_dbg(module_name,
-                                                                line_number,
-                                                                component_id);
+               second_object =
+                   acpi_ut_allocate_object_desc_dbg(module_name, line_number,
+                                                    component_id);
                if (!second_object) {
                        acpi_ut_delete_object_desc(object);
                        return_PTR(NULL);
@@ -253,7 +253,8 @@ union acpi_operand_object *acpi_ut_create_buffer_object(acpi_size buffer_size)
                buffer = ACPI_ALLOCATE_ZEROED(buffer_size);
                if (!buffer) {
                        ACPI_ERROR((AE_INFO, "Could not allocate size %u",
-                                   (u32) buffer_size));
+                                   (u32)buffer_size));
+
                        acpi_ut_remove_reference(buffer_desc);
                        return_PTR(NULL);
                }
@@ -305,7 +306,8 @@ union acpi_operand_object *acpi_ut_create_string_object(acpi_size string_size)
        string = ACPI_ALLOCATE_ZEROED(string_size + 1);
        if (!string) {
                ACPI_ERROR((AE_INFO, "Could not allocate size %u",
-                           (u32) string_size));
+                           (u32)string_size));
+
                acpi_ut_remove_reference(string_desc);
                return_PTR(NULL);
        }
@@ -649,8 +651,9 @@ acpi_ut_get_package_object_size(union acpi_operand_object *internal_object,
        info.object_space = 0;
        info.num_packages = 1;
 
-       status = acpi_ut_walk_package_tree(internal_object, NULL,
-                                          acpi_ut_get_element_length, &info);
+       status =
+           acpi_ut_walk_package_tree(internal_object, NULL,
+                                     acpi_ut_get_element_length, &info);
        if (ACPI_FAILURE(status)) {
                return_ACPI_STATUS(status);
        }
@@ -660,7 +663,8 @@ acpi_ut_get_package_object_size(union acpi_operand_object *internal_object,
         * just add the length of the package objects themselves.
         * Round up to the next machine word.
         */
-       info.length += ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object)) *
+       info.length +=
+           ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object)) *
            (acpi_size) info.num_packages;
 
        /* Return the total package length */
@@ -692,8 +696,8 @@ acpi_ut_get_object_size(union acpi_operand_object *internal_object,
        ACPI_FUNCTION_ENTRY();
 
        if ((ACPI_GET_DESCRIPTOR_TYPE(internal_object) ==
-            ACPI_DESC_TYPE_OPERAND)
-           && (internal_object->common.type == ACPI_TYPE_PACKAGE)) {
+            ACPI_DESC_TYPE_OPERAND) &&
+           (internal_object->common.type == ACPI_TYPE_PACKAGE)) {
                status =
                    acpi_ut_get_package_object_size(internal_object,
                                                    obj_length);
index 8f3d203aed79844ee78859ae954492f09e9fce95..0809d73193e1906dbc75583b8ba5be44615f461e 100644 (file)
@@ -269,9 +269,10 @@ acpi_status acpi_ut_remove_interface(acpi_string interface_name)
        previous_interface = next_interface = acpi_gbl_supported_interfaces;
        while (next_interface) {
                if (!strcmp(interface_name, next_interface->name)) {
-
-                       /* Found: name is in either the static list or was added at runtime */
-
+                       /*
+                        * Found: name is in either the static list
+                        * or was added at runtime
+                        */
                        if (next_interface->flags & ACPI_OSI_DYNAMIC) {
 
                                /* Interface was added dynamically, remove and free it */
@@ -288,8 +289,8 @@ acpi_status acpi_ut_remove_interface(acpi_string interface_name)
                                ACPI_FREE(next_interface);
                        } else {
                                /*
-                                * Interface is in static list. If marked invalid, then it
-                                * does not actually exist. Else, mark it invalid.
+                                * Interface is in static list. If marked invalid, then
+                                * it does not actually exist. Else, mark it invalid.
                                 */
                                if (next_interface->flags & ACPI_OSI_INVALID) {
                                        return (AE_NOT_EXIST);
index 2959217067cb012beaa8f6de84df8299c094d3fe..ebb811c43c899b242483e52d5773137c5a2fe6af 100644 (file)
@@ -73,8 +73,8 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id)
        /* Guard against multiple allocations of ID to the same location */
 
        if (*owner_id) {
-               ACPI_ERROR((AE_INFO, "Owner ID [0x%2.2X] already exists",
-                           *owner_id));
+               ACPI_ERROR((AE_INFO,
+                           "Owner ID [0x%2.2X] already exists", *owner_id));
                return_ACPI_STATUS(AE_ALREADY_EXISTS);
        }
 
@@ -87,8 +87,8 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id)
 
        /*
         * Find a free owner ID, cycle through all possible IDs on repeated
-        * allocations. (ACPI_NUM_OWNERID_MASKS + 1) because first index may have
-        * to be scanned twice.
+        * allocations. (ACPI_NUM_OWNERID_MASKS + 1) because first index
+        * may have to be scanned twice.
         */
        for (i = 0, j = acpi_gbl_last_owner_id_index;
             i < (ACPI_NUM_OWNERID_MASKS + 1); i++, j++) {
@@ -141,8 +141,8 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id)
         * they are released when a table is unloaded or a method completes
         * execution.
         *
-        * If this error happens, there may be very deep nesting of invoked control
-        * methods, or there may be a bug where the IDs are not released.
+        * If this error happens, there may be very deep nesting of invoked
+        * control methods, or there may be a bug where the IDs are not released.
         */
        status = AE_OWNER_ID_LIMIT;
        ACPI_ERROR((AE_INFO,
index 97898ed71b4b3a9a9a9e8d510b83fdbe52546a71..9f8e415bf0af3a749bcf7213d013695b10ac6c45 100644 (file)
@@ -225,8 +225,10 @@ const union acpi_predefined_info *acpi_ut_match_resource_name(char *name)
 {
        const union acpi_predefined_info *this_name;
 
-       /* Quick check for a predefined name, first character must be underscore */
-
+       /*
+        * Quick check for a predefined name, first character must
+        * be underscore
+        */
        if (name[0] != '_') {
                return (NULL);
        }
index b26297c5de49d528f19e8d0aacba119f94c69a71..01f04da779c5db0cf7c81a865728066765e55e11 100644 (file)
@@ -314,8 +314,9 @@ static char *acpi_ut_format_number(char *string,
        if (need_prefix) {
                string = acpi_ut_bound_string_output(string, end, '0');
                if (base == 16) {
-                       string = acpi_ut_bound_string_output(string, end,
-                                                            upper ? 'X' : 'x');
+                       string =
+                           acpi_ut_bound_string_output(string, end,
+                                                       upper ? 'X' : 'x');
                }
        }
        if (!(type & ACPI_FORMAT_LEFT)) {
@@ -400,6 +401,7 @@ acpi_ut_vsnprintf(char *string,
                        } else {
                                break;
                        }
+
                } while (1);
 
                /* Process width */
@@ -429,6 +431,7 @@ acpi_ut_vsnprintf(char *string,
                                ++format;
                                precision = va_arg(args, int);
                        }
+
                        if (precision < 0) {
                                precision = 0;
                        }
@@ -488,10 +491,12 @@ acpi_ut_vsnprintf(char *string,
                                                                        ' ');
                                }
                        }
+
                        for (i = 0; i < length; ++i) {
                                pos = acpi_ut_bound_string_output(pos, end, *s);
                                ++s;
                        }
+
                        while (length < width--) {
                                pos =
                                    acpi_ut_bound_string_output(pos, end, ' ');
@@ -529,9 +534,9 @@ acpi_ut_vsnprintf(char *string,
                        }
 
                        p = va_arg(args, void *);
-                       pos = acpi_ut_format_number(pos, end,
-                                                   ACPI_TO_INTEGER(p), 16,
-                                                   width, precision, type);
+                       pos =
+                           acpi_ut_format_number(pos, end, ACPI_TO_INTEGER(p),
+                                                 16, width, precision, type);
                        continue;
 
                default:
index b3505dbc715e63e9eb9a5d4dd459de9f92f58466..d50b41c4daa788a0949e811747afeac1879ad33f 100644 (file)
@@ -441,8 +441,8 @@ acpi_ut_walk_aml_resources(struct acpi_walk_state *walk_state,
                    acpi_ut_validate_resource(walk_state, aml, &resource_index);
                if (ACPI_FAILURE(status)) {
                        /*
-                        * Exit on failure. Cannot continue because the descriptor length
-                        * may be bogus also.
+                        * Exit on failure. Cannot continue because the descriptor
+                        * length may be bogus also.
                         */
                        return_ACPI_STATUS(status);
                }
@@ -568,8 +568,8 @@ acpi_ut_validate_resource(struct acpi_walk_state *walk_state,
        }
 
        /*
-        * Check validity of the resource type, via acpi_gbl_resource_types. Zero
-        * indicates an invalid resource.
+        * Check validity of the resource type, via acpi_gbl_resource_types.
+        * Zero indicates an invalid resource.
         */
        if (!acpi_gbl_resource_types[resource_index]) {
                goto invalid_resource;
index f201171c5dda9fcd877181550976c95e131e61a0..0050e00997ed5a7e3f4f6cec09772deed57200d8 100644 (file)
@@ -246,6 +246,7 @@ union acpi_generic_state *acpi_ut_create_pkg_state(void *internal_object,
        state->pkg.dest_object = external_object;
        state->pkg.index = index;
        state->pkg.num_packages = 1;
+
        return (state);
 }
 
@@ -279,6 +280,7 @@ union acpi_generic_state *acpi_ut_create_control_state(void)
 
        state->common.descriptor_type = ACPI_DESC_TYPE_STATE_CONTROL;
        state->common.state = ACPI_CONTROL_CONDITIONAL_EXECUTING;
+
        return (state);
 }
 
@@ -304,5 +306,6 @@ void acpi_ut_delete_generic_state(union acpi_generic_state *state)
        if (state) {
                (void)acpi_os_release_object(acpi_gbl_state_cache, state);
        }
+
        return;
 }
index 4ddd105d9741c05f641acdd6250a669bda4d6a0d..958b2f7b552d315a5b02f40f268dbf827b814380 100644 (file)
@@ -135,6 +135,7 @@ void acpi_ut_print_string(char *string, u16 max_length)
                        break;
                }
        }
+
        acpi_os_printf("\"");
 
        if (i == max_length && string[i]) {
@@ -239,6 +240,14 @@ void acpi_ut_repair_name(char *name)
 
        ACPI_FUNCTION_NAME(ut_repair_name);
 
+       /*
+        * Special case for the root node. This can happen if we get an
+        * error during the execution of module-level code.
+        */
+       if (ACPI_COMPARE_NAME(name, "\\___")) {
+               return;
+       }
+
        ACPI_MOVE_NAME(&original_name, name);
 
        /* Check each character in the name */
index 9a7dc8196a5da76779f10c855d17fc0e5f4430c8..ea698e98442e4b7645d150aa33e5ef328270cb07 100644 (file)
@@ -150,9 +150,9 @@ void *acpi_ut_allocate_and_track(acpi_size size,
                return (NULL);
        }
 
-       status = acpi_ut_track_allocation(allocation, size,
-                                         ACPI_MEM_MALLOC, component, module,
-                                         line);
+       status =
+           acpi_ut_track_allocation(allocation, size, ACPI_MEM_MALLOC,
+                                    component, module, line);
        if (ACPI_FAILURE(status)) {
                acpi_os_free(allocation);
                return (NULL);
@@ -161,6 +161,7 @@ void *acpi_ut_allocate_and_track(acpi_size size,
        acpi_gbl_global_list->total_allocated++;
        acpi_gbl_global_list->total_size += (u32)size;
        acpi_gbl_global_list->current_total_size += (u32)size;
+
        if (acpi_gbl_global_list->current_total_size >
            acpi_gbl_global_list->max_occupied) {
                acpi_gbl_global_list->max_occupied =
@@ -223,6 +224,7 @@ void *acpi_ut_allocate_zeroed_and_track(acpi_size size,
        acpi_gbl_global_list->total_allocated++;
        acpi_gbl_global_list->total_size += (u32)size;
        acpi_gbl_global_list->current_total_size += (u32)size;
+
        if (acpi_gbl_global_list->current_total_size >
            acpi_gbl_global_list->max_occupied) {
                acpi_gbl_global_list->max_occupied =
@@ -269,8 +271,8 @@ acpi_ut_free_and_track(void *allocation,
        acpi_gbl_global_list->total_freed++;
        acpi_gbl_global_list->current_total_size -= debug_block->size;
 
-       status = acpi_ut_remove_allocation(debug_block,
-                                          component, module, line);
+       status =
+           acpi_ut_remove_allocation(debug_block, component, module, line);
        if (ACPI_FAILURE(status)) {
                ACPI_EXCEPTION((AE_INFO, status, "Could not free memory"));
        }
@@ -525,35 +527,35 @@ void acpi_ut_dump_allocation_info(void)
 
 /*
        ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
-                         ("%30s: %4d (%3d Kb)\n", "Current allocations",
-                         mem_list->current_count,
-                         ROUND_UP_TO_1K (mem_list->current_size)));
+               ("%30s: %4d (%3d Kb)\n", "Current allocations",
+               mem_list->current_count,
+               ROUND_UP_TO_1K (mem_list->current_size)));
 
        ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
-                         ("%30s: %4d (%3d Kb)\n", "Max concurrent allocations",
-                         mem_list->max_concurrent_count,
-                         ROUND_UP_TO_1K (mem_list->max_concurrent_size)));
+               ("%30s: %4d (%3d Kb)\n", "Max concurrent allocations",
+               mem_list->max_concurrent_count,
+               ROUND_UP_TO_1K (mem_list->max_concurrent_size)));
 
        ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
-                         ("%30s: %4d (%3d Kb)\n", "Total (all) internal objects",
-                         running_object_count,
-                         ROUND_UP_TO_1K (running_object_size)));
+               ("%30s: %4d (%3d Kb)\n", "Total (all) internal objects",
+               running_object_count,
+               ROUND_UP_TO_1K (running_object_size)));
 
        ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
-                         ("%30s: %4d (%3d Kb)\n", "Total (all) allocations",
-                         running_alloc_count,
-                         ROUND_UP_TO_1K (running_alloc_size)));
+               ("%30s: %4d (%3d Kb)\n", "Total (all) allocations",
+               running_alloc_count,
+               ROUND_UP_TO_1K (running_alloc_size)));
 
        ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
-                         ("%30s: %4d (%3d Kb)\n", "Current Nodes",
-                         acpi_gbl_current_node_count,
-                         ROUND_UP_TO_1K (acpi_gbl_current_node_size)));
+               ("%30s: %4d (%3d Kb)\n", "Current Nodes",
+               acpi_gbl_current_node_count,
+               ROUND_UP_TO_1K (acpi_gbl_current_node_size)));
 
        ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
-                         ("%30s: %4d (%3d Kb)\n", "Max Nodes",
-                         acpi_gbl_max_concurrent_node_count,
-                         ROUND_UP_TO_1K ((acpi_gbl_max_concurrent_node_count *
-                                        sizeof (struct acpi_namespace_node)))));
+               ("%30s: %4d (%3d Kb)\n", "Max Nodes",
+               acpi_gbl_max_concurrent_node_count,
+               ROUND_UP_TO_1K ((acpi_gbl_max_concurrent_node_count *
+                       sizeof (struct acpi_namespace_node)))));
 */
        return_VOID;
 }
index f9c8f9ce1f0f3e315d00db27e5e5623b92f278fa..9f3f0a1591f6e39e84c51ef42cc7c6d9775f7708 100644 (file)
@@ -154,7 +154,6 @@ acpi_status acpi_get_system_info(struct acpi_buffer * out_buffer)
         * Populate the return buffer
         */
        info_ptr = (struct acpi_system_info *)out_buffer->pointer;
-
        info_ptr->acpi_ca_version = ACPI_CA_VERSION;
 
        /* System flags (ACPI capabilities) */
@@ -216,7 +215,6 @@ acpi_status acpi_get_statistics(struct acpi_statistics *stats)
        /* Other counters */
 
        stats->method_count = acpi_method_count;
-
        return_ACPI_STATUS(AE_OK);
 }
 
index 98d578753101e3ff4b7bcf73c83fdb679bc7c765..f6cbaf451dbfec8c03484c6821f8371617b22e58 100644 (file)
@@ -117,6 +117,7 @@ acpi_exception(const char *module_name,
                acpi_os_printf(ACPI_MSG_EXCEPTION "%s, ",
                               acpi_format_exception(status));
        }
+
        va_start(arg_list, format);
        acpi_os_vprintf(format, arg_list);
        ACPI_MSG_SUFFIX;
index a7137ec2844789240c44a7a42d6358e7839d880b..e38facd3e32f51902683354aec9266fe61f1f9f2 100644 (file)
@@ -147,6 +147,28 @@ acpi_status __init acpi_enable_subsystem(u32 flags)
 
        ACPI_FUNCTION_TRACE(acpi_enable_subsystem);
 
+       /*
+        * The early initialization phase is complete. The namespace is loaded,
+        * and we can now support address spaces other than Memory, I/O, and
+        * PCI_Config.
+        */
+       acpi_gbl_early_initialization = FALSE;
+
+       /*
+        * Install the default operation region handlers. These are the
+        * handlers that are defined by the ACPI specification to be
+        * "always accessible" -- namely, system_memory, system_IO, and
+        * PCI_Config. This also means that no _REG methods need to be
+        * run for these address spaces. We need to have these handlers
+        * installed before any AML code can be executed, especially any
+        * module-level code (11/2015).
+        */
+       status = acpi_ev_install_region_handlers();
+       if (ACPI_FAILURE(status)) {
+               ACPI_EXCEPTION((AE_INFO, status,
+                               "During Region initialization"));
+               return_ACPI_STATUS(status);
+       }
 #if (!ACPI_REDUCED_HARDWARE)
 
        /* Enable ACPI mode */
@@ -175,23 +197,7 @@ acpi_status __init acpi_enable_subsystem(u32 flags)
                        return_ACPI_STATUS(status);
                }
        }
-#endif                         /* !ACPI_REDUCED_HARDWARE */
-
-       /*
-        * Install the default op_region handlers. These are installed unless
-        * other handlers have already been installed via the
-        * install_address_space_handler interface.
-        */
-       if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
-               ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
-                                 "[Init] Installing default address space handlers\n"));
 
-               status = acpi_ev_install_region_handlers();
-               if (ACPI_FAILURE(status)) {
-                       return_ACPI_STATUS(status);
-               }
-       }
-#if (!ACPI_REDUCED_HARDWARE)
        /*
         * Initialize ACPI Event handling (Fixed and General Purpose)
         *
@@ -261,6 +267,7 @@ acpi_status __init acpi_initialize_objects(u32 flags)
         * initialized, even if they contain executable AML (see the call to
         * acpi_ns_initialize_objects below).
         */
+       acpi_gbl_reg_methods_enabled = TRUE;
        if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
                ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
                                  "[Init] Executing _REG OpRegion methods\n"));
@@ -285,8 +292,14 @@ acpi_status __init acpi_initialize_objects(u32 flags)
         * outside of any control method is wrapped with a temporary control
         * method object and placed on a global list. The methods on this list
         * are executed below.
+        *
+        * This case executes the module-level code for all tables only after
+        * all of the tables have been loaded. It is a legacy option and is
+        * not compatible with other ACPI implementations. See acpi_ns_load_table.
         */
-       acpi_ns_exec_module_code_list();
+       if (acpi_gbl_group_module_level_code) {
+               acpi_ns_exec_module_code_list();
+       }
 
        /*
         * Initialize the objects that remain uninitialized. This runs the
index f2606af3364c7f6ca1c580bc3bc4921df46f1b3f..95d6123a7010e533a8e64e5dcec6cafb325191dc 100644 (file)
@@ -89,9 +89,9 @@ acpi_ut_get_mutex_object(acpi_handle handle,
 
        mutex_node = handle;
        if (pathname != NULL) {
-               status = acpi_get_handle(handle, pathname,
-                                        ACPI_CAST_PTR(acpi_handle,
-                                                      &mutex_node));
+               status =
+                   acpi_get_handle(handle, pathname,
+                                   ACPI_CAST_PTR(acpi_handle, &mutex_node));
                if (ACPI_FAILURE(status)) {
                        return (status);
                }
index a212cefae524f8d2daaa2b4161ee16c2fae90cf8..891c42d1cd652c732f4957fc8bb2c2f20a5fc470 100644 (file)
@@ -180,14 +180,15 @@ static void acpi_print_osc_error(acpi_handle handle,
        int i;
 
        if (ACPI_FAILURE(acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer)))
-               printk(KERN_DEBUG "%s\n", error);
+               printk(KERN_DEBUG "%s: %s\n", context->uuid_str, error);
        else {
-               printk(KERN_DEBUG "%s:%s\n", (char *)buffer.pointer, error);
+               printk(KERN_DEBUG "%s (%s): %s\n",
+                      (char *)buffer.pointer, context->uuid_str, error);
                kfree(buffer.pointer);
        }
-       printk(KERN_DEBUG"_OSC request data:");
+       printk(KERN_DEBUG "_OSC request data:");
        for (i = 0; i < context->cap.length; i += sizeof(u32))
-               printk("%x ", *((u32 *)(context->cap.pointer + i)));
+               printk(" %x", *((u32 *)(context->cap.pointer + i)));
        printk("\n");
 }
 
@@ -1094,6 +1095,7 @@ static int __init acpi_init(void)
        acpi_debugfs_init();
        acpi_sleep_proc_init();
        acpi_wakeup_device_init();
+       acpi_debugger_init();
        return 0;
 }
 
index fa4585a6914e912a402ec339d4bd241dd0fadac1..ee9e0f27b2bf43fc33ad1008736f8837f0a640cd 100644 (file)
@@ -17,25 +17,6 @@ enum acpi_irq_model_id acpi_irq_model;
 
 static struct fwnode_handle *acpi_gsi_domain_id;
 
-static unsigned int acpi_gsi_get_irq_type(int trigger, int polarity)
-{
-       switch (polarity) {
-       case ACPI_ACTIVE_LOW:
-               return trigger == ACPI_EDGE_SENSITIVE ?
-                      IRQ_TYPE_EDGE_FALLING :
-                      IRQ_TYPE_LEVEL_LOW;
-       case ACPI_ACTIVE_HIGH:
-               return trigger == ACPI_EDGE_SENSITIVE ?
-                      IRQ_TYPE_EDGE_RISING :
-                      IRQ_TYPE_LEVEL_HIGH;
-       case ACPI_ACTIVE_BOTH:
-               if (trigger == ACPI_EDGE_SENSITIVE)
-                       return IRQ_TYPE_EDGE_BOTH;
-       default:
-               return IRQ_TYPE_NONE;
-       }
-}
-
 /**
  * acpi_gsi_to_irq() - Retrieve the linux irq number for a given GSI
  * @gsi: GSI IRQ number to map
@@ -82,7 +63,7 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger,
 
        fwspec.fwnode = acpi_gsi_domain_id;
        fwspec.param[0] = gsi;
-       fwspec.param[1] = acpi_gsi_get_irq_type(trigger, polarity);
+       fwspec.param[1] = acpi_dev_get_irq_type(trigger, polarity);
        fwspec.param_count = 2;
 
        return irq_create_fwspec_mapping(&fwspec);
index 11d87bf67e738ce7e7a07541993b92bbb66e423a..1e6833a5cd44b6db55b5c9e376eceabfb44b30e0 100644 (file)
@@ -86,6 +86,14 @@ bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent);
 #define ACPI_STA_DEFAULT (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | \
                          ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING)
 
+extern struct list_head acpi_bus_id_list;
+
+struct acpi_device_bus_id {
+       char bus_id[15];
+       unsigned int instance_no;
+       struct list_head node;
+};
+
 int acpi_device_add(struct acpi_device *device,
                    void (*release)(struct device *));
 void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
index 32d684af0ec7c8a36781e5b7e712c7dd0e65b241..67da6fb722740bf9f540c2a7d603460ceb0e2e8f 100644 (file)
@@ -220,6 +220,7 @@ void acpi_os_printf(const char *fmt, ...)
        acpi_os_vprintf(fmt, args);
        va_end(args);
 }
+EXPORT_SYMBOL(acpi_os_printf);
 
 void acpi_os_vprintf(const char *fmt, va_list args)
 {
@@ -234,7 +235,8 @@ void acpi_os_vprintf(const char *fmt, va_list args)
                printk(KERN_CONT "%s", buffer);
        }
 #else
-       printk(KERN_CONT "%s", buffer);
+       if (acpi_debugger_write_log(buffer) < 0)
+               printk(KERN_CONT "%s", buffer);
 #endif
 }
 
@@ -364,6 +366,19 @@ static void acpi_unmap(acpi_physical_address pg_off, void __iomem *vaddr)
                iounmap(vaddr);
 }
 
+/**
+ * acpi_os_map_iomem - Get a virtual address for a given physical address range.
+ * @phys: Start of the physical address range to map.
+ * @size: Size of the physical address range to map.
+ *
+ * Look up the given physical address range in the list of existing ACPI memory
+ * mappings.  If found, get a reference to it and return a pointer to it (its
+ * virtual address).  If not found, map it, add it to that list and return a
+ * pointer to it.
+ *
+ * During early init (when acpi_gbl_permanent_mmap has not been set yet) this
+ * routine simply calls __acpi_map_table() to get the job done.
+ */
 void __iomem *__init_refok
 acpi_os_map_iomem(acpi_physical_address phys, acpi_size size)
 {
@@ -439,6 +454,20 @@ static void acpi_os_map_cleanup(struct acpi_ioremap *map)
        }
 }
 
+/**
+ * acpi_os_unmap_iomem - Drop a memory mapping reference.
+ * @virt: Start of the address range to drop a reference to.
+ * @size: Size of the address range to drop a reference to.
+ *
+ * Look up the given virtual address range in the list of existing ACPI memory
+ * mappings, drop a reference to it and unmap it if there are no more active
+ * references to it.
+ *
+ * During early init (when acpi_gbl_permanent_mmap has not been set yet) this
+ * routine simply calls __acpi_unmap_table() to get the job done.  Since
+ * __acpi_unmap_table() is an __init function, the __ref annotation is needed
+ * here.
+ */
 void __ref acpi_os_unmap_iomem(void __iomem *virt, acpi_size size)
 {
        struct acpi_ioremap *map;
@@ -1101,6 +1130,200 @@ static void acpi_os_execute_deferred(struct work_struct *work)
        kfree(dpc);
 }
 
+#ifdef CONFIG_ACPI_DEBUGGER
+static struct acpi_debugger acpi_debugger;
+static bool acpi_debugger_initialized;
+
+int acpi_register_debugger(struct module *owner,
+                          const struct acpi_debugger_ops *ops)
+{
+       int ret = 0;
+
+       mutex_lock(&acpi_debugger.lock);
+       if (acpi_debugger.ops) {
+               ret = -EBUSY;
+               goto err_lock;
+       }
+
+       acpi_debugger.owner = owner;
+       acpi_debugger.ops = ops;
+
+err_lock:
+       mutex_unlock(&acpi_debugger.lock);
+       return ret;
+}
+EXPORT_SYMBOL(acpi_register_debugger);
+
+void acpi_unregister_debugger(const struct acpi_debugger_ops *ops)
+{
+       mutex_lock(&acpi_debugger.lock);
+       if (ops == acpi_debugger.ops) {
+               acpi_debugger.ops = NULL;
+               acpi_debugger.owner = NULL;
+       }
+       mutex_unlock(&acpi_debugger.lock);
+}
+EXPORT_SYMBOL(acpi_unregister_debugger);
+
+int acpi_debugger_create_thread(acpi_osd_exec_callback function, void *context)
+{
+       int ret;
+       int (*func)(acpi_osd_exec_callback, void *);
+       struct module *owner;
+
+       if (!acpi_debugger_initialized)
+               return -ENODEV;
+       mutex_lock(&acpi_debugger.lock);
+       if (!acpi_debugger.ops) {
+               ret = -ENODEV;
+               goto err_lock;
+       }
+       if (!try_module_get(acpi_debugger.owner)) {
+               ret = -ENODEV;
+               goto err_lock;
+       }
+       func = acpi_debugger.ops->create_thread;
+       owner = acpi_debugger.owner;
+       mutex_unlock(&acpi_debugger.lock);
+
+       ret = func(function, context);
+
+       mutex_lock(&acpi_debugger.lock);
+       module_put(owner);
+err_lock:
+       mutex_unlock(&acpi_debugger.lock);
+       return ret;
+}
+
+ssize_t acpi_debugger_write_log(const char *msg)
+{
+       ssize_t ret;
+       ssize_t (*func)(const char *);
+       struct module *owner;
+
+       if (!acpi_debugger_initialized)
+               return -ENODEV;
+       mutex_lock(&acpi_debugger.lock);
+       if (!acpi_debugger.ops) {
+               ret = -ENODEV;
+               goto err_lock;
+       }
+       if (!try_module_get(acpi_debugger.owner)) {
+               ret = -ENODEV;
+               goto err_lock;
+       }
+       func = acpi_debugger.ops->write_log;
+       owner = acpi_debugger.owner;
+       mutex_unlock(&acpi_debugger.lock);
+
+       ret = func(msg);
+
+       mutex_lock(&acpi_debugger.lock);
+       module_put(owner);
+err_lock:
+       mutex_unlock(&acpi_debugger.lock);
+       return ret;
+}
+
+ssize_t acpi_debugger_read_cmd(char *buffer, size_t buffer_length)
+{
+       ssize_t ret;
+       ssize_t (*func)(char *, size_t);
+       struct module *owner;
+
+       if (!acpi_debugger_initialized)
+               return -ENODEV;
+       mutex_lock(&acpi_debugger.lock);
+       if (!acpi_debugger.ops) {
+               ret = -ENODEV;
+               goto err_lock;
+       }
+       if (!try_module_get(acpi_debugger.owner)) {
+               ret = -ENODEV;
+               goto err_lock;
+       }
+       func = acpi_debugger.ops->read_cmd;
+       owner = acpi_debugger.owner;
+       mutex_unlock(&acpi_debugger.lock);
+
+       ret = func(buffer, buffer_length);
+
+       mutex_lock(&acpi_debugger.lock);
+       module_put(owner);
+err_lock:
+       mutex_unlock(&acpi_debugger.lock);
+       return ret;
+}
+
+int acpi_debugger_wait_command_ready(void)
+{
+       int ret;
+       int (*func)(bool, char *, size_t);
+       struct module *owner;
+
+       if (!acpi_debugger_initialized)
+               return -ENODEV;
+       mutex_lock(&acpi_debugger.lock);
+       if (!acpi_debugger.ops) {
+               ret = -ENODEV;
+               goto err_lock;
+       }
+       if (!try_module_get(acpi_debugger.owner)) {
+               ret = -ENODEV;
+               goto err_lock;
+       }
+       func = acpi_debugger.ops->wait_command_ready;
+       owner = acpi_debugger.owner;
+       mutex_unlock(&acpi_debugger.lock);
+
+       ret = func(acpi_gbl_method_executing,
+                  acpi_gbl_db_line_buf, ACPI_DB_LINE_BUFFER_SIZE);
+
+       mutex_lock(&acpi_debugger.lock);
+       module_put(owner);
+err_lock:
+       mutex_unlock(&acpi_debugger.lock);
+       return ret;
+}
+
+int acpi_debugger_notify_command_complete(void)
+{
+       int ret;
+       int (*func)(void);
+       struct module *owner;
+
+       if (!acpi_debugger_initialized)
+               return -ENODEV;
+       mutex_lock(&acpi_debugger.lock);
+       if (!acpi_debugger.ops) {
+               ret = -ENODEV;
+               goto err_lock;
+       }
+       if (!try_module_get(acpi_debugger.owner)) {
+               ret = -ENODEV;
+               goto err_lock;
+       }
+       func = acpi_debugger.ops->notify_command_complete;
+       owner = acpi_debugger.owner;
+       mutex_unlock(&acpi_debugger.lock);
+
+       ret = func();
+
+       mutex_lock(&acpi_debugger.lock);
+       module_put(owner);
+err_lock:
+       mutex_unlock(&acpi_debugger.lock);
+       return ret;
+}
+
+int __init acpi_debugger_init(void)
+{
+       mutex_init(&acpi_debugger.lock);
+       acpi_debugger_initialized = true;
+       return 0;
+}
+#endif
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_os_execute
@@ -1127,6 +1350,15 @@ acpi_status acpi_os_execute(acpi_execute_type type,
                          "Scheduling function [%p(%p)] for deferred execution.\n",
                          function, context));
 
+       if (type == OSL_DEBUGGER_MAIN_THREAD) {
+               ret = acpi_debugger_create_thread(function, context);
+               if (ret) {
+                       pr_err("Call to kthread_create() failed.\n");
+                       status = AE_ERROR;
+               }
+               goto out_thread;
+       }
+
        /*
         * Allocate/initialize DPC structure.  Note that this memory will be
         * freed by the callee.  The kernel handles the work_struct list  in a
@@ -1151,11 +1383,17 @@ acpi_status acpi_os_execute(acpi_execute_type type,
        if (type == OSL_NOTIFY_HANDLER) {
                queue = kacpi_notify_wq;
                INIT_WORK(&dpc->work, acpi_os_execute_deferred);
-       } else {
+       } else if (type == OSL_GPE_HANDLER) {
                queue = kacpid_wq;
                INIT_WORK(&dpc->work, acpi_os_execute_deferred);
+       } else {
+               pr_err("Unsupported os_execute type %d.\n", type);
+               status = AE_ERROR;
        }
 
+       if (ACPI_FAILURE(status))
+               goto err_workqueue;
+
        /*
         * On some machines, a software-initiated SMI causes corruption unless
         * the SMI runs on CPU 0.  An SMI can be initiated by any AML, but
@@ -1164,13 +1402,15 @@ acpi_status acpi_os_execute(acpi_execute_type type,
         * queueing on CPU 0.
         */
        ret = queue_work_on(0, queue, &dpc->work);
-
        if (!ret) {
                printk(KERN_ERR PREFIX
                          "Call to queue_work() failed.\n");
                status = AE_ERROR;
-               kfree(dpc);
        }
+err_workqueue:
+       if (ACPI_FAILURE(status))
+               kfree(dpc);
+out_thread:
        return status;
 }
 EXPORT_SYMBOL(acpi_os_execute);
@@ -1358,10 +1598,39 @@ acpi_status acpi_os_get_line(char *buffer, u32 buffer_length, u32 *bytes_read)
                chars = strlen(buffer) - 1;
                buffer[chars] = '\0';
        }
+#else
+       int ret;
+
+       ret = acpi_debugger_read_cmd(buffer, buffer_length);
+       if (ret < 0)
+               return AE_ERROR;
+       if (bytes_read)
+               *bytes_read = ret;
 #endif
 
        return AE_OK;
 }
+EXPORT_SYMBOL(acpi_os_get_line);
+
+acpi_status acpi_os_wait_command_ready(void)
+{
+       int ret;
+
+       ret = acpi_debugger_wait_command_ready();
+       if (ret < 0)
+               return AE_ERROR;
+       return AE_OK;
+}
+
+acpi_status acpi_os_notify_command_complete(void)
+{
+       int ret;
+
+       ret = acpi_debugger_notify_command_complete();
+       if (ret < 0)
+               return AE_ERROR;
+       return AE_OK;
+}
 
 acpi_status acpi_os_signal(u32 function, void *info)
 {
index c9336751e5e3708f96e9f972ab05fc5454970adb..d30184c7f3bcb851c62fe410906160b6e802a631 100644 (file)
@@ -131,9 +131,6 @@ static void do_prt_fixups(struct acpi_prt_entry *entry,
                quirk = &prt_quirks[i];
 
                /* All current quirks involve link devices, not GSIs */
-               if (!prt->source)
-                       continue;
-
                if (dmi_check_system(quirk->system) &&
                    entry->id.segment == quirk->segment &&
                    entry->id.bus == quirk->bus &&
index 7c8408b946ca10160d41648f14f99a6716529903..fa2863567eed3c944c884245118c0d55d5ec5fdd 100644 (file)
@@ -4,6 +4,7 @@
  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
  *  Copyright (C) 2002       Dominik Brodowski <devel@brodo.de>
+ *  Copyright (c) 2015, The Linux Foundation. All rights reserved.
  *
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  *
@@ -67,12 +68,12 @@ static struct acpi_scan_handler pci_link_handler = {
  * later even the link is disable. Instead, we just repick the active irq
  */
 struct acpi_pci_link_irq {
-       u8 active;              /* Current IRQ */
+       u32 active;             /* Current IRQ */
        u8 triggering;          /* All IRQs */
        u8 polarity;            /* All IRQs */
        u8 resource_type;
        u8 possible_count;
-       u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE];
+       u32 possible[ACPI_PCI_LINK_MAX_POSSIBLE];
        u8 initialized:1;
        u8 reserved:7;
 };
@@ -437,7 +438,6 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
  * enabled system.
  */
 
-#define ACPI_MAX_IRQS          256
 #define ACPI_MAX_ISA_IRQ       16
 
 #define PIRQ_PENALTY_PCI_AVAILABLE     (0)
@@ -447,7 +447,7 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
 #define PIRQ_PENALTY_ISA_USED          (16*16*16*16*16)
 #define PIRQ_PENALTY_ISA_ALWAYS                (16*16*16*16*16*16)
 
-static int acpi_irq_penalty[ACPI_MAX_IRQS] = {
+static int acpi_irq_isa_penalty[ACPI_MAX_ISA_IRQ] = {
        PIRQ_PENALTY_ISA_ALWAYS,        /* IRQ0 timer */
        PIRQ_PENALTY_ISA_ALWAYS,        /* IRQ1 keyboard */
        PIRQ_PENALTY_ISA_ALWAYS,        /* IRQ2 cascade */
@@ -464,9 +464,68 @@ static int acpi_irq_penalty[ACPI_MAX_IRQS] = {
        PIRQ_PENALTY_ISA_USED,          /* IRQ13 fpe, sometimes */
        PIRQ_PENALTY_ISA_USED,          /* IRQ14 ide0 */
        PIRQ_PENALTY_ISA_USED,          /* IRQ15 ide1 */
-       /* >IRQ15 */
 };
 
+struct irq_penalty_info {
+       int irq;
+       int penalty;
+       struct list_head node;
+};
+
+static LIST_HEAD(acpi_irq_penalty_list);
+
+static int acpi_irq_get_penalty(int irq)
+{
+       struct irq_penalty_info *irq_info;
+
+       if (irq < ACPI_MAX_ISA_IRQ)
+               return acpi_irq_isa_penalty[irq];
+
+       list_for_each_entry(irq_info, &acpi_irq_penalty_list, node) {
+               if (irq_info->irq == irq)
+                       return irq_info->penalty;
+       }
+
+       return 0;
+}
+
+static int acpi_irq_set_penalty(int irq, int new_penalty)
+{
+       struct irq_penalty_info *irq_info;
+
+       /* see if this is a ISA IRQ */
+       if (irq < ACPI_MAX_ISA_IRQ) {
+               acpi_irq_isa_penalty[irq] = new_penalty;
+               return 0;
+       }
+
+       /* next, try to locate from the dynamic list */
+       list_for_each_entry(irq_info, &acpi_irq_penalty_list, node) {
+               if (irq_info->irq == irq) {
+                       irq_info->penalty  = new_penalty;
+                       return 0;
+               }
+       }
+
+       /* nope, let's allocate a slot for this IRQ */
+       irq_info = kzalloc(sizeof(*irq_info), GFP_KERNEL);
+       if (!irq_info)
+               return -ENOMEM;
+
+       irq_info->irq = irq;
+       irq_info->penalty = new_penalty;
+       list_add_tail(&irq_info->node, &acpi_irq_penalty_list);
+
+       return 0;
+}
+
+static void acpi_irq_add_penalty(int irq, int penalty)
+{
+       int curpen = acpi_irq_get_penalty(irq);
+
+       acpi_irq_set_penalty(irq, curpen + penalty);
+}
+
 int __init acpi_irq_penalty_init(void)
 {
        struct acpi_pci_link *link;
@@ -487,15 +546,16 @@ int __init acpi_irq_penalty_init(void)
                            link->irq.possible_count;
 
                        for (i = 0; i < link->irq.possible_count; i++) {
-                               if (link->irq.possible[i] < ACPI_MAX_ISA_IRQ)
-                                       acpi_irq_penalty[link->irq.
-                                                        possible[i]] +=
-                                           penalty;
+                               if (link->irq.possible[i] < ACPI_MAX_ISA_IRQ) {
+                                       int irqpos = link->irq.possible[i];
+
+                                       acpi_irq_add_penalty(irqpos, penalty);
+                               }
                        }
 
                } else if (link->irq.active) {
-                       acpi_irq_penalty[link->irq.active] +=
-                           PIRQ_PENALTY_PCI_POSSIBLE;
+                       acpi_irq_add_penalty(link->irq.active,
+                                            PIRQ_PENALTY_PCI_POSSIBLE);
                }
        }
 
@@ -547,12 +607,12 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
                 * the use of IRQs 9, 10, 11, and >15.
                 */
                for (i = (link->irq.possible_count - 1); i >= 0; i--) {
-                       if (acpi_irq_penalty[irq] >
-                           acpi_irq_penalty[link->irq.possible[i]])
+                       if (acpi_irq_get_penalty(irq) >
+                           acpi_irq_get_penalty(link->irq.possible[i]))
                                irq = link->irq.possible[i];
                }
        }
-       if (acpi_irq_penalty[irq] >= PIRQ_PENALTY_ISA_ALWAYS) {
+       if (acpi_irq_get_penalty(irq) >= PIRQ_PENALTY_ISA_ALWAYS) {
                printk(KERN_ERR PREFIX "No IRQ available for %s [%s]. "
                            "Try pci=noacpi or acpi=off\n",
                            acpi_device_name(link->device),
@@ -568,7 +628,8 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
                            acpi_device_bid(link->device));
                return -ENODEV;
        } else {
-               acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_USING;
+               acpi_irq_add_penalty(link->irq.active, PIRQ_PENALTY_PCI_USING);
+
                printk(KERN_WARNING PREFIX "%s [%s] enabled at IRQ %d\n",
                       acpi_device_name(link->device),
                       acpi_device_bid(link->device), link->irq.active);
@@ -778,7 +839,7 @@ static void acpi_pci_link_remove(struct acpi_device *device)
 }
 
 /*
- * modify acpi_irq_penalty[] from cmdline
+ * modify penalty from cmdline
  */
 static int __init acpi_irq_penalty_update(char *str, int used)
 {
@@ -796,13 +857,10 @@ static int __init acpi_irq_penalty_update(char *str, int used)
                if (irq < 0)
                        continue;
 
-               if (irq >= ARRAY_SIZE(acpi_irq_penalty))
-                       continue;
-
                if (used)
-                       acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED;
+                       acpi_irq_add_penalty(irq, PIRQ_PENALTY_ISA_USED);
                else
-                       acpi_irq_penalty[irq] = PIRQ_PENALTY_PCI_AVAILABLE;
+                       acpi_irq_set_penalty(irq, PIRQ_PENALTY_PCI_AVAILABLE);
 
                if (retval != 2)        /* no next number */
                        break;
@@ -819,18 +877,15 @@ static int __init acpi_irq_penalty_update(char *str, int used)
  */
 void acpi_penalize_isa_irq(int irq, int active)
 {
-       if (irq >= 0 && irq < ARRAY_SIZE(acpi_irq_penalty)) {
-               if (active)
-                       acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED;
-               else
-                       acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING;
-       }
+       if (irq >= 0)
+               acpi_irq_add_penalty(irq, active ?
+                       PIRQ_PENALTY_ISA_USED : PIRQ_PENALTY_PCI_USING);
 }
 
 bool acpi_isa_irq_available(int irq)
 {
-       return irq >= 0 && (irq >= ARRAY_SIZE(acpi_irq_penalty) ||
-                           acpi_irq_penalty[irq] < PIRQ_PENALTY_ISA_ALWAYS);
+       return irq >= 0 &&
+               (acpi_irq_get_penalty(irq) < PIRQ_PENALTY_ISA_ALWAYS);
 }
 
 /*
@@ -840,13 +895,18 @@ bool acpi_isa_irq_available(int irq)
  */
 void acpi_penalize_sci_irq(int irq, int trigger, int polarity)
 {
-       if (irq >= 0 && irq < ARRAY_SIZE(acpi_irq_penalty)) {
-               if (trigger != ACPI_MADT_TRIGGER_LEVEL ||
-                   polarity != ACPI_MADT_POLARITY_ACTIVE_LOW)
-                       acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_ALWAYS;
-               else
-                       acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING;
-       }
+       int penalty;
+
+       if (irq < 0)
+               return;
+
+       if (trigger != ACPI_MADT_TRIGGER_LEVEL ||
+           polarity != ACPI_MADT_POLARITY_ACTIVE_LOW)
+               penalty = PIRQ_PENALTY_ISA_ALWAYS;
+       else
+               penalty = PIRQ_PENALTY_PCI_USING;
+
+       acpi_irq_add_penalty(irq, penalty);
 }
 
 /*
index 88f4306744c0aa23cb1b8b38ecf7f8df9c38b5f1..2aee41655ce9223a264a56e11d439ddccc365632 100644 (file)
@@ -346,7 +346,7 @@ void acpi_free_properties(struct acpi_device *adev)
  *
  * Return: %0 if property with @name has been found (success),
  *         %-EINVAL if the arguments are invalid,
- *         %-ENODATA if the property doesn't exist,
+ *         %-EINVAL if the property doesn't exist,
  *         %-EPROTO if the property value type doesn't match @type.
  */
 static int acpi_data_get_property(struct acpi_device_data *data,
@@ -360,7 +360,7 @@ static int acpi_data_get_property(struct acpi_device_data *data,
                return -EINVAL;
 
        if (!data->pointer || !data->properties)
-               return -ENODATA;
+               return -EINVAL;
 
        properties = data->properties;
        for (i = 0; i < properties->package.count; i++) {
@@ -375,13 +375,13 @@ static int acpi_data_get_property(struct acpi_device_data *data,
                if (!strcmp(name, propname->string.pointer)) {
                        if (type != ACPI_TYPE_ANY && propvalue->type != type)
                                return -EPROTO;
-                       else if (obj)
+                       if (obj)
                                *obj = propvalue;
 
                        return 0;
                }
        }
-       return -ENODATA;
+       return -EINVAL;
 }
 
 /**
@@ -439,7 +439,7 @@ int acpi_node_prop_get(struct fwnode_handle *fwnode, const char *propname,
  *
  * Return: %0 if array property (package) with @name has been found (success),
  *         %-EINVAL if the arguments are invalid,
- *         %-ENODATA if the property doesn't exist,
+ *         %-EINVAL if the property doesn't exist,
  *         %-EPROTO if the property is not a package or the type of its elements
  *           doesn't match @type.
  */
index cdc5c2599bebcc1a95ca2f29a525a5e63fab3b0f..d02fd53042a5d95603f1cd99176bff6b799dd9dd 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/export.h>
 #include <linux/ioport.h>
 #include <linux/slab.h>
+#include <linux/irq.h>
 
 #ifdef CONFIG_X86
 #define valid_IRQ(i) (((i) != 0) && ((i) != 2))
@@ -336,6 +337,31 @@ unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable)
 }
 EXPORT_SYMBOL_GPL(acpi_dev_irq_flags);
 
+/**
+ * acpi_dev_get_irq_type - Determine irq type.
+ * @triggering: Triggering type as provided by ACPI.
+ * @polarity: Interrupt polarity as provided by ACPI.
+ */
+unsigned int acpi_dev_get_irq_type(int triggering, int polarity)
+{
+       switch (polarity) {
+       case ACPI_ACTIVE_LOW:
+               return triggering == ACPI_EDGE_SENSITIVE ?
+                      IRQ_TYPE_EDGE_FALLING :
+                      IRQ_TYPE_LEVEL_LOW;
+       case ACPI_ACTIVE_HIGH:
+               return triggering == ACPI_EDGE_SENSITIVE ?
+                      IRQ_TYPE_EDGE_RISING :
+                      IRQ_TYPE_LEVEL_HIGH;
+       case ACPI_ACTIVE_BOTH:
+               if (triggering == ACPI_EDGE_SENSITIVE)
+                       return IRQ_TYPE_EDGE_BOTH;
+       default:
+               return IRQ_TYPE_NONE;
+       }
+}
+EXPORT_SYMBOL_GPL(acpi_dev_get_irq_type);
+
 static void acpi_dev_irqresource_disabled(struct resource *res, u32 gsi)
 {
        res->start = gsi;
index cb3dedb1beaed3b045cd0ae5dc6f338623551d5c..ad0b13ad4bbb93b2b10da64b9607db809bdba39b 100644 (file)
@@ -417,11 +417,11 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery)
                if ((value & 0xf000) != sel) {
                        value &= 0x0fff;
                        value |= sel;
-               ret = acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD,
+                       ret = acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD,
                                         ACPI_SBS_MANAGER,
                                         0x01, (u8 *)&value, 2);
-               if (ret)
-                       goto end;
+                       if (ret)
+                               goto end;
                }
        }
        ret = acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_BATTERY,
index 78d5f02a073bb1c9e84beaeaf2f38b6f54125333..407a3760e8de659863fb4f6cea274a78bf11ff7b 100644 (file)
@@ -39,7 +39,7 @@ static const char *dummy_hid = "device";
 
 static LIST_HEAD(acpi_dep_list);
 static DEFINE_MUTEX(acpi_dep_list_lock);
-static LIST_HEAD(acpi_bus_id_list);
+LIST_HEAD(acpi_bus_id_list);
 static DEFINE_MUTEX(acpi_scan_lock);
 static LIST_HEAD(acpi_scan_handlers_list);
 DEFINE_MUTEX(acpi_device_lock);
@@ -52,12 +52,6 @@ struct acpi_dep_data {
        acpi_handle slave;
 };
 
-struct acpi_device_bus_id{
-       char bus_id[15];
-       unsigned int instance_no;
-       struct list_head node;
-};
-
 void acpi_scan_lock_acquire(void)
 {
        mutex_lock(&acpi_scan_lock);
@@ -471,10 +465,24 @@ static void acpi_device_release(struct device *dev)
 
 static void acpi_device_del(struct acpi_device *device)
 {
+       struct acpi_device_bus_id *acpi_device_bus_id;
+
        mutex_lock(&acpi_device_lock);
        if (device->parent)
                list_del(&device->node);
 
+       list_for_each_entry(acpi_device_bus_id, &acpi_bus_id_list, node)
+               if (!strcmp(acpi_device_bus_id->bus_id,
+                           acpi_device_hid(device))) {
+                       if (acpi_device_bus_id->instance_no > 0)
+                               acpi_device_bus_id->instance_no--;
+                       else {
+                               list_del(&acpi_device_bus_id->node);
+                               kfree(acpi_device_bus_id);
+                       }
+                       break;
+               }
+
        list_del(&device->wakeup_list);
        mutex_unlock(&acpi_device_lock);
 
@@ -1461,7 +1469,7 @@ static int acpi_bus_type_and_status(acpi_handle handle, int *type,
                *type = ACPI_BUS_TYPE_DEVICE;
                status = acpi_bus_get_status_handle(handle, sta);
                if (ACPI_FAILURE(status))
-                       return -ENODEV;
+                       *sta = 0;
                break;
        case ACPI_TYPE_PROCESSOR:
                *type = ACPI_BUS_TYPE_PROCESSOR;
index 0d94621dc856080a0a3715040b7b5339c1edb248..9cb975200cacba638ce84b19fbee8d9948459300 100644 (file)
@@ -61,7 +61,7 @@ static int acpi_sleep_prepare(u32 acpi_state)
        if (acpi_state == ACPI_STATE_S3) {
                if (!acpi_wakeup_address)
                        return -EFAULT;
-               acpi_set_firmware_waking_vector(acpi_wakeup_address);
+               acpi_set_waking_vector(acpi_wakeup_address);
 
        }
        ACPI_FLUSH_CPU_CACHE();
@@ -410,7 +410,7 @@ static void acpi_pm_finish(void)
        acpi_leave_sleep_state(acpi_state);
 
        /* reset firmware waking vector */
-       acpi_set_firmware_waking_vector((acpi_physical_address) 0);
+       acpi_set_waking_vector(0);
 
        acpi_target_sleep_state = ACPI_STATE_S0;
 
index c797ffa568d513c6533b576072f9967ed49f6c42..a9cc34e663f9cf15d356c90d6f36f1d3a78435ed 100644 (file)
@@ -6,3 +6,9 @@ extern struct list_head acpi_wakeup_device_list;
 extern struct mutex acpi_device_lock;
 
 extern void acpi_resume_power_resources(void);
+
+static inline acpi_status acpi_set_waking_vector(u32 wakeup_address)
+{
+       return acpi_set_firmware_waking_vector(
+                               (acpi_physical_address)wakeup_address, 0);
+}
index 475c9079bf856761157887c73ad4d1ec57a98992..f2f9873bb5c363699b49459ebc2fcc9a00af0776 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/dynamic_debug.h>
 
 #include "internal.h"
+#include "sleep.h"
 
 #define _COMPONENT             ACPI_BUS_COMPONENT
 ACPI_MODULE_NAME("utils");
@@ -709,6 +710,36 @@ bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs)
 }
 EXPORT_SYMBOL(acpi_check_dsm);
 
+/**
+ * acpi_dev_present - Detect presence of a given ACPI device in the system.
+ * @hid: Hardware ID of the device.
+ *
+ * Return %true if the device was present at the moment of invocation.
+ * Note that if the device is pluggable, it may since have disappeared.
+ *
+ * For this function to work, acpi_bus_scan() must have been executed
+ * which happens in the subsys_initcall() subsection. Hence, do not
+ * call from a subsys_initcall() or earlier (use acpi_get_devices()
+ * instead). Calling from module_init() is fine (which is synonymous
+ * with device_initcall()).
+ */
+bool acpi_dev_present(const char *hid)
+{
+       struct acpi_device_bus_id *acpi_device_bus_id;
+       bool found = false;
+
+       mutex_lock(&acpi_device_lock);
+       list_for_each_entry(acpi_device_bus_id, &acpi_bus_id_list, node)
+               if (!strcmp(acpi_device_bus_id->bus_id, hid)) {
+                       found = true;
+                       break;
+               }
+       mutex_unlock(&acpi_device_lock);
+
+       return found;
+}
+EXPORT_SYMBOL(acpi_dev_present);
+
 /*
  * acpi_backlight= handling, this is done here rather then in video_detect.c
  * because __setup cannot be used in modules.
index daaf1c4e1e0f78657afb1f140b49e0cf3162d6df..90e2d54be526bcc0df8ec41bf292a8016d99ba3d 100644 (file)
@@ -250,6 +250,15 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
                DMI_MATCH(DMI_PRODUCT_NAME, "XPS L521X"),
                },
        },
+       {
+        /* https://bugzilla.kernel.org/show_bug.cgi?id=108971 */
+        .callback = video_detect_force_video,
+        .ident = "SAMSUNG 530U4E/540U4E",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+               DMI_MATCH(DMI_PRODUCT_NAME, "530U4E/540U4E"),
+               },
+       },
 
        /* Non win8 machines which need native backlight nevertheless */
        {
@@ -279,6 +288,14 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
                DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro12,1"),
                },
        },
+       {
+        .callback = video_detect_force_native,
+        .ident = "Dell Vostro V131",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+               DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V131"),
+               },
+       },
        { },
 };
 
index 1782f3aa386e6db3571aa3a437a2f9a9d5f72066..e05db388bd1ca9a7720af8d2053127ae2ed562d1 100644 (file)
@@ -131,6 +131,8 @@ extern void device_remove_groups(struct device *dev,
 extern char *make_class_name(const char *name, struct kobject *kobj);
 
 extern int devres_release_all(struct device *dev);
+extern void device_block_probing(void);
+extern void device_unblock_probing(void);
 
 /* /sys/devices directory */
 extern struct kset *devices_kset;
index b7d56c5ea3c688fe03c7b5edda4f62c0906a9fc7..0a8bdade53f2f67943dca83bc53cfa74f0b8da7d 100644 (file)
@@ -2261,7 +2261,10 @@ void set_primary_fwnode(struct device *dev, struct fwnode_handle *fwnode)
                if (fwnode_is_primary(fn))
                        fn = fn->secondary;
 
-               fwnode->secondary = fn;
+               if (fn) {
+                       WARN_ON(fwnode->secondary);
+                       fwnode->secondary = fn;
+               }
                dev->fwnode = fwnode;
        } else {
                dev->fwnode = fwnode_is_primary(dev->fwnode) ?
index a641cf3ccad691e76d9665e9defab4ef04e9af4f..7399be790b5dbdf8715694522ba410cdede2808f 100644 (file)
@@ -54,6 +54,13 @@ static LIST_HEAD(deferred_probe_active_list);
 static struct workqueue_struct *deferred_wq;
 static atomic_t deferred_trigger_count = ATOMIC_INIT(0);
 
+/*
+ * In some cases, like suspend to RAM or hibernation, It might be reasonable
+ * to prohibit probing of devices as it could be unsafe.
+ * Once defer_all_probes is true all drivers probes will be forcibly deferred.
+ */
+static bool defer_all_probes;
+
 /*
  * deferred_probe_work_func() - Retry probing devices in the active list.
  */
@@ -171,6 +178,30 @@ static void driver_deferred_probe_trigger(void)
        queue_work(deferred_wq, &deferred_probe_work);
 }
 
+/**
+ * device_block_probing() - Block/defere device's probes
+ *
+ *     It will disable probing of devices and defer their probes instead.
+ */
+void device_block_probing(void)
+{
+       defer_all_probes = true;
+       /* sync with probes to avoid races. */
+       wait_for_device_probe();
+}
+
+/**
+ * device_unblock_probing() - Unblock/enable device's probes
+ *
+ *     It will restore normal behavior and trigger re-probing of deferred
+ * devices.
+ */
+void device_unblock_probing(void)
+{
+       defer_all_probes = false;
+       driver_deferred_probe_trigger();
+}
+
 /**
  * deferred_probe_initcall() - Enable probing of deferred devices
  *
@@ -268,6 +299,9 @@ int device_bind_driver(struct device *dev)
        ret = driver_sysfs_add(dev);
        if (!ret)
                driver_bound(dev);
+       else if (dev->bus)
+               blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
+                                            BUS_NOTIFY_DRIVER_NOT_BOUND, dev);
        return ret;
 }
 EXPORT_SYMBOL_GPL(device_bind_driver);
@@ -277,9 +311,20 @@ static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue);
 
 static int really_probe(struct device *dev, struct device_driver *drv)
 {
-       int ret = 0;
+       int ret = -EPROBE_DEFER;
        int local_trigger_count = atomic_read(&deferred_trigger_count);
 
+       if (defer_all_probes) {
+               /*
+                * Value of defer_all_probes can be set only by
+                * device_defer_all_probes_enable() which, in turn, will call
+                * wait_for_device_probe() right after that to avoid any races.
+                */
+               dev_dbg(dev, "Driver %s force probe deferral\n", drv->name);
+               driver_deferred_probe_add(dev);
+               return ret;
+       }
+
        atomic_inc(&probe_count);
        pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
                 drv->bus->name, __func__, drv->name, dev_name(dev));
@@ -290,7 +335,7 @@ static int really_probe(struct device *dev, struct device_driver *drv)
        /* If using pinctrl, bind pins now before probing */
        ret = pinctrl_bind_pins(dev);
        if (ret)
-               goto probe_failed;
+               goto pinctrl_bind_failed;
 
        if (driver_sysfs_add(dev)) {
                printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
@@ -334,12 +379,17 @@ static int really_probe(struct device *dev, struct device_driver *drv)
        goto done;
 
 probe_failed:
+       if (dev->bus)
+               blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
+                                            BUS_NOTIFY_DRIVER_NOT_BOUND, dev);
+pinctrl_bind_failed:
        devres_release_all(dev);
        driver_sysfs_remove(dev);
        dev->driver = NULL;
        dev_set_drvdata(dev, NULL);
        if (dev->pm_domain && dev->pm_domain->dismiss)
                dev->pm_domain->dismiss(dev);
+       pm_runtime_reinit(dev);
 
        switch (ret) {
        case -EPROBE_DEFER:
@@ -393,6 +443,10 @@ int driver_probe_done(void)
  */
 void wait_for_device_probe(void)
 {
+       /* wait for the deferred probe workqueue to finish */
+       if (driver_deferred_probe_enable)
+               flush_workqueue(deferred_wq);
+
        /* wait for the known devices to complete their probing */
        wait_event(probe_waitqueue, atomic_read(&probe_count) == 0);
        async_synchronize_full();
@@ -695,13 +749,13 @@ static void __device_release_driver(struct device *dev)
                dev_set_drvdata(dev, NULL);
                if (dev->pm_domain && dev->pm_domain->dismiss)
                        dev->pm_domain->dismiss(dev);
+               pm_runtime_reinit(dev);
 
                klist_remove(&dev->p->knode_driver);
                if (dev->bus)
                        blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
                                                     BUS_NOTIFY_UNBOUND_DRIVER,
                                                     dev);
-
        }
 }
 
index 73e399466c6edfe0dbd4b704e925dab5bff19904..8dcbb266643b8773e212bc29f3b2137c3060e059 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/acpi.h>
 #include <linux/clk/clk-conf.h>
 #include <linux/limits.h>
+#include <linux/property.h>
 
 #include "base.h"
 #include "power/power.h"
@@ -318,6 +319,22 @@ int platform_device_add_data(struct platform_device *pdev, const void *data,
 }
 EXPORT_SYMBOL_GPL(platform_device_add_data);
 
+/**
+ * platform_device_add_properties - add built-in properties to a platform device
+ * @pdev: platform device to add properties to
+ * @pset: properties to add
+ *
+ * The function will take deep copy of the properties in @pset and attach
+ * the copy to the platform device. The memory associated with properties
+ * will be freed when the platform device is released.
+ */
+int platform_device_add_properties(struct platform_device *pdev,
+                                  const struct property_set *pset)
+{
+       return device_add_property_set(&pdev->dev, pset);
+}
+EXPORT_SYMBOL_GPL(platform_device_add_properties);
+
 /**
  * platform_device_add - add a platform device to device hierarchy
  * @pdev: platform device we're adding
@@ -429,6 +446,8 @@ void platform_device_del(struct platform_device *pdev)
                        if (r->parent)
                                release_resource(r);
                }
+
+               device_remove_property_set(&pdev->dev);
        }
 }
 EXPORT_SYMBOL_GPL(platform_device_del);
@@ -507,6 +526,12 @@ struct platform_device *platform_device_register_full(
        if (ret)
                goto err;
 
+       if (pdevinfo->pset) {
+               ret = platform_device_add_properties(pdev, pdevinfo->pset);
+               if (ret)
+                       goto err;
+       }
+
        ret = platform_device_add(pdev);
        if (ret) {
 err:
index 60ee5591ee8f0d58d8229bad412d0f5882064e6a..c39b8617280feff712096e6699ffe6d4f3db13f8 100644 (file)
@@ -473,6 +473,7 @@ static int pm_clk_notify(struct notifier_block *nb,
                        enable_clock(dev, NULL);
                }
                break;
+       case BUS_NOTIFY_DRIVER_NOT_BOUND:
        case BUS_NOTIFY_UNBOUND_DRIVER:
                if (clknb->con_ids[0]) {
                        for (con_id = clknb->con_ids; *con_id; con_id++)
index f32b802b98f4b56bc0e733fe1efe5b81b182b009..f48e33385b3e136029c6770505a3dcee3d313e86 100644 (file)
@@ -112,7 +112,7 @@ EXPORT_SYMBOL_GPL(dev_pm_domain_attach);
 
 /**
  * dev_pm_domain_detach - Detach a device from its PM domain.
- * @dev: Device to attach.
+ * @dev: Device to detach.
  * @power_off: Used to indicate whether we should power off the device.
  *
  * This functions will reverse the actions from dev_pm_domain_attach() and thus
index 65f50eccd49b0aa4b6801912fd8d21a73f79a7b9..b8037901284042790a80b12a0ef507f149019240 100644 (file)
@@ -1263,6 +1263,7 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(__pm_genpd_add_device);
 
 /**
  * pm_genpd_remove_device - Remove a device from an I/O PM domain.
@@ -1313,6 +1314,7 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd,
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(pm_genpd_remove_device);
 
 /**
  * pm_genpd_add_subdomain - Add a subdomain to an I/O PM domain.
index 1710c26ba097d363873dfd8318ff1d949aeb4a86..9d626ac08d9c05d6cd5ee97559950bedf89976f8 100644 (file)
@@ -963,6 +963,9 @@ void dpm_complete(pm_message_t state)
        }
        list_splice(&list, &dpm_list);
        mutex_unlock(&dpm_list_mtx);
+
+       /* Allow device probing and trigger re-probing of deferred devices */
+       device_unblock_probing();
        trace_suspend_resume(TPS("dpm_complete"), state.event, false);
 }
 
@@ -1624,6 +1627,20 @@ int dpm_prepare(pm_message_t state)
        trace_suspend_resume(TPS("dpm_prepare"), state.event, true);
        might_sleep();
 
+       /*
+        * Give a chance for the known devices to complete their probes, before
+        * disable probing of devices. This sync point is important at least
+        * at boot time + hibernation restore.
+        */
+       wait_for_device_probe();
+       /*
+        * It is unsafe if probing of devices will happen during suspend or
+        * hibernation and system behavior will be unpredictable in this case.
+        * So, let's prohibit device's probing here and defer their probes
+        * instead. The normal behavior will be restored in dpm_complete().
+        */
+       device_block_probing();
+
        mutex_lock(&dpm_list_mtx);
        while (!list_empty(&dpm_list)) {
                struct device *dev = to_device(dpm_list.next);
index 33c1e18c41a4d467259fb438911418372b7e82a4..19837ef04d8ef21a355e22171117398b2f966f80 100644 (file)
@@ -1,2 +1,3 @@
 ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
 obj-y                          += core.o cpu.o
+obj-$(CONFIG_DEBUG_FS)         += debugfs.o
index b8e76f75073b47a945b695506bb68176c586a161..cf351d3dab1c3b7a9badf6b468092ca216c47012 100644 (file)
@@ -463,6 +463,7 @@ static void _kfree_list_dev_rcu(struct rcu_head *head)
 static void _remove_list_dev(struct device_list_opp *list_dev,
                             struct device_opp *dev_opp)
 {
+       opp_debug_unregister(list_dev, dev_opp);
        list_del(&list_dev->node);
        call_srcu(&dev_opp->srcu_head.srcu, &list_dev->rcu_head,
                  _kfree_list_dev_rcu);
@@ -472,6 +473,7 @@ struct device_list_opp *_add_list_dev(const struct device *dev,
                                      struct device_opp *dev_opp)
 {
        struct device_list_opp *list_dev;
+       int ret;
 
        list_dev = kzalloc(sizeof(*list_dev), GFP_KERNEL);
        if (!list_dev)
@@ -481,6 +483,12 @@ struct device_list_opp *_add_list_dev(const struct device *dev,
        list_dev->dev = dev;
        list_add_rcu(&list_dev->node, &dev_opp->dev_list);
 
+       /* Create debugfs entries for the dev_opp */
+       ret = opp_debug_register(list_dev, dev_opp);
+       if (ret)
+               dev_err(dev, "%s: Failed to register opp debugfs (%d)\n",
+                       __func__, ret);
+
        return list_dev;
 }
 
@@ -551,6 +559,12 @@ static void _remove_device_opp(struct device_opp *dev_opp)
        if (!list_empty(&dev_opp->opp_list))
                return;
 
+       if (dev_opp->supported_hw)
+               return;
+
+       if (dev_opp->prop_name)
+               return;
+
        list_dev = list_first_entry(&dev_opp->dev_list, struct device_list_opp,
                                    node);
 
@@ -596,6 +610,7 @@ static void _opp_remove(struct device_opp *dev_opp,
         */
        if (notify)
                srcu_notifier_call_chain(&dev_opp->srcu_head, OPP_EVENT_REMOVE, opp);
+       opp_debug_remove_one(opp);
        list_del_rcu(&opp->node);
        call_srcu(&dev_opp->srcu_head.srcu, &opp->rcu_head, _kfree_opp_rcu);
 
@@ -673,6 +688,7 @@ static int _opp_add(struct device *dev, struct dev_pm_opp *new_opp,
 {
        struct dev_pm_opp *opp;
        struct list_head *head = &dev_opp->opp_list;
+       int ret;
 
        /*
         * Insert new OPP in order of increasing frequency and discard if
@@ -703,6 +719,11 @@ static int _opp_add(struct device *dev, struct dev_pm_opp *new_opp,
        new_opp->dev_opp = dev_opp;
        list_add_rcu(&new_opp->node, head);
 
+       ret = opp_debug_create_one(new_opp, dev_opp);
+       if (ret)
+               dev_err(dev, "%s: Failed to register opp to debugfs (%d)\n",
+                       __func__, ret);
+
        return 0;
 }
 
@@ -776,35 +797,49 @@ unlock:
 }
 
 /* TODO: Support multiple regulators */
-static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev)
+static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
+                             struct device_opp *dev_opp)
 {
        u32 microvolt[3] = {0};
        u32 val;
        int count, ret;
+       struct property *prop = NULL;
+       char name[NAME_MAX];
+
+       /* Search for "opp-microvolt-<name>" */
+       if (dev_opp->prop_name) {
+               snprintf(name, sizeof(name), "opp-microvolt-%s",
+                        dev_opp->prop_name);
+               prop = of_find_property(opp->np, name, NULL);
+       }
 
-       /* Missing property isn't a problem, but an invalid entry is */
-       if (!of_find_property(opp->np, "opp-microvolt", NULL))
-               return 0;
+       if (!prop) {
+               /* Search for "opp-microvolt" */
+               sprintf(name, "opp-microvolt");
+               prop = of_find_property(opp->np, name, NULL);
 
-       count = of_property_count_u32_elems(opp->np, "opp-microvolt");
+               /* Missing property isn't a problem, but an invalid entry is */
+               if (!prop)
+                       return 0;
+       }
+
+       count = of_property_count_u32_elems(opp->np, name);
        if (count < 0) {
-               dev_err(dev, "%s: Invalid opp-microvolt property (%d)\n",
-                       __func__, count);
+               dev_err(dev, "%s: Invalid %s property (%d)\n",
+                       __func__, name, count);
                return count;
        }
 
        /* There can be one or three elements here */
        if (count != 1 && count != 3) {
-               dev_err(dev, "%s: Invalid number of elements in opp-microvolt property (%d)\n",
-                       __func__, count);
+               dev_err(dev, "%s: Invalid number of elements in %s property (%d)\n",
+                       __func__, name, count);
                return -EINVAL;
        }
 
-       ret = of_property_read_u32_array(opp->np, "opp-microvolt", microvolt,
-                                        count);
+       ret = of_property_read_u32_array(opp->np, name, microvolt, count);
        if (ret) {
-               dev_err(dev, "%s: error parsing opp-microvolt: %d\n", __func__,
-                       ret);
+               dev_err(dev, "%s: error parsing %s: %d\n", __func__, name, ret);
                return -EINVAL;
        }
 
@@ -812,12 +847,271 @@ static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev)
        opp->u_volt_min = microvolt[1];
        opp->u_volt_max = microvolt[2];
 
-       if (!of_property_read_u32(opp->np, "opp-microamp", &val))
+       /* Search for "opp-microamp-<name>" */
+       prop = NULL;
+       if (dev_opp->prop_name) {
+               snprintf(name, sizeof(name), "opp-microamp-%s",
+                        dev_opp->prop_name);
+               prop = of_find_property(opp->np, name, NULL);
+       }
+
+       if (!prop) {
+               /* Search for "opp-microamp" */
+               sprintf(name, "opp-microamp");
+               prop = of_find_property(opp->np, name, NULL);
+       }
+
+       if (prop && !of_property_read_u32(opp->np, name, &val))
                opp->u_amp = val;
 
        return 0;
 }
 
+/**
+ * dev_pm_opp_set_supported_hw() - Set supported platforms
+ * @dev: Device for which supported-hw has to be set.
+ * @versions: Array of hierarchy of versions to match.
+ * @count: Number of elements in the array.
+ *
+ * This is required only for the V2 bindings, and it enables a platform to
+ * specify the hierarchy of versions it supports. OPP layer will then enable
+ * OPPs, which are available for those versions, based on its 'opp-supported-hw'
+ * property.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ */
+int dev_pm_opp_set_supported_hw(struct device *dev, const u32 *versions,
+                               unsigned int count)
+{
+       struct device_opp *dev_opp;
+       int ret = 0;
+
+       /* Hold our list modification lock here */
+       mutex_lock(&dev_opp_list_lock);
+
+       dev_opp = _add_device_opp(dev);
+       if (!dev_opp) {
+               ret = -ENOMEM;
+               goto unlock;
+       }
+
+       /* Make sure there are no concurrent readers while updating dev_opp */
+       WARN_ON(!list_empty(&dev_opp->opp_list));
+
+       /* Do we already have a version hierarchy associated with dev_opp? */
+       if (dev_opp->supported_hw) {
+               dev_err(dev, "%s: Already have supported hardware list\n",
+                       __func__);
+               ret = -EBUSY;
+               goto err;
+       }
+
+       dev_opp->supported_hw = kmemdup(versions, count * sizeof(*versions),
+                                       GFP_KERNEL);
+       if (!dev_opp->supported_hw) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       dev_opp->supported_hw_count = count;
+       mutex_unlock(&dev_opp_list_lock);
+       return 0;
+
+err:
+       _remove_device_opp(dev_opp);
+unlock:
+       mutex_unlock(&dev_opp_list_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_set_supported_hw);
+
+/**
+ * dev_pm_opp_put_supported_hw() - Releases resources blocked for supported hw
+ * @dev: Device for which supported-hw has to be set.
+ *
+ * This is required only for the V2 bindings, and is called for a matching
+ * dev_pm_opp_set_supported_hw(). Until this is called, the device_opp structure
+ * will not be freed.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ */
+void dev_pm_opp_put_supported_hw(struct device *dev)
+{
+       struct device_opp *dev_opp;
+
+       /* Hold our list modification lock here */
+       mutex_lock(&dev_opp_list_lock);
+
+       /* Check for existing list for 'dev' first */
+       dev_opp = _find_device_opp(dev);
+       if (IS_ERR(dev_opp)) {
+               dev_err(dev, "Failed to find dev_opp: %ld\n", PTR_ERR(dev_opp));
+               goto unlock;
+       }
+
+       /* Make sure there are no concurrent readers while updating dev_opp */
+       WARN_ON(!list_empty(&dev_opp->opp_list));
+
+       if (!dev_opp->supported_hw) {
+               dev_err(dev, "%s: Doesn't have supported hardware list\n",
+                       __func__);
+               goto unlock;
+       }
+
+       kfree(dev_opp->supported_hw);
+       dev_opp->supported_hw = NULL;
+       dev_opp->supported_hw_count = 0;
+
+       /* Try freeing device_opp if this was the last blocking resource */
+       _remove_device_opp(dev_opp);
+
+unlock:
+       mutex_unlock(&dev_opp_list_lock);
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_put_supported_hw);
+
+/**
+ * dev_pm_opp_set_prop_name() - Set prop-extn name
+ * @dev: Device for which the regulator has to be set.
+ * @name: name to postfix to properties.
+ *
+ * This is required only for the V2 bindings, and it enables a platform to
+ * specify the extn to be used for certain property names. The properties to
+ * which the extension will apply are opp-microvolt and opp-microamp. OPP core
+ * should postfix the property name with -<name> while looking for them.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ */
+int dev_pm_opp_set_prop_name(struct device *dev, const char *name)
+{
+       struct device_opp *dev_opp;
+       int ret = 0;
+
+       /* Hold our list modification lock here */
+       mutex_lock(&dev_opp_list_lock);
+
+       dev_opp = _add_device_opp(dev);
+       if (!dev_opp) {
+               ret = -ENOMEM;
+               goto unlock;
+       }
+
+       /* Make sure there are no concurrent readers while updating dev_opp */
+       WARN_ON(!list_empty(&dev_opp->opp_list));
+
+       /* Do we already have a prop-name associated with dev_opp? */
+       if (dev_opp->prop_name) {
+               dev_err(dev, "%s: Already have prop-name %s\n", __func__,
+                       dev_opp->prop_name);
+               ret = -EBUSY;
+               goto err;
+       }
+
+       dev_opp->prop_name = kstrdup(name, GFP_KERNEL);
+       if (!dev_opp->prop_name) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       mutex_unlock(&dev_opp_list_lock);
+       return 0;
+
+err:
+       _remove_device_opp(dev_opp);
+unlock:
+       mutex_unlock(&dev_opp_list_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_set_prop_name);
+
+/**
+ * dev_pm_opp_put_prop_name() - Releases resources blocked for prop-name
+ * @dev: Device for which the regulator has to be set.
+ *
+ * This is required only for the V2 bindings, and is called for a matching
+ * dev_pm_opp_set_prop_name(). Until this is called, the device_opp structure
+ * will not be freed.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ */
+void dev_pm_opp_put_prop_name(struct device *dev)
+{
+       struct device_opp *dev_opp;
+
+       /* Hold our list modification lock here */
+       mutex_lock(&dev_opp_list_lock);
+
+       /* Check for existing list for 'dev' first */
+       dev_opp = _find_device_opp(dev);
+       if (IS_ERR(dev_opp)) {
+               dev_err(dev, "Failed to find dev_opp: %ld\n", PTR_ERR(dev_opp));
+               goto unlock;
+       }
+
+       /* Make sure there are no concurrent readers while updating dev_opp */
+       WARN_ON(!list_empty(&dev_opp->opp_list));
+
+       if (!dev_opp->prop_name) {
+               dev_err(dev, "%s: Doesn't have a prop-name\n", __func__);
+               goto unlock;
+       }
+
+       kfree(dev_opp->prop_name);
+       dev_opp->prop_name = NULL;
+
+       /* Try freeing device_opp if this was the last blocking resource */
+       _remove_device_opp(dev_opp);
+
+unlock:
+       mutex_unlock(&dev_opp_list_lock);
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_put_prop_name);
+
+static bool _opp_is_supported(struct device *dev, struct device_opp *dev_opp,
+                             struct device_node *np)
+{
+       unsigned int count = dev_opp->supported_hw_count;
+       u32 version;
+       int ret;
+
+       if (!dev_opp->supported_hw)
+               return true;
+
+       while (count--) {
+               ret = of_property_read_u32_index(np, "opp-supported-hw", count,
+                                                &version);
+               if (ret) {
+                       dev_warn(dev, "%s: failed to read opp-supported-hw property at index %d: %d\n",
+                                __func__, count, ret);
+                       return false;
+               }
+
+               /* Both of these are bitwise masks of the versions */
+               if (!(version & dev_opp->supported_hw[count]))
+                       return false;
+       }
+
+       return true;
+}
+
 /**
  * _opp_add_static_v2() - Allocate static OPPs (As per 'v2' DT bindings)
  * @dev:       device for which we do this operation
@@ -864,6 +1158,12 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np)
                goto free_opp;
        }
 
+       /* Check if the OPP supports hardware's hierarchy of versions or not */
+       if (!_opp_is_supported(dev, dev_opp, np)) {
+               dev_dbg(dev, "OPP not supported by hardware: %llu\n", rate);
+               goto free_opp;
+       }
+
        /*
         * Rate is defined as an unsigned long in clk API, and so casting
         * explicitly to its type. Must be fixed once rate is 64 bit
@@ -879,7 +1179,7 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np)
        if (!of_property_read_u32(np, "clock-latency-ns", &val))
                new_opp->clock_latency_ns = val;
 
-       ret = opp_parse_supplies(new_opp, dev);
+       ret = opp_parse_supplies(new_opp, dev, dev_opp);
        if (ret)
                goto free_opp;
 
@@ -889,12 +1189,14 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np)
 
        /* OPP to select on device suspend */
        if (of_property_read_bool(np, "opp-suspend")) {
-               if (dev_opp->suspend_opp)
+               if (dev_opp->suspend_opp) {
                        dev_warn(dev, "%s: Multiple suspend OPPs found (%lu %lu)\n",
                                 __func__, dev_opp->suspend_opp->rate,
                                 new_opp->rate);
-               else
+               } else {
+                       new_opp->suspend = true;
                        dev_opp->suspend_opp = new_opp;
+               }
        }
 
        if (new_opp->clock_latency_ns > dev_opp->clock_latency_ns_max)
index 7b445e88a0d559f091918be5e841f6a1380a33da..9f0c15570f64c4db0447570a6d4f1856f48d6cde 100644 (file)
@@ -214,7 +214,6 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_of_cpumask_add_table);
 /*
  * Works only for OPP v2 bindings.
  *
- * cpumask should be already set to mask of cpu_dev->id.
  * Returns -ENOENT if operating-points-v2 bindings aren't supported.
  */
 int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev, cpumask_var_t cpumask)
@@ -230,6 +229,8 @@ int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev, cpumask_var_t cpumask
                return -ENOENT;
        }
 
+       cpumask_set_cpu(cpu_dev->id, cpumask);
+
        /* OPPs are shared ? */
        if (!of_property_read_bool(np, "opp-shared"))
                goto put_cpu_node;
diff --git a/drivers/base/power/opp/debugfs.c b/drivers/base/power/opp/debugfs.c
new file mode 100644 (file)
index 0000000..ddfe477
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * Generic OPP debugfs interface
+ *
+ * Copyright (C) 2015-2016 Viresh Kumar <viresh.kumar@linaro.org>
+ *
+ * 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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/limits.h>
+
+#include "opp.h"
+
+static struct dentry *rootdir;
+
+static void opp_set_dev_name(const struct device *dev, char *name)
+{
+       if (dev->parent)
+               snprintf(name, NAME_MAX, "%s-%s", dev_name(dev->parent),
+                        dev_name(dev));
+       else
+               snprintf(name, NAME_MAX, "%s", dev_name(dev));
+}
+
+void opp_debug_remove_one(struct dev_pm_opp *opp)
+{
+       debugfs_remove_recursive(opp->dentry);
+}
+
+int opp_debug_create_one(struct dev_pm_opp *opp, struct device_opp *dev_opp)
+{
+       struct dentry *pdentry = dev_opp->dentry;
+       struct dentry *d;
+       char name[25];  /* 20 chars for 64 bit value + 5 (opp:\0) */
+
+       /* Rate is unique to each OPP, use it to give opp-name */
+       snprintf(name, sizeof(name), "opp:%lu", opp->rate);
+
+       /* Create per-opp directory */
+       d = debugfs_create_dir(name, pdentry);
+       if (!d)
+               return -ENOMEM;
+
+       if (!debugfs_create_bool("available", S_IRUGO, d, &opp->available))
+               return -ENOMEM;
+
+       if (!debugfs_create_bool("dynamic", S_IRUGO, d, &opp->dynamic))
+               return -ENOMEM;
+
+       if (!debugfs_create_bool("turbo", S_IRUGO, d, &opp->turbo))
+               return -ENOMEM;
+
+       if (!debugfs_create_bool("suspend", S_IRUGO, d, &opp->suspend))
+               return -ENOMEM;
+
+       if (!debugfs_create_ulong("rate_hz", S_IRUGO, d, &opp->rate))
+               return -ENOMEM;
+
+       if (!debugfs_create_ulong("u_volt_target", S_IRUGO, d, &opp->u_volt))
+               return -ENOMEM;
+
+       if (!debugfs_create_ulong("u_volt_min", S_IRUGO, d, &opp->u_volt_min))
+               return -ENOMEM;
+
+       if (!debugfs_create_ulong("u_volt_max", S_IRUGO, d, &opp->u_volt_max))
+               return -ENOMEM;
+
+       if (!debugfs_create_ulong("u_amp", S_IRUGO, d, &opp->u_amp))
+               return -ENOMEM;
+
+       if (!debugfs_create_ulong("clock_latency_ns", S_IRUGO, d,
+                                 &opp->clock_latency_ns))
+               return -ENOMEM;
+
+       opp->dentry = d;
+       return 0;
+}
+
+static int device_opp_debug_create_dir(struct device_list_opp *list_dev,
+                                      struct device_opp *dev_opp)
+{
+       const struct device *dev = list_dev->dev;
+       struct dentry *d;
+
+       opp_set_dev_name(dev, dev_opp->dentry_name);
+
+       /* Create device specific directory */
+       d = debugfs_create_dir(dev_opp->dentry_name, rootdir);
+       if (!d) {
+               dev_err(dev, "%s: Failed to create debugfs dir\n", __func__);
+               return -ENOMEM;
+       }
+
+       list_dev->dentry = d;
+       dev_opp->dentry = d;
+
+       return 0;
+}
+
+static int device_opp_debug_create_link(struct device_list_opp *list_dev,
+                                       struct device_opp *dev_opp)
+{
+       const struct device *dev = list_dev->dev;
+       char name[NAME_MAX];
+       struct dentry *d;
+
+       opp_set_dev_name(list_dev->dev, name);
+
+       /* Create device specific directory link */
+       d = debugfs_create_symlink(name, rootdir, dev_opp->dentry_name);
+       if (!d) {
+               dev_err(dev, "%s: Failed to create link\n", __func__);
+               return -ENOMEM;
+       }
+
+       list_dev->dentry = d;
+
+       return 0;
+}
+
+/**
+ * opp_debug_register - add a device opp node to the debugfs 'opp' directory
+ * @list_dev: list-dev pointer for device
+ * @dev_opp: the device-opp being added
+ *
+ * Dynamically adds device specific directory in debugfs 'opp' directory. If the
+ * device-opp is shared with other devices, then links will be created for all
+ * devices except the first.
+ *
+ * Return: 0 on success, otherwise negative error.
+ */
+int opp_debug_register(struct device_list_opp *list_dev,
+                      struct device_opp *dev_opp)
+{
+       if (!rootdir) {
+               pr_debug("%s: Uninitialized rootdir\n", __func__);
+               return -EINVAL;
+       }
+
+       if (dev_opp->dentry)
+               return device_opp_debug_create_link(list_dev, dev_opp);
+
+       return device_opp_debug_create_dir(list_dev, dev_opp);
+}
+
+static void opp_migrate_dentry(struct device_list_opp *list_dev,
+                              struct device_opp *dev_opp)
+{
+       struct device_list_opp *new_dev;
+       const struct device *dev;
+       struct dentry *dentry;
+
+       /* Look for next list-dev */
+       list_for_each_entry(new_dev, &dev_opp->dev_list, node)
+               if (new_dev != list_dev)
+                       break;
+
+       /* new_dev is guaranteed to be valid here */
+       dev = new_dev->dev;
+       debugfs_remove_recursive(new_dev->dentry);
+
+       opp_set_dev_name(dev, dev_opp->dentry_name);
+
+       dentry = debugfs_rename(rootdir, list_dev->dentry, rootdir,
+                               dev_opp->dentry_name);
+       if (!dentry) {
+               dev_err(dev, "%s: Failed to rename link from: %s to %s\n",
+                       __func__, dev_name(list_dev->dev), dev_name(dev));
+               return;
+       }
+
+       new_dev->dentry = dentry;
+       dev_opp->dentry = dentry;
+}
+
+/**
+ * opp_debug_unregister - remove a device opp node from debugfs opp directory
+ * @list_dev: list-dev pointer for device
+ * @dev_opp: the device-opp being removed
+ *
+ * Dynamically removes device specific directory from debugfs 'opp' directory.
+ */
+void opp_debug_unregister(struct device_list_opp *list_dev,
+                         struct device_opp *dev_opp)
+{
+       if (list_dev->dentry == dev_opp->dentry) {
+               /* Move the real dentry object under another device */
+               if (!list_is_singular(&dev_opp->dev_list)) {
+                       opp_migrate_dentry(list_dev, dev_opp);
+                       goto out;
+               }
+               dev_opp->dentry = NULL;
+       }
+
+       debugfs_remove_recursive(list_dev->dentry);
+
+out:
+       list_dev->dentry = NULL;
+}
+
+static int __init opp_debug_init(void)
+{
+       /* Create /sys/kernel/debug/opp directory */
+       rootdir = debugfs_create_dir("opp", NULL);
+       if (!rootdir) {
+               pr_err("%s: Failed to create root directory\n", __func__);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+core_initcall(opp_debug_init);
index 7366b2aa8997897f89890cf99a4990d83e61a5a6..690638ef36ee534c1ab9a57d8c4c7ee840f78a51 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/device.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
+#include <linux/limits.h>
 #include <linux/pm_opp.h>
 #include <linux/rculist.h>
 #include <linux/rcupdate.h>
@@ -50,9 +51,10 @@ extern struct mutex dev_opp_list_lock;
  *             are protected by the dev_opp_list_lock for integrity.
  *             IMPORTANT: the opp nodes should be maintained in increasing
  *             order.
- * @dynamic:   not-created from static DT entries.
  * @available: true/false - marks if this OPP as available or not
+ * @dynamic:   not-created from static DT entries.
  * @turbo:     true if turbo (boost) OPP
+ * @suspend:   true if suspend OPP
  * @rate:      Frequency in hertz
  * @u_volt:    Target voltage in microvolts corresponding to this OPP
  * @u_volt_min:        Minimum voltage in microvolts corresponding to this OPP
@@ -63,6 +65,7 @@ extern struct mutex dev_opp_list_lock;
  * @dev_opp:   points back to the device_opp struct this opp belongs to
  * @rcu_head:  RCU callback head used for deferred freeing
  * @np:                OPP's device node.
+ * @dentry:    debugfs dentry pointer (per opp)
  *
  * This structure stores the OPP information for a given device.
  */
@@ -72,6 +75,7 @@ struct dev_pm_opp {
        bool available;
        bool dynamic;
        bool turbo;
+       bool suspend;
        unsigned long rate;
 
        unsigned long u_volt;
@@ -84,6 +88,10 @@ struct dev_pm_opp {
        struct rcu_head rcu_head;
 
        struct device_node *np;
+
+#ifdef CONFIG_DEBUG_FS
+       struct dentry *dentry;
+#endif
 };
 
 /**
@@ -91,6 +99,7 @@ struct dev_pm_opp {
  * @node:      list node
  * @dev:       device to which the struct object belongs
  * @rcu_head:  RCU callback head used for deferred freeing
+ * @dentry:    debugfs dentry pointer (per device)
  *
  * This is an internal data structure maintaining the list of devices that are
  * managed by 'struct device_opp'.
@@ -99,6 +108,10 @@ struct device_list_opp {
        struct list_head node;
        const struct device *dev;
        struct rcu_head rcu_head;
+
+#ifdef CONFIG_DEBUG_FS
+       struct dentry *dentry;
+#endif
 };
 
 /**
@@ -113,7 +126,14 @@ struct device_list_opp {
  * @dev_list:  list of devices that share these OPPs
  * @opp_list:  list of opps
  * @np:                struct device_node pointer for opp's DT node.
+ * @clock_latency_ns_max: Max clock latency in nanoseconds.
  * @shared_opp: OPP is shared between multiple devices.
+ * @suspend_opp: Pointer to OPP to be used during device suspend.
+ * @supported_hw: Array of version number to support.
+ * @supported_hw_count: Number of elements in supported_hw array.
+ * @prop_name: A name to postfix to many DT properties, while parsing them.
+ * @dentry:    debugfs dentry pointer of the real device directory (not links).
+ * @dentry_name: Name of the real dentry.
  *
  * This is an internal data structure maintaining the link to opps attached to
  * a device. This structure is not meant to be shared to users as it is
@@ -135,6 +155,15 @@ struct device_opp {
        unsigned long clock_latency_ns_max;
        bool shared_opp;
        struct dev_pm_opp *suspend_opp;
+
+       unsigned int *supported_hw;
+       unsigned int supported_hw_count;
+       const char *prop_name;
+
+#ifdef CONFIG_DEBUG_FS
+       struct dentry *dentry;
+       char dentry_name[NAME_MAX];
+#endif
 };
 
 /* Routines internal to opp core */
@@ -143,4 +172,26 @@ struct device_list_opp *_add_list_dev(const struct device *dev,
                                      struct device_opp *dev_opp);
 struct device_node *_of_get_opp_desc_node(struct device *dev);
 
+#ifdef CONFIG_DEBUG_FS
+void opp_debug_remove_one(struct dev_pm_opp *opp);
+int opp_debug_create_one(struct dev_pm_opp *opp, struct device_opp *dev_opp);
+int opp_debug_register(struct device_list_opp *list_dev,
+                      struct device_opp *dev_opp);
+void opp_debug_unregister(struct device_list_opp *list_dev,
+                         struct device_opp *dev_opp);
+#else
+static inline void opp_debug_remove_one(struct dev_pm_opp *opp) {}
+
+static inline int opp_debug_create_one(struct dev_pm_opp *opp,
+                                      struct device_opp *dev_opp)
+{ return 0; }
+static inline int opp_debug_register(struct device_list_opp *list_dev,
+                                    struct device_opp *dev_opp)
+{ return 0; }
+
+static inline void opp_debug_unregister(struct device_list_opp *list_dev,
+                                       struct device_opp *dev_opp)
+{ }
+#endif         /* DEBUG_FS */
+
 #endif         /* __DRIVER_OPP_H__ */
index 998fa6b230844391b023b5ba8d4f0a22f9c645b0..8b06193d4a5e9f1aa42cfae570a5499be86ee4a5 100644 (file)
@@ -18,6 +18,7 @@ static inline void pm_runtime_early_init(struct device *dev)
 }
 
 extern void pm_runtime_init(struct device *dev);
+extern void pm_runtime_reinit(struct device *dev);
 extern void pm_runtime_remove(struct device *dev);
 
 struct wake_irq {
@@ -84,6 +85,7 @@ static inline void pm_runtime_early_init(struct device *dev)
 }
 
 static inline void pm_runtime_init(struct device *dev) {}
+static inline void pm_runtime_reinit(struct device *dev) {}
 static inline void pm_runtime_remove(struct device *dev) {}
 
 static inline int dpm_sysfs_add(struct device *dev) { return 0; }
index e1a10a03df8ec0f92cb43813e881e5d7bb0237c5..4c7055009bd6ac88477458cf3fc551a966d2ad37 100644 (file)
@@ -965,6 +965,30 @@ int __pm_runtime_resume(struct device *dev, int rpmflags)
 }
 EXPORT_SYMBOL_GPL(__pm_runtime_resume);
 
+/**
+ * pm_runtime_get_if_in_use - Conditionally bump up the device's usage counter.
+ * @dev: Device to handle.
+ *
+ * Return -EINVAL if runtime PM is disabled for the device.
+ *
+ * If that's not the case and if the device's runtime PM status is RPM_ACTIVE
+ * and the runtime PM usage counter is nonzero, increment the counter and
+ * return 1.  Otherwise return 0 without changing the counter.
+ */
+int pm_runtime_get_if_in_use(struct device *dev)
+{
+       unsigned long flags;
+       int retval;
+
+       spin_lock_irqsave(&dev->power.lock, flags);
+       retval = dev->power.disable_depth > 0 ? -EINVAL :
+               dev->power.runtime_status == RPM_ACTIVE
+                       && atomic_inc_not_zero(&dev->power.usage_count);
+       spin_unlock_irqrestore(&dev->power.lock, flags);
+       return retval;
+}
+EXPORT_SYMBOL_GPL(pm_runtime_get_if_in_use);
+
 /**
  * __pm_runtime_set_status - Set runtime PM status of a device.
  * @dev: Device to handle.
@@ -1389,6 +1413,25 @@ void pm_runtime_init(struct device *dev)
        init_waitqueue_head(&dev->power.wait_queue);
 }
 
+/**
+ * pm_runtime_reinit - Re-initialize runtime PM fields in given device object.
+ * @dev: Device object to re-initialize.
+ */
+void pm_runtime_reinit(struct device *dev)
+{
+       if (!pm_runtime_enabled(dev)) {
+               if (dev->power.runtime_status == RPM_ACTIVE)
+                       pm_runtime_set_suspended(dev);
+               if (dev->power.irq_safe) {
+                       spin_lock_irq(&dev->power.lock);
+                       dev->power.irq_safe = 0;
+                       spin_unlock_irq(&dev->power.lock);
+                       if (dev->parent)
+                               pm_runtime_put(dev->parent);
+               }
+       }
+}
+
 /**
  * pm_runtime_remove - Prepare for removing a device from device hierarchy.
  * @dev: Device object being removed from device hierarchy.
@@ -1396,12 +1439,7 @@ void pm_runtime_init(struct device *dev)
 void pm_runtime_remove(struct device *dev)
 {
        __pm_runtime_disable(dev, false);
-
-       /* Change the status back to 'suspended' to match the initial status. */
-       if (dev->power.runtime_status == RPM_ACTIVE)
-               pm_runtime_set_suspended(dev);
-       if (dev->power.irq_safe && dev->parent)
-               pm_runtime_put(dev->parent);
+       pm_runtime_reinit(dev);
 }
 
 /**
index 1325ff225cc4a5b37a7c0b3fe0b3d7946c37811e..c359351d50f1c99e9758b74ea84d97e76b402b0f 100644 (file)
 #include <linux/etherdevice.h>
 #include <linux/phy.h>
 
-/**
- * device_add_property_set - Add a collection of properties to a device object.
- * @dev: Device to add properties to.
- * @pset: Collection of properties to add.
- *
- * Associate a collection of device properties represented by @pset with @dev
- * as its secondary firmware node.
- */
-void device_add_property_set(struct device *dev, struct property_set *pset)
-{
-       if (!pset)
-               return;
-
-       pset->fwnode.type = FWNODE_PDATA;
-       set_secondary_fwnode(dev, &pset->fwnode);
-}
-EXPORT_SYMBOL_GPL(device_add_property_set);
-
-static inline bool is_pset(struct fwnode_handle *fwnode)
+static inline bool is_pset_node(struct fwnode_handle *fwnode)
 {
        return fwnode && fwnode->type == FWNODE_PDATA;
 }
 
-static inline struct property_set *to_pset(struct fwnode_handle *fwnode)
+static inline struct property_set *to_pset_node(struct fwnode_handle *fwnode)
 {
-       return is_pset(fwnode) ?
+       return is_pset_node(fwnode) ?
                container_of(fwnode, struct property_set, fwnode) : NULL;
 }
 
@@ -63,45 +45,135 @@ static struct property_entry *pset_prop_get(struct property_set *pset,
        return NULL;
 }
 
-static int pset_prop_read_array(struct property_set *pset, const char *name,
-                               enum dev_prop_type type, void *val, size_t nval)
+static void *pset_prop_find(struct property_set *pset, const char *propname,
+                           size_t length)
 {
        struct property_entry *prop;
-       unsigned int item_size;
+       void *pointer;
 
-       prop = pset_prop_get(pset, name);
+       prop = pset_prop_get(pset, propname);
        if (!prop)
-               return -ENODATA;
+               return ERR_PTR(-EINVAL);
+       if (prop->is_array)
+               pointer = prop->pointer.raw_data;
+       else
+               pointer = &prop->value.raw_data;
+       if (!pointer)
+               return ERR_PTR(-ENODATA);
+       if (length > prop->length)
+               return ERR_PTR(-EOVERFLOW);
+       return pointer;
+}
+
+static int pset_prop_read_u8_array(struct property_set *pset,
+                                  const char *propname,
+                                  u8 *values, size_t nval)
+{
+       void *pointer;
+       size_t length = nval * sizeof(*values);
+
+       pointer = pset_prop_find(pset, propname, length);
+       if (IS_ERR(pointer))
+               return PTR_ERR(pointer);
+
+       memcpy(values, pointer, length);
+       return 0;
+}
+
+static int pset_prop_read_u16_array(struct property_set *pset,
+                                   const char *propname,
+                                   u16 *values, size_t nval)
+{
+       void *pointer;
+       size_t length = nval * sizeof(*values);
+
+       pointer = pset_prop_find(pset, propname, length);
+       if (IS_ERR(pointer))
+               return PTR_ERR(pointer);
+
+       memcpy(values, pointer, length);
+       return 0;
+}
+
+static int pset_prop_read_u32_array(struct property_set *pset,
+                                   const char *propname,
+                                   u32 *values, size_t nval)
+{
+       void *pointer;
+       size_t length = nval * sizeof(*values);
+
+       pointer = pset_prop_find(pset, propname, length);
+       if (IS_ERR(pointer))
+               return PTR_ERR(pointer);
+
+       memcpy(values, pointer, length);
+       return 0;
+}
+
+static int pset_prop_read_u64_array(struct property_set *pset,
+                                   const char *propname,
+                                   u64 *values, size_t nval)
+{
+       void *pointer;
+       size_t length = nval * sizeof(*values);
+
+       pointer = pset_prop_find(pset, propname, length);
+       if (IS_ERR(pointer))
+               return PTR_ERR(pointer);
+
+       memcpy(values, pointer, length);
+       return 0;
+}
+
+static int pset_prop_count_elems_of_size(struct property_set *pset,
+                                        const char *propname, size_t length)
+{
+       struct property_entry *prop;
+
+       prop = pset_prop_get(pset, propname);
+       if (!prop)
+               return -EINVAL;
+
+       return prop->length / length;
+}
+
+static int pset_prop_read_string_array(struct property_set *pset,
+                                      const char *propname,
+                                      const char **strings, size_t nval)
+{
+       void *pointer;
+       size_t length = nval * sizeof(*strings);
+
+       pointer = pset_prop_find(pset, propname, length);
+       if (IS_ERR(pointer))
+               return PTR_ERR(pointer);
+
+       memcpy(strings, pointer, length);
+       return 0;
+}
+
+static int pset_prop_read_string(struct property_set *pset,
+                                const char *propname, const char **strings)
+{
+       struct property_entry *prop;
+       const char **pointer;
 
-       if (prop->type != type)
-               return -EPROTO;
-
-       if (!val)
-               return prop->nval;
-
-       if (prop->nval < nval)
-               return -EOVERFLOW;
-
-       switch (type) {
-       case DEV_PROP_U8:
-               item_size = sizeof(u8);
-               break;
-       case DEV_PROP_U16:
-               item_size = sizeof(u16);
-               break;
-       case DEV_PROP_U32:
-               item_size = sizeof(u32);
-               break;
-       case DEV_PROP_U64:
-               item_size = sizeof(u64);
-               break;
-       case DEV_PROP_STRING:
-               item_size = sizeof(const char *);
-               break;
-       default:
+       prop = pset_prop_get(pset, propname);
+       if (!prop)
                return -EINVAL;
+       if (!prop->is_string)
+               return -EILSEQ;
+       if (prop->is_array) {
+               pointer = prop->pointer.str;
+               if (!pointer)
+                       return -ENODATA;
+       } else {
+               pointer = &prop->value.str;
+               if (*pointer && strnlen(*pointer, prop->length) >= prop->length)
+                       return -EILSEQ;
        }
-       memcpy(val, prop->value.raw_data, nval * item_size);
+
+       *strings = *pointer;
        return 0;
 }
 
@@ -124,6 +196,18 @@ bool device_property_present(struct device *dev, const char *propname)
 }
 EXPORT_SYMBOL_GPL(device_property_present);
 
+static bool __fwnode_property_present(struct fwnode_handle *fwnode,
+                                     const char *propname)
+{
+       if (is_of_node(fwnode))
+               return of_property_read_bool(to_of_node(fwnode), propname);
+       else if (is_acpi_node(fwnode))
+               return !acpi_node_prop_get(fwnode, propname, NULL);
+       else if (is_pset_node(fwnode))
+               return !!pset_prop_get(to_pset_node(fwnode), propname);
+       return false;
+}
+
 /**
  * fwnode_property_present - check if a property of a firmware node is present
  * @fwnode: Firmware node whose property to check
@@ -131,12 +215,12 @@ EXPORT_SYMBOL_GPL(device_property_present);
  */
 bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname)
 {
-       if (is_of_node(fwnode))
-               return of_property_read_bool(to_of_node(fwnode), propname);
-       else if (is_acpi_node(fwnode))
-               return !acpi_node_prop_get(fwnode, propname, NULL);
+       bool ret;
 
-       return !!pset_prop_get(to_pset(fwnode), propname);
+       ret = __fwnode_property_present(fwnode, propname);
+       if (ret == false && fwnode && fwnode->secondary)
+               ret = __fwnode_property_present(fwnode->secondary, propname);
+       return ret;
 }
 EXPORT_SYMBOL_GPL(fwnode_property_present);
 
@@ -309,25 +393,40 @@ int device_property_match_string(struct device *dev, const char *propname,
 }
 EXPORT_SYMBOL_GPL(device_property_match_string);
 
-#define OF_DEV_PROP_READ_ARRAY(node, propname, type, val, nval) \
-       (val) ? of_property_read_##type##_array((node), (propname), (val), (nval)) \
+#define OF_DEV_PROP_READ_ARRAY(node, propname, type, val, nval)                                \
+       (val) ? of_property_read_##type##_array((node), (propname), (val), (nval))      \
              : of_property_count_elems_of_size((node), (propname), sizeof(type))
 
-#define FWNODE_PROP_READ_ARRAY(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_) \
-({ \
-       int _ret_; \
-       if (is_of_node(_fwnode_)) \
-               _ret_ = OF_DEV_PROP_READ_ARRAY(to_of_node(_fwnode_), _propname_, \
-                                              _type_, _val_, _nval_); \
-       else if (is_acpi_node(_fwnode_)) \
-               _ret_ = acpi_node_prop_read(_fwnode_, _propname_, _proptype_, \
-                                           _val_, _nval_); \
-       else if (is_pset(_fwnode_)) \
-               _ret_ = pset_prop_read_array(to_pset(_fwnode_), _propname_, \
-                                            _proptype_, _val_, _nval_); \
-       else \
-               _ret_ = -ENXIO; \
-       _ret_; \
+#define PSET_PROP_READ_ARRAY(node, propname, type, val, nval)                          \
+       (val) ? pset_prop_read_##type##_array((node), (propname), (val), (nval))        \
+             : pset_prop_count_elems_of_size((node), (propname), sizeof(type))
+
+#define FWNODE_PROP_READ(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_)      \
+({                                                                                     \
+       int _ret_;                                                                      \
+       if (is_of_node(_fwnode_))                                                       \
+               _ret_ = OF_DEV_PROP_READ_ARRAY(to_of_node(_fwnode_), _propname_,        \
+                                              _type_, _val_, _nval_);                  \
+       else if (is_acpi_node(_fwnode_))                                                \
+               _ret_ = acpi_node_prop_read(_fwnode_, _propname_, _proptype_,           \
+                                           _val_, _nval_);                             \
+       else if (is_pset_node(_fwnode_))                                                \
+               _ret_ = PSET_PROP_READ_ARRAY(to_pset_node(_fwnode_), _propname_,        \
+                                            _type_, _val_, _nval_);                    \
+       else                                                                            \
+               _ret_ = -ENXIO;                                                         \
+       _ret_;                                                                          \
+})
+
+#define FWNODE_PROP_READ_ARRAY(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_)        \
+({                                                                                     \
+       int _ret_;                                                                      \
+       _ret_ = FWNODE_PROP_READ(_fwnode_, _propname_, _type_, _proptype_,              \
+                                _val_, _nval_);                                        \
+       if (_ret_ == -EINVAL && _fwnode_ && _fwnode_->secondary)                        \
+               _ret_ = FWNODE_PROP_READ(_fwnode_->secondary, _propname_, _type_,       \
+                               _proptype_, _val_, _nval_);                             \
+       _ret_;                                                                          \
 })
 
 /**
@@ -434,6 +533,41 @@ int fwnode_property_read_u64_array(struct fwnode_handle *fwnode,
 }
 EXPORT_SYMBOL_GPL(fwnode_property_read_u64_array);
 
+static int __fwnode_property_read_string_array(struct fwnode_handle *fwnode,
+                                              const char *propname,
+                                              const char **val, size_t nval)
+{
+       if (is_of_node(fwnode))
+               return val ?
+                       of_property_read_string_array(to_of_node(fwnode),
+                                                     propname, val, nval) :
+                       of_property_count_strings(to_of_node(fwnode), propname);
+       else if (is_acpi_node(fwnode))
+               return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
+                                          val, nval);
+       else if (is_pset_node(fwnode))
+               return val ?
+                       pset_prop_read_string_array(to_pset_node(fwnode),
+                                                   propname, val, nval) :
+                       pset_prop_count_elems_of_size(to_pset_node(fwnode),
+                                                     propname,
+                                                     sizeof(const char *));
+       return -ENXIO;
+}
+
+static int __fwnode_property_read_string(struct fwnode_handle *fwnode,
+                                        const char *propname, const char **val)
+{
+       if (is_of_node(fwnode))
+               return of_property_read_string(to_of_node(fwnode), propname, val);
+       else if (is_acpi_node(fwnode))
+               return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
+                                          val, 1);
+       else if (is_pset_node(fwnode))
+               return pset_prop_read_string(to_pset_node(fwnode), propname, val);
+       return -ENXIO;
+}
+
 /**
  * fwnode_property_read_string_array - return string array property of a node
  * @fwnode: Firmware node to get the property of
@@ -456,18 +590,13 @@ int fwnode_property_read_string_array(struct fwnode_handle *fwnode,
                                      const char *propname, const char **val,
                                      size_t nval)
 {
-       if (is_of_node(fwnode))
-               return val ?
-                       of_property_read_string_array(to_of_node(fwnode),
-                                                     propname, val, nval) :
-                       of_property_count_strings(to_of_node(fwnode), propname);
-       else if (is_acpi_node(fwnode))
-               return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
-                                          val, nval);
-       else if (is_pset(fwnode))
-               return pset_prop_read_array(to_pset(fwnode), propname,
-                                           DEV_PROP_STRING, val, nval);
-       return -ENXIO;
+       int ret;
+
+       ret = __fwnode_property_read_string_array(fwnode, propname, val, nval);
+       if (ret == -EINVAL && fwnode && fwnode->secondary)
+               ret = __fwnode_property_read_string_array(fwnode->secondary,
+                                                         propname, val, nval);
+       return ret;
 }
 EXPORT_SYMBOL_GPL(fwnode_property_read_string_array);
 
@@ -489,14 +618,13 @@ EXPORT_SYMBOL_GPL(fwnode_property_read_string_array);
 int fwnode_property_read_string(struct fwnode_handle *fwnode,
                                const char *propname, const char **val)
 {
-       if (is_of_node(fwnode))
-               return of_property_read_string(to_of_node(fwnode), propname, val);
-       else if (is_acpi_node(fwnode))
-               return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
-                                          val, 1);
+       int ret;
 
-       return pset_prop_read_array(to_pset(fwnode), propname,
-                                   DEV_PROP_STRING, val, 1);
+       ret = __fwnode_property_read_string(fwnode, propname, val);
+       if (ret == -EINVAL && fwnode && fwnode->secondary)
+               ret = __fwnode_property_read_string(fwnode->secondary,
+                                                   propname, val);
+       return ret;
 }
 EXPORT_SYMBOL_GPL(fwnode_property_read_string);
 
@@ -525,6 +653,9 @@ int fwnode_property_match_string(struct fwnode_handle *fwnode,
        if (nval < 0)
                return nval;
 
+       if (nval == 0)
+               return -ENODATA;
+
        values = kcalloc(nval, sizeof(*values), GFP_KERNEL);
        if (!values)
                return -ENOMEM;
@@ -546,6 +677,182 @@ out:
 }
 EXPORT_SYMBOL_GPL(fwnode_property_match_string);
 
+/**
+ * pset_free_set - releases memory allocated for copied property set
+ * @pset: Property set to release
+ *
+ * Function takes previously copied property set and releases all the
+ * memory allocated to it.
+ */
+static void pset_free_set(struct property_set *pset)
+{
+       const struct property_entry *prop;
+       size_t i, nval;
+
+       if (!pset)
+               return;
+
+       for (prop = pset->properties; prop->name; prop++) {
+               if (prop->is_array) {
+                       if (prop->is_string && prop->pointer.str) {
+                               nval = prop->length / sizeof(const char *);
+                               for (i = 0; i < nval; i++)
+                                       kfree(prop->pointer.str[i]);
+                       }
+                       kfree(prop->pointer.raw_data);
+               } else if (prop->is_string) {
+                       kfree(prop->value.str);
+               }
+               kfree(prop->name);
+       }
+
+       kfree(pset->properties);
+       kfree(pset);
+}
+
+static int pset_copy_entry(struct property_entry *dst,
+                          const struct property_entry *src)
+{
+       const char **d, **s;
+       size_t i, nval;
+
+       dst->name = kstrdup(src->name, GFP_KERNEL);
+       if (!dst->name)
+               return -ENOMEM;
+
+       if (src->is_array) {
+               if (!src->length)
+                       return -ENODATA;
+
+               if (src->is_string) {
+                       nval = src->length / sizeof(const char *);
+                       dst->pointer.str = kcalloc(nval, sizeof(const char *),
+                                                  GFP_KERNEL);
+                       if (!dst->pointer.str)
+                               return -ENOMEM;
+
+                       d = dst->pointer.str;
+                       s = src->pointer.str;
+                       for (i = 0; i < nval; i++) {
+                               d[i] = kstrdup(s[i], GFP_KERNEL);
+                               if (!d[i] && s[i])
+                                       return -ENOMEM;
+                       }
+               } else {
+                       dst->pointer.raw_data = kmemdup(src->pointer.raw_data,
+                                                       src->length, GFP_KERNEL);
+                       if (!dst->pointer.raw_data)
+                               return -ENOMEM;
+               }
+       } else if (src->is_string) {
+               dst->value.str = kstrdup(src->value.str, GFP_KERNEL);
+               if (!dst->value.str && src->value.str)
+                       return -ENOMEM;
+       } else {
+               dst->value.raw_data = src->value.raw_data;
+       }
+
+       dst->length = src->length;
+       dst->is_array = src->is_array;
+       dst->is_string = src->is_string;
+
+       return 0;
+}
+
+/**
+ * pset_copy_set - copies property set
+ * @pset: Property set to copy
+ *
+ * This function takes a deep copy of the given property set and returns
+ * pointer to the copy. Call device_free_property_set() to free resources
+ * allocated in this function.
+ *
+ * Return: Pointer to the new property set or error pointer.
+ */
+static struct property_set *pset_copy_set(const struct property_set *pset)
+{
+       const struct property_entry *entry;
+       struct property_set *p;
+       size_t i, n = 0;
+
+       p = kzalloc(sizeof(*p), GFP_KERNEL);
+       if (!p)
+               return ERR_PTR(-ENOMEM);
+
+       while (pset->properties[n].name)
+               n++;
+
+       p->properties = kcalloc(n + 1, sizeof(*entry), GFP_KERNEL);
+       if (!p->properties) {
+               kfree(p);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       for (i = 0; i < n; i++) {
+               int ret = pset_copy_entry(&p->properties[i],
+                                         &pset->properties[i]);
+               if (ret) {
+                       pset_free_set(p);
+                       return ERR_PTR(ret);
+               }
+       }
+
+       return p;
+}
+
+/**
+ * device_remove_property_set - Remove properties from a device object.
+ * @dev: Device whose properties to remove.
+ *
+ * The function removes properties previously associated to the device
+ * secondary firmware node with device_add_property_set(). Memory allocated
+ * to the properties will also be released.
+ */
+void device_remove_property_set(struct device *dev)
+{
+       struct fwnode_handle *fwnode;
+
+       fwnode = dev_fwnode(dev);
+       if (!fwnode)
+               return;
+       /*
+        * Pick either primary or secondary node depending which one holds
+        * the pset. If there is no real firmware node (ACPI/DT) primary
+        * will hold the pset.
+        */
+       if (!is_pset_node(fwnode))
+               fwnode = fwnode->secondary;
+       if (!IS_ERR(fwnode) && is_pset_node(fwnode))
+               pset_free_set(to_pset_node(fwnode));
+       set_secondary_fwnode(dev, NULL);
+}
+EXPORT_SYMBOL_GPL(device_remove_property_set);
+
+/**
+ * device_add_property_set - Add a collection of properties to a device object.
+ * @dev: Device to add properties to.
+ * @pset: Collection of properties to add.
+ *
+ * Associate a collection of device properties represented by @pset with @dev
+ * as its secondary firmware node. The function takes a copy of @pset.
+ */
+int device_add_property_set(struct device *dev, const struct property_set *pset)
+{
+       struct property_set *p;
+
+       if (!pset)
+               return -EINVAL;
+
+       p = pset_copy_set(pset);
+       if (IS_ERR(p))
+               return PTR_ERR(p);
+
+       p->fwnode.type = FWNODE_PDATA;
+       set_secondary_fwnode(dev, &p->fwnode);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(device_add_property_set);
+
 /**
  * device_get_next_child_node - Return the next child node handle for a device
  * @dev: Device to find the next child node for.
index b1f8a73e5a943e8fc692dfcba7f28d1e08dba4f2..0031069b64c95aa93f2d1d0696ee8a9c63cc59ef 100644 (file)
@@ -6,6 +6,8 @@
 config ARM_BIG_LITTLE_CPUFREQ
        tristate "Generic ARM big LITTLE CPUfreq driver"
        depends on (ARM_CPU_TOPOLOGY || ARM64) && HAVE_CLK
+       # if CPU_THERMAL is on and THERMAL=m, ARM_BIT_LITTLE_CPUFREQ cannot be =y
+       depends on !CPU_THERMAL || THERMAL
        select PM_OPP
        help
          This enables the Generic CPUfreq driver for ARM big.LITTLE platforms.
@@ -217,6 +219,16 @@ config ARM_SPEAR_CPUFREQ
        help
          This adds the CPUFreq driver support for SPEAr SOCs.
 
+config ARM_STI_CPUFREQ
+       tristate "STi CPUFreq support"
+       depends on SOC_STIH407
+       help
+         This driver uses the generic OPP framework to match the running
+         platform with a predefined set of suitable values.  If not provided
+         we will fall-back so safe-values contained in Device Tree.  Enable
+         this config option if you wish to add CPUFreq support for STi based
+         SoCs.
+
 config ARM_TEGRA20_CPUFREQ
        bool "Tegra20 CPUFreq support"
        depends on ARCH_TEGRA
index c0af1a1281c89134269445f9330d4d449c37135e..9e63fb1b09f815fa70e1c4d908707ba39989f8fa 100644 (file)
@@ -73,6 +73,7 @@ obj-$(CONFIG_ARM_SA1100_CPUFREQ)      += sa1100-cpufreq.o
 obj-$(CONFIG_ARM_SA1110_CPUFREQ)       += sa1110-cpufreq.o
 obj-$(CONFIG_ARM_SCPI_CPUFREQ)         += scpi-cpufreq.o
 obj-$(CONFIG_ARM_SPEAR_CPUFREQ)                += spear-cpufreq.o
+obj-$(CONFIG_ARM_STI_CPUFREQ)          += sti-cpufreq.o
 obj-$(CONFIG_ARM_TEGRA20_CPUFREQ)      += tegra20-cpufreq.o
 obj-$(CONFIG_ARM_TEGRA124_CPUFREQ)     += tegra124-cpufreq.o
 obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ) += vexpress-spc-cpufreq.o
index cec1ee2d2f744b968fe653f47dc5067dfe4dccb1..51eef87bbc374f85826b16b27141f024aefd9bbe 100644 (file)
@@ -135,7 +135,7 @@ static void boost_set_msrs(bool enable, const struct cpumask *cpumask)
        wrmsr_on_cpus(cpumask, msr_addr, msrs);
 }
 
-static int _store_boost(int val)
+static int set_boost(int val)
 {
        get_online_cpus();
        boost_set_msrs(val, cpu_online_mask);
@@ -158,29 +158,24 @@ static ssize_t show_freqdomain_cpus(struct cpufreq_policy *policy, char *buf)
 cpufreq_freq_attr_ro(freqdomain_cpus);
 
 #ifdef CONFIG_X86_ACPI_CPUFREQ_CPB
-static ssize_t store_boost(const char *buf, size_t count)
+static ssize_t store_cpb(struct cpufreq_policy *policy, const char *buf,
+                        size_t count)
 {
        int ret;
-       unsigned long val = 0;
+       unsigned int val = 0;
 
-       if (!acpi_cpufreq_driver.boost_supported)
+       if (!acpi_cpufreq_driver.set_boost)
                return -EINVAL;
 
-       ret = kstrtoul(buf, 10, &val);
-       if (ret || (val > 1))
+       ret = kstrtouint(buf, 10, &val);
+       if (ret || val > 1)
                return -EINVAL;
 
-       _store_boost((int) val);
+       set_boost(val);
 
        return count;
 }
 
-static ssize_t store_cpb(struct cpufreq_policy *policy, const char *buf,
-                        size_t count)
-{
-       return store_boost(buf, count);
-}
-
 static ssize_t show_cpb(struct cpufreq_policy *policy, char *buf)
 {
        return sprintf(buf, "%u\n", acpi_cpufreq_driver.boost_enabled);
@@ -905,7 +900,6 @@ static struct cpufreq_driver acpi_cpufreq_driver = {
        .resume         = acpi_cpufreq_resume,
        .name           = "acpi-cpufreq",
        .attr           = acpi_cpufreq_attr,
-       .set_boost      = _store_boost,
 };
 
 static void __init acpi_cpufreq_boost_init(void)
@@ -916,7 +910,7 @@ static void __init acpi_cpufreq_boost_init(void)
                if (!msrs)
                        return;
 
-               acpi_cpufreq_driver.boost_supported = true;
+               acpi_cpufreq_driver.set_boost = set_boost;
                acpi_cpufreq_driver.boost_enabled = boost_state(0);
 
                cpu_notifier_register_begin();
index c5d256caa664a63731e0cb7db6f5b00e31c750d8..c251247ae6613e860164627d8c8161f2b0d0cfe5 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/cpu.h>
 #include <linux/cpufreq.h>
 #include <linux/cpumask.h>
+#include <linux/cpu_cooling.h>
 #include <linux/export.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
@@ -55,6 +56,7 @@ static bool bL_switching_enabled;
 #define ACTUAL_FREQ(cluster, freq)  ((cluster == A7_CLUSTER) ? freq << 1 : freq)
 #define VIRT_FREQ(cluster, freq)    ((cluster == A7_CLUSTER) ? freq >> 1 : freq)
 
+static struct thermal_cooling_device *cdev[MAX_CLUSTERS];
 static struct cpufreq_arm_bL_ops *arm_bL_ops;
 static struct clk *clk[MAX_CLUSTERS];
 static struct cpufreq_frequency_table *freq_table[MAX_CLUSTERS + 1];
@@ -493,6 +495,12 @@ static int bL_cpufreq_init(struct cpufreq_policy *policy)
 static int bL_cpufreq_exit(struct cpufreq_policy *policy)
 {
        struct device *cpu_dev;
+       int cur_cluster = cpu_to_cluster(policy->cpu);
+
+       if (cur_cluster < MAX_CLUSTERS) {
+               cpufreq_cooling_unregister(cdev[cur_cluster]);
+               cdev[cur_cluster] = NULL;
+       }
 
        cpu_dev = get_cpu_device(policy->cpu);
        if (!cpu_dev) {
@@ -507,6 +515,38 @@ static int bL_cpufreq_exit(struct cpufreq_policy *policy)
        return 0;
 }
 
+static void bL_cpufreq_ready(struct cpufreq_policy *policy)
+{
+       struct device *cpu_dev = get_cpu_device(policy->cpu);
+       int cur_cluster = cpu_to_cluster(policy->cpu);
+       struct device_node *np;
+
+       /* Do not register a cpu_cooling device if we are in IKS mode */
+       if (cur_cluster >= MAX_CLUSTERS)
+               return;
+
+       np = of_node_get(cpu_dev->of_node);
+       if (WARN_ON(!np))
+               return;
+
+       if (of_find_property(np, "#cooling-cells", NULL)) {
+               u32 power_coefficient = 0;
+
+               of_property_read_u32(np, "dynamic-power-coefficient",
+                                    &power_coefficient);
+
+               cdev[cur_cluster] = of_cpufreq_power_cooling_register(np,
+                               policy->related_cpus, power_coefficient, NULL);
+               if (IS_ERR(cdev[cur_cluster])) {
+                       dev_err(cpu_dev,
+                               "running cpufreq without cooling device: %ld\n",
+                               PTR_ERR(cdev[cur_cluster]));
+                       cdev[cur_cluster] = NULL;
+               }
+       }
+       of_node_put(np);
+}
+
 static struct cpufreq_driver bL_cpufreq_driver = {
        .name                   = "arm-big-little",
        .flags                  = CPUFREQ_STICKY |
@@ -517,6 +557,7 @@ static struct cpufreq_driver bL_cpufreq_driver = {
        .get                    = bL_cpufreq_get_rate,
        .init                   = bL_cpufreq_init,
        .exit                   = bL_cpufreq_exit,
+       .ready                  = bL_cpufreq_ready,
        .attr                   = cpufreq_generic_attr,
 };
 
index a9f8e5bd0716f508858627d33c381437153fc3a3..12e97d8a9db06f868f8961d13fe419d318973e02 100644 (file)
@@ -112,7 +112,7 @@ static unsigned int bfin_getfreq_khz(unsigned int cpu)
 }
 
 #ifdef CONFIG_BF60x
-unsigned long cpu_set_cclk(int cpu, unsigned long new)
+static int cpu_set_cclk(int cpu, unsigned long new)
 {
        struct clk *clk;
        int ret;
index 90d64081ddb34ee8ba7a06372a269defdcf07a97..9bc37c437874a6ba185799680a093598cb213948 100644 (file)
@@ -50,7 +50,8 @@ static int set_target(struct cpufreq_policy *policy, unsigned int index)
        struct private_data *priv = policy->driver_data;
        struct device *cpu_dev = priv->cpu_dev;
        struct regulator *cpu_reg = priv->cpu_reg;
-       unsigned long volt = 0, volt_old = 0, tol = 0;
+       unsigned long volt = 0, tol = 0;
+       int volt_old = 0;
        unsigned int old_freq, new_freq;
        long freq_Hz, freq_exact;
        int ret;
@@ -83,7 +84,7 @@ static int set_target(struct cpufreq_policy *policy, unsigned int index)
                        opp_freq / 1000, volt);
        }
 
-       dev_dbg(cpu_dev, "%u MHz, %ld mV --> %u MHz, %ld mV\n",
+       dev_dbg(cpu_dev, "%u MHz, %d mV --> %u MHz, %ld mV\n",
                old_freq / 1000, (volt_old > 0) ? volt_old / 1000 : -1,
                new_freq / 1000, volt ? volt / 1000 : -1);
 
@@ -407,8 +408,13 @@ static void cpufreq_ready(struct cpufreq_policy *policy)
         * thermal DT code takes care of matching them.
         */
        if (of_find_property(np, "#cooling-cells", NULL)) {
-               priv->cdev = of_cpufreq_cooling_register(np,
-                                                        policy->related_cpus);
+               u32 power_coefficient = 0;
+
+               of_property_read_u32(np, "dynamic-power-coefficient",
+                                    &power_coefficient);
+
+               priv->cdev = of_cpufreq_power_cooling_register(np,
+                               policy->related_cpus, power_coefficient, NULL);
                if (IS_ERR(priv->cdev)) {
                        dev_err(priv->cpu_dev,
                                "running cpufreq without cooling device: %ld\n",
index 8412ce5f93a712a03bfa81df25bee238a299d242..c35e7da1ed7a185fd95d0f0ae7f7b2961d235a0f 100644 (file)
@@ -2330,29 +2330,15 @@ int cpufreq_boost_trigger_state(int state)
        return ret;
 }
 
-int cpufreq_boost_supported(void)
+static bool cpufreq_boost_supported(void)
 {
-       if (likely(cpufreq_driver))
-               return cpufreq_driver->boost_supported;
-
-       return 0;
+       return likely(cpufreq_driver) && cpufreq_driver->set_boost;
 }
-EXPORT_SYMBOL_GPL(cpufreq_boost_supported);
 
 static int create_boost_sysfs_file(void)
 {
        int ret;
 
-       if (!cpufreq_boost_supported())
-               return 0;
-
-       /*
-        * Check if driver provides function to enable boost -
-        * if not, use cpufreq_boost_set_sw as default
-        */
-       if (!cpufreq_driver->set_boost)
-               cpufreq_driver->set_boost = cpufreq_boost_set_sw;
-
        ret = sysfs_create_file(cpufreq_global_kobject, &boost.attr);
        if (ret)
                pr_err("%s: cannot register global BOOST sysfs file\n",
@@ -2375,7 +2361,7 @@ int cpufreq_enable_boost_support(void)
        if (cpufreq_boost_supported())
                return 0;
 
-       cpufreq_driver->boost_supported = true;
+       cpufreq_driver->set_boost = cpufreq_boost_set_sw;
 
        /* This will get removed on driver unregister */
        return create_boost_sysfs_file();
@@ -2435,9 +2421,11 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
        if (driver_data->setpolicy)
                driver_data->flags |= CPUFREQ_CONST_LOOPS;
 
-       ret = create_boost_sysfs_file();
-       if (ret)
-               goto err_null_driver;
+       if (cpufreq_boost_supported()) {
+               ret = create_boost_sysfs_file();
+               if (ret)
+                       goto err_null_driver;
+       }
 
        ret = subsys_interface_register(&cpufreq_interface);
        if (ret)
index 1fa1deb6e91fcbb25b01f8c8e0c23438a0e2bcb4..606ad74abe6e8b248b15a142c4f3fca7241c64be 100644 (file)
@@ -115,13 +115,13 @@ static void cs_check_cpu(int cpu, unsigned int load)
        }
 }
 
-static unsigned int cs_dbs_timer(struct cpu_dbs_info *cdbs,
-                                struct dbs_data *dbs_data, bool modify_all)
+static unsigned int cs_dbs_timer(struct cpufreq_policy *policy, bool modify_all)
 {
+       struct dbs_data *dbs_data = policy->governor_data;
        struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
 
        if (modify_all)
-               dbs_check_cpu(dbs_data, cdbs->shared->policy->cpu);
+               dbs_check_cpu(dbs_data, policy->cpu);
 
        return delay_for_sampling_rate(cs_tuners->sampling_rate);
 }
index b260576ddb129c9bf485a12a954d0b1db30e08c5..bab3a514ec128254d8cff0ccdeaf02f427625d06 100644 (file)
@@ -84,6 +84,9 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu)
                        (cur_wall_time - j_cdbs->prev_cpu_wall);
                j_cdbs->prev_cpu_wall = cur_wall_time;
 
+               if (cur_idle_time < j_cdbs->prev_cpu_idle)
+                       cur_idle_time = j_cdbs->prev_cpu_idle;
+
                idle_time = (unsigned int)
                        (cur_idle_time - j_cdbs->prev_cpu_idle);
                j_cdbs->prev_cpu_idle = cur_idle_time;
@@ -158,47 +161,55 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu)
 }
 EXPORT_SYMBOL_GPL(dbs_check_cpu);
 
-static inline void __gov_queue_work(int cpu, struct dbs_data *dbs_data,
-               unsigned int delay)
+void gov_add_timers(struct cpufreq_policy *policy, unsigned int delay)
 {
-       struct cpu_dbs_info *cdbs = dbs_data->cdata->get_cpu_cdbs(cpu);
-
-       mod_delayed_work_on(cpu, system_wq, &cdbs->dwork, delay);
-}
-
-void gov_queue_work(struct dbs_data *dbs_data, struct cpufreq_policy *policy,
-               unsigned int delay, bool all_cpus)
-{
-       int i;
+       struct dbs_data *dbs_data = policy->governor_data;
+       struct cpu_dbs_info *cdbs;
+       int cpu;
 
-       if (!all_cpus) {
-               /*
-                * Use raw_smp_processor_id() to avoid preemptible warnings.
-                * We know that this is only called with all_cpus == false from
-                * works that have been queued with *_work_on() functions and
-                * those works are canceled during CPU_DOWN_PREPARE so they
-                * can't possibly run on any other CPU.
-                */
-               __gov_queue_work(raw_smp_processor_id(), dbs_data, delay);
-       } else {
-               for_each_cpu(i, policy->cpus)
-                       __gov_queue_work(i, dbs_data, delay);
+       for_each_cpu(cpu, policy->cpus) {
+               cdbs = dbs_data->cdata->get_cpu_cdbs(cpu);
+               cdbs->timer.expires = jiffies + delay;
+               add_timer_on(&cdbs->timer, cpu);
        }
 }
-EXPORT_SYMBOL_GPL(gov_queue_work);
+EXPORT_SYMBOL_GPL(gov_add_timers);
 
-static inline void gov_cancel_work(struct dbs_data *dbs_data,
-               struct cpufreq_policy *policy)
+static inline void gov_cancel_timers(struct cpufreq_policy *policy)
 {
+       struct dbs_data *dbs_data = policy->governor_data;
        struct cpu_dbs_info *cdbs;
        int i;
 
        for_each_cpu(i, policy->cpus) {
                cdbs = dbs_data->cdata->get_cpu_cdbs(i);
-               cancel_delayed_work_sync(&cdbs->dwork);
+               del_timer_sync(&cdbs->timer);
        }
 }
 
+void gov_cancel_work(struct cpu_common_dbs_info *shared)
+{
+       /* Tell dbs_timer_handler() to skip queuing up work items. */
+       atomic_inc(&shared->skip_work);
+       /*
+        * If dbs_timer_handler() is already running, it may not notice the
+        * incremented skip_work, so wait for it to complete to prevent its work
+        * item from being queued up after the cancel_work_sync() below.
+        */
+       gov_cancel_timers(shared->policy);
+       /*
+        * In case dbs_timer_handler() managed to run and spawn a work item
+        * before the timers have been canceled, wait for that work item to
+        * complete and then cancel all of the timers set up by it.  If
+        * dbs_timer_handler() runs again at that point, it will see the
+        * positive value of skip_work and won't spawn any more work items.
+        */
+       cancel_work_sync(&shared->work);
+       gov_cancel_timers(shared->policy);
+       atomic_set(&shared->skip_work, 0);
+}
+EXPORT_SYMBOL_GPL(gov_cancel_work);
+
 /* Will return if we need to evaluate cpu load again or not */
 static bool need_load_eval(struct cpu_common_dbs_info *shared,
                           unsigned int sampling_rate)
@@ -217,29 +228,21 @@ static bool need_load_eval(struct cpu_common_dbs_info *shared,
        return true;
 }
 
-static void dbs_timer(struct work_struct *work)
+static void dbs_work_handler(struct work_struct *work)
 {
-       struct cpu_dbs_info *cdbs = container_of(work, struct cpu_dbs_info,
-                                                dwork.work);
-       struct cpu_common_dbs_info *shared = cdbs->shared;
+       struct cpu_common_dbs_info *shared = container_of(work, struct
+                                       cpu_common_dbs_info, work);
        struct cpufreq_policy *policy;
        struct dbs_data *dbs_data;
        unsigned int sampling_rate, delay;
-       bool modify_all = true;
-
-       mutex_lock(&shared->timer_mutex);
+       bool eval_load;
 
        policy = shared->policy;
-
-       /*
-        * Governor might already be disabled and there is no point continuing
-        * with the work-handler.
-        */
-       if (!policy)
-               goto unlock;
-
        dbs_data = policy->governor_data;
 
+       /* Kill all timers */
+       gov_cancel_timers(policy);
+
        if (dbs_data->cdata->governor == GOV_CONSERVATIVE) {
                struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
 
@@ -250,14 +253,37 @@ static void dbs_timer(struct work_struct *work)
                sampling_rate = od_tuners->sampling_rate;
        }
 
-       if (!need_load_eval(cdbs->shared, sampling_rate))
-               modify_all = false;
-
-       delay = dbs_data->cdata->gov_dbs_timer(cdbs, dbs_data, modify_all);
-       gov_queue_work(dbs_data, policy, delay, modify_all);
+       eval_load = need_load_eval(shared, sampling_rate);
 
-unlock:
+       /*
+        * Make sure cpufreq_governor_limits() isn't evaluating load in
+        * parallel.
+        */
+       mutex_lock(&shared->timer_mutex);
+       delay = dbs_data->cdata->gov_dbs_timer(policy, eval_load);
        mutex_unlock(&shared->timer_mutex);
+
+       atomic_dec(&shared->skip_work);
+
+       gov_add_timers(policy, delay);
+}
+
+static void dbs_timer_handler(unsigned long data)
+{
+       struct cpu_dbs_info *cdbs = (struct cpu_dbs_info *)data;
+       struct cpu_common_dbs_info *shared = cdbs->shared;
+
+       /*
+        * Timer handler may not be allowed to queue the work at the moment,
+        * because:
+        * - Another timer handler has done that
+        * - We are stopping the governor
+        * - Or we are updating the sampling rate of the ondemand governor
+        */
+       if (atomic_inc_return(&shared->skip_work) > 1)
+               atomic_dec(&shared->skip_work);
+       else
+               queue_work(system_wq, &shared->work);
 }
 
 static void set_sampling_rate(struct dbs_data *dbs_data,
@@ -287,6 +313,9 @@ static int alloc_common_dbs_info(struct cpufreq_policy *policy,
        for_each_cpu(j, policy->related_cpus)
                cdata->get_cpu_cdbs(j)->shared = shared;
 
+       mutex_init(&shared->timer_mutex);
+       atomic_set(&shared->skip_work, 0);
+       INIT_WORK(&shared->work, dbs_work_handler);
        return 0;
 }
 
@@ -297,6 +326,8 @@ static void free_common_dbs_info(struct cpufreq_policy *policy,
        struct cpu_common_dbs_info *shared = cdbs->shared;
        int j;
 
+       mutex_destroy(&shared->timer_mutex);
+
        for_each_cpu(j, policy->cpus)
                cdata->get_cpu_cdbs(j)->shared = NULL;
 
@@ -433,7 +464,6 @@ static int cpufreq_governor_start(struct cpufreq_policy *policy,
 
        shared->policy = policy;
        shared->time_stamp = ktime_get();
-       mutex_init(&shared->timer_mutex);
 
        for_each_cpu(j, policy->cpus) {
                struct cpu_dbs_info *j_cdbs = cdata->get_cpu_cdbs(j);
@@ -450,7 +480,9 @@ static int cpufreq_governor_start(struct cpufreq_policy *policy,
                if (ignore_nice)
                        j_cdbs->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE];
 
-               INIT_DEFERRABLE_WORK(&j_cdbs->dwork, dbs_timer);
+               __setup_timer(&j_cdbs->timer, dbs_timer_handler,
+                             (unsigned long)j_cdbs,
+                             TIMER_DEFERRABLE | TIMER_IRQSAFE);
        }
 
        if (cdata->governor == GOV_CONSERVATIVE) {
@@ -468,8 +500,7 @@ static int cpufreq_governor_start(struct cpufreq_policy *policy,
                od_ops->powersave_bias_init_cpu(cpu);
        }
 
-       gov_queue_work(dbs_data, policy, delay_for_sampling_rate(sampling_rate),
-                      true);
+       gov_add_timers(policy, delay_for_sampling_rate(sampling_rate));
        return 0;
 }
 
@@ -483,18 +514,9 @@ static int cpufreq_governor_stop(struct cpufreq_policy *policy,
        if (!shared || !shared->policy)
                return -EBUSY;
 
-       /*
-        * Work-handler must see this updated, as it should not proceed any
-        * further after governor is disabled. And so timer_mutex is taken while
-        * updating this value.
-        */
-       mutex_lock(&shared->timer_mutex);
+       gov_cancel_work(shared);
        shared->policy = NULL;
-       mutex_unlock(&shared->timer_mutex);
-
-       gov_cancel_work(dbs_data, policy);
 
-       mutex_destroy(&shared->timer_mutex);
        return 0;
 }
 
index 5621bb03e874e97415bbd1a790ba98b5737eac65..91e767a058a763995971b6e98f8c1336a78df471 100644 (file)
@@ -17,6 +17,7 @@
 #ifndef _CPUFREQ_GOVERNOR_H
 #define _CPUFREQ_GOVERNOR_H
 
+#include <linux/atomic.h>
 #include <linux/cpufreq.h>
 #include <linux/kernel_stat.h>
 #include <linux/module.h>
@@ -132,12 +133,14 @@ static void *get_cpu_dbs_info_s(int cpu)                          \
 struct cpu_common_dbs_info {
        struct cpufreq_policy *policy;
        /*
-        * percpu mutex that serializes governor limit change with dbs_timer
-        * invocation. We do not want dbs_timer to run when user is changing
-        * the governor or limits.
+        * Per policy mutex that serializes load evaluation from limit-change
+        * and work-handler.
         */
        struct mutex timer_mutex;
+
        ktime_t time_stamp;
+       atomic_t skip_work;
+       struct work_struct work;
 };
 
 /* Per cpu structures */
@@ -152,7 +155,7 @@ struct cpu_dbs_info {
         * wake-up from idle.
         */
        unsigned int prev_load;
-       struct delayed_work dwork;
+       struct timer_list timer;
        struct cpu_common_dbs_info *shared;
 };
 
@@ -209,8 +212,7 @@ struct common_dbs_data {
 
        struct cpu_dbs_info *(*get_cpu_cdbs)(int cpu);
        void *(*get_cpu_dbs_info_s)(int cpu);
-       unsigned int (*gov_dbs_timer)(struct cpu_dbs_info *cdbs,
-                                     struct dbs_data *dbs_data,
+       unsigned int (*gov_dbs_timer)(struct cpufreq_policy *policy,
                                      bool modify_all);
        void (*gov_check_cpu)(int cpu, unsigned int load);
        int (*init)(struct dbs_data *dbs_data, bool notify);
@@ -269,11 +271,11 @@ static ssize_t show_sampling_rate_min_gov_pol                             \
 
 extern struct mutex cpufreq_governor_lock;
 
+void gov_add_timers(struct cpufreq_policy *policy, unsigned int delay);
+void gov_cancel_work(struct cpu_common_dbs_info *shared);
 void dbs_check_cpu(struct dbs_data *dbs_data, int cpu);
 int cpufreq_governor_dbs(struct cpufreq_policy *policy,
                struct common_dbs_data *cdata, unsigned int event);
-void gov_queue_work(struct dbs_data *dbs_data, struct cpufreq_policy *policy,
-               unsigned int delay, bool all_cpus);
 void od_register_powersave_bias_handler(unsigned int (*f)
                (struct cpufreq_policy *, unsigned int, unsigned int),
                unsigned int powersave_bias);
index 03ac6ce540424a189e2946a1dd98d2046cbc3622..eae51070c03427573708fe2bd67a081ccc2ffe82 100644 (file)
@@ -191,10 +191,9 @@ static void od_check_cpu(int cpu, unsigned int load)
        }
 }
 
-static unsigned int od_dbs_timer(struct cpu_dbs_info *cdbs,
-                                struct dbs_data *dbs_data, bool modify_all)
+static unsigned int od_dbs_timer(struct cpufreq_policy *policy, bool modify_all)
 {
-       struct cpufreq_policy *policy = cdbs->shared->policy;
+       struct dbs_data *dbs_data = policy->governor_data;
        unsigned int cpu = policy->cpu;
        struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info,
                        cpu);
@@ -247,40 +246,66 @@ static void update_sampling_rate(struct dbs_data *dbs_data,
                unsigned int new_rate)
 {
        struct od_dbs_tuners *od_tuners = dbs_data->tuners;
+       struct cpumask cpumask;
        int cpu;
 
        od_tuners->sampling_rate = new_rate = max(new_rate,
                        dbs_data->min_sampling_rate);
 
-       for_each_online_cpu(cpu) {
+       /*
+        * Lock governor so that governor start/stop can't execute in parallel.
+        */
+       mutex_lock(&od_dbs_cdata.mutex);
+
+       cpumask_copy(&cpumask, cpu_online_mask);
+
+       for_each_cpu(cpu, &cpumask) {
                struct cpufreq_policy *policy;
                struct od_cpu_dbs_info_s *dbs_info;
+               struct cpu_dbs_info *cdbs;
+               struct cpu_common_dbs_info *shared;
                unsigned long next_sampling, appointed_at;
 
-               policy = cpufreq_cpu_get(cpu);
-               if (!policy)
-                       continue;
-               if (policy->governor != &cpufreq_gov_ondemand) {
-                       cpufreq_cpu_put(policy);
-                       continue;
-               }
                dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
-               cpufreq_cpu_put(policy);
+               cdbs = &dbs_info->cdbs;
+               shared = cdbs->shared;
 
-               if (!delayed_work_pending(&dbs_info->cdbs.dwork))
+               /*
+                * A valid shared and shared->policy means governor hasn't
+                * stopped or exited yet.
+                */
+               if (!shared || !shared->policy)
+                       continue;
+
+               policy = shared->policy;
+
+               /* clear all CPUs of this policy */
+               cpumask_andnot(&cpumask, &cpumask, policy->cpus);
+
+               /*
+                * Update sampling rate for CPUs whose policy is governed by
+                * dbs_data. In case of governor_per_policy, only a single
+                * policy will be governed by dbs_data, otherwise there can be
+                * multiple policies that are governed by the same dbs_data.
+                */
+               if (dbs_data != policy->governor_data)
                        continue;
 
+               /*
+                * Checking this for any CPU should be fine, timers for all of
+                * them are scheduled together.
+                */
                next_sampling = jiffies + usecs_to_jiffies(new_rate);
-               appointed_at = dbs_info->cdbs.dwork.timer.expires;
+               appointed_at = dbs_info->cdbs.timer.expires;
 
                if (time_before(next_sampling, appointed_at)) {
-                       cancel_delayed_work_sync(&dbs_info->cdbs.dwork);
-
-                       gov_queue_work(dbs_data, policy,
-                                      usecs_to_jiffies(new_rate), true);
+                       gov_cancel_work(shared);
+                       gov_add_timers(policy, usecs_to_jiffies(new_rate));
 
                }
        }
+
+       mutex_unlock(&od_dbs_cdata.mutex);
 }
 
 static ssize_t store_sampling_rate(struct dbs_data *dbs_data, const char *buf,
index 98fb8821382d8fc145c6bf9227b62236fdabedb1..cd83d477e32d412394da574e8e02adb6dd7be832 100644 (file)
@@ -66,6 +66,7 @@ static inline int ceiling_fp(int32_t x)
 
 struct sample {
        int32_t core_pct_busy;
+       int32_t busy_scaled;
        u64 aperf;
        u64 mperf;
        u64 tsc;
@@ -112,6 +113,7 @@ struct cpudata {
        u64     prev_aperf;
        u64     prev_mperf;
        u64     prev_tsc;
+       u64     prev_cummulative_iowait;
        struct sample sample;
 };
 
@@ -133,6 +135,7 @@ struct pstate_funcs {
        int (*get_scaling)(void);
        void (*set)(struct cpudata*, int pstate);
        void (*get_vid)(struct cpudata *);
+       int32_t (*get_target_pstate)(struct cpudata *);
 };
 
 struct cpu_defaults {
@@ -140,6 +143,9 @@ struct cpu_defaults {
        struct pstate_funcs funcs;
 };
 
+static inline int32_t get_target_pstate_use_performance(struct cpudata *cpu);
+static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu);
+
 static struct pstate_adjust_policy pid_params;
 static struct pstate_funcs pstate_funcs;
 static int hwp_active;
@@ -738,6 +744,7 @@ static struct cpu_defaults core_params = {
                .get_turbo = core_get_turbo_pstate,
                .get_scaling = core_get_scaling,
                .set = core_set_pstate,
+               .get_target_pstate = get_target_pstate_use_performance,
        },
 };
 
@@ -758,6 +765,7 @@ static struct cpu_defaults silvermont_params = {
                .set = atom_set_pstate,
                .get_scaling = silvermont_get_scaling,
                .get_vid = atom_get_vid,
+               .get_target_pstate = get_target_pstate_use_cpu_load,
        },
 };
 
@@ -778,6 +786,7 @@ static struct cpu_defaults airmont_params = {
                .set = atom_set_pstate,
                .get_scaling = airmont_get_scaling,
                .get_vid = atom_get_vid,
+               .get_target_pstate = get_target_pstate_use_cpu_load,
        },
 };
 
@@ -797,6 +806,7 @@ static struct cpu_defaults knl_params = {
                .get_turbo = knl_get_turbo_pstate,
                .get_scaling = core_get_scaling,
                .set = core_set_pstate,
+               .get_target_pstate = get_target_pstate_use_performance,
        },
 };
 
@@ -882,12 +892,11 @@ static inline void intel_pstate_sample(struct cpudata *cpu)
        local_irq_save(flags);
        rdmsrl(MSR_IA32_APERF, aperf);
        rdmsrl(MSR_IA32_MPERF, mperf);
-       if (cpu->prev_mperf == mperf) {
+       tsc = rdtsc();
+       if ((cpu->prev_mperf == mperf) || (cpu->prev_tsc == tsc)) {
                local_irq_restore(flags);
                return;
        }
-
-       tsc = rdtsc();
        local_irq_restore(flags);
 
        cpu->last_sample_time = cpu->sample.time;
@@ -922,7 +931,43 @@ static inline void intel_pstate_set_sample_time(struct cpudata *cpu)
        mod_timer_pinned(&cpu->timer, jiffies + delay);
 }
 
-static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu)
+static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu)
+{
+       struct sample *sample = &cpu->sample;
+       u64 cummulative_iowait, delta_iowait_us;
+       u64 delta_iowait_mperf;
+       u64 mperf, now;
+       int32_t cpu_load;
+
+       cummulative_iowait = get_cpu_iowait_time_us(cpu->cpu, &now);
+
+       /*
+        * Convert iowait time into number of IO cycles spent at max_freq.
+        * IO is considered as busy only for the cpu_load algorithm. For
+        * performance this is not needed since we always try to reach the
+        * maximum P-State, so we are already boosting the IOs.
+        */
+       delta_iowait_us = cummulative_iowait - cpu->prev_cummulative_iowait;
+       delta_iowait_mperf = div64_u64(delta_iowait_us * cpu->pstate.scaling *
+               cpu->pstate.max_pstate, MSEC_PER_SEC);
+
+       mperf = cpu->sample.mperf + delta_iowait_mperf;
+       cpu->prev_cummulative_iowait = cummulative_iowait;
+
+
+       /*
+        * The load can be estimated as the ratio of the mperf counter
+        * running at a constant frequency during active periods
+        * (C0) and the time stamp counter running at the same frequency
+        * also during C-states.
+        */
+       cpu_load = div64_u64(int_tofp(100) * mperf, sample->tsc);
+       cpu->sample.busy_scaled = cpu_load;
+
+       return cpu->pstate.current_pstate - pid_calc(&cpu->pid, cpu_load);
+}
+
+static inline int32_t get_target_pstate_use_performance(struct cpudata *cpu)
 {
        int32_t core_busy, max_pstate, current_pstate, sample_ratio;
        s64 duration_us;
@@ -960,30 +1005,24 @@ static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu)
                core_busy = mul_fp(core_busy, sample_ratio);
        }
 
-       return core_busy;
+       cpu->sample.busy_scaled = core_busy;
+       return cpu->pstate.current_pstate - pid_calc(&cpu->pid, core_busy);
 }
 
 static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu)
 {
-       int32_t busy_scaled;
-       struct _pid *pid;
-       signed int ctl;
-       int from;
+       int from, target_pstate;
        struct sample *sample;
 
        from = cpu->pstate.current_pstate;
 
-       pid = &cpu->pid;
-       busy_scaled = intel_pstate_get_scaled_busy(cpu);
+       target_pstate = pstate_funcs.get_target_pstate(cpu);
 
-       ctl = pid_calc(pid, busy_scaled);
-
-       /* Negative values of ctl increase the pstate and vice versa */
-       intel_pstate_set_pstate(cpu, cpu->pstate.current_pstate - ctl, true);
+       intel_pstate_set_pstate(cpu, target_pstate, true);
 
        sample = &cpu->sample;
        trace_pstate_sample(fp_toint(sample->core_pct_busy),
-               fp_toint(busy_scaled),
+               fp_toint(sample->busy_scaled),
                from,
                cpu->pstate.current_pstate,
                sample->mperf,
@@ -1237,6 +1276,8 @@ static void copy_cpu_funcs(struct pstate_funcs *funcs)
        pstate_funcs.get_scaling = funcs->get_scaling;
        pstate_funcs.set       = funcs->set;
        pstate_funcs.get_vid   = funcs->get_vid;
+       pstate_funcs.get_target_pstate = funcs->get_target_pstate;
+
 }
 
 #if IS_ENABLED(CONFIG_ACPI)
index 83001dc5b6468529cd996e5d5a5179cd3fdc1f44..1efba340456dfc5df4b2005517fe0c1b048e198a 100644 (file)
  * the original PLL becomes stable at target frequency.
  */
 struct mtk_cpu_dvfs_info {
+       struct cpumask cpus;
        struct device *cpu_dev;
        struct regulator *proc_reg;
        struct regulator *sram_reg;
        struct clk *cpu_clk;
        struct clk *inter_clk;
        struct thermal_cooling_device *cdev;
+       struct list_head list_head;
        int intermediate_voltage;
        bool need_voltage_tracking;
 };
 
+static LIST_HEAD(dvfs_info_list);
+
+static struct mtk_cpu_dvfs_info *mtk_cpu_dvfs_info_lookup(int cpu)
+{
+       struct mtk_cpu_dvfs_info *info;
+       struct list_head *list;
+
+       list_for_each(list, &dvfs_info_list) {
+               info = list_entry(list, struct mtk_cpu_dvfs_info, list_head);
+
+               if (cpumask_test_cpu(cpu, &info->cpus))
+                       return info;
+       }
+
+       return NULL;
+}
+
 static int mtk_cpufreq_voltage_tracking(struct mtk_cpu_dvfs_info *info,
                                        int new_vproc)
 {
@@ -59,7 +78,10 @@ static int mtk_cpufreq_voltage_tracking(struct mtk_cpu_dvfs_info *info,
        int old_vproc, old_vsram, new_vsram, vsram, vproc, ret;
 
        old_vproc = regulator_get_voltage(proc_reg);
-       old_vsram = regulator_get_voltage(sram_reg);
+       if (old_vproc < 0) {
+               pr_err("%s: invalid Vproc value: %d\n", __func__, old_vproc);
+               return old_vproc;
+       }
        /* Vsram should not exceed the maximum allowed voltage of SoC. */
        new_vsram = min(new_vproc + MIN_VOLT_SHIFT, MAX_VOLT_LIMIT);
 
@@ -72,7 +94,17 @@ static int mtk_cpufreq_voltage_tracking(struct mtk_cpu_dvfs_info *info,
                 */
                do {
                        old_vsram = regulator_get_voltage(sram_reg);
+                       if (old_vsram < 0) {
+                               pr_err("%s: invalid Vsram value: %d\n",
+                                      __func__, old_vsram);
+                               return old_vsram;
+                       }
                        old_vproc = regulator_get_voltage(proc_reg);
+                       if (old_vproc < 0) {
+                               pr_err("%s: invalid Vproc value: %d\n",
+                                      __func__, old_vproc);
+                               return old_vproc;
+                       }
 
                        vsram = min(new_vsram, old_vproc + MAX_VOLT_SHIFT);
 
@@ -117,7 +149,17 @@ static int mtk_cpufreq_voltage_tracking(struct mtk_cpu_dvfs_info *info,
                 */
                do {
                        old_vproc = regulator_get_voltage(proc_reg);
+                       if (old_vproc < 0) {
+                               pr_err("%s: invalid Vproc value: %d\n",
+                                      __func__, old_vproc);
+                               return old_vproc;
+                       }
                        old_vsram = regulator_get_voltage(sram_reg);
+                       if (old_vsram < 0) {
+                               pr_err("%s: invalid Vsram value: %d\n",
+                                      __func__, old_vsram);
+                               return old_vsram;
+                       }
 
                        vproc = max(new_vproc, old_vsram - MAX_VOLT_SHIFT);
                        ret = regulator_set_voltage(proc_reg, vproc,
@@ -185,6 +227,10 @@ static int mtk_cpufreq_set_target(struct cpufreq_policy *policy,
 
        old_freq_hz = clk_get_rate(cpu_clk);
        old_vproc = regulator_get_voltage(info->proc_reg);
+       if (old_vproc < 0) {
+               pr_err("%s: invalid Vproc value: %d\n", __func__, old_vproc);
+               return old_vproc;
+       }
 
        freq_hz = freq_table[index].frequency * 1000;
 
@@ -344,7 +390,15 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
        /* Both presence and absence of sram regulator are valid cases. */
        sram_reg = regulator_get_exclusive(cpu_dev, "sram");
 
-       ret = dev_pm_opp_of_add_table(cpu_dev);
+       /* Get OPP-sharing information from "operating-points-v2" bindings */
+       ret = dev_pm_opp_of_get_sharing_cpus(cpu_dev, &info->cpus);
+       if (ret) {
+               pr_err("failed to get OPP-sharing information for cpu%d\n",
+                      cpu);
+               goto out_free_resources;
+       }
+
+       ret = dev_pm_opp_of_cpumask_add_table(&info->cpus);
        if (ret) {
                pr_warn("no OPP table for cpu%d\n", cpu);
                goto out_free_resources;
@@ -378,7 +432,7 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
        return 0;
 
 out_free_opp_table:
-       dev_pm_opp_of_remove_table(cpu_dev);
+       dev_pm_opp_of_cpumask_remove_table(&info->cpus);
 
 out_free_resources:
        if (!IS_ERR(proc_reg))
@@ -404,7 +458,7 @@ static void mtk_cpu_dvfs_info_release(struct mtk_cpu_dvfs_info *info)
        if (!IS_ERR(info->inter_clk))
                clk_put(info->inter_clk);
 
-       dev_pm_opp_of_remove_table(info->cpu_dev);
+       dev_pm_opp_of_cpumask_remove_table(&info->cpus);
 }
 
 static int mtk_cpufreq_init(struct cpufreq_policy *policy)
@@ -413,22 +467,18 @@ static int mtk_cpufreq_init(struct cpufreq_policy *policy)
        struct cpufreq_frequency_table *freq_table;
        int ret;
 
-       info = kzalloc(sizeof(*info), GFP_KERNEL);
-       if (!info)
-               return -ENOMEM;
-
-       ret = mtk_cpu_dvfs_info_init(info, policy->cpu);
-       if (ret) {
-               pr_err("%s failed to initialize dvfs info for cpu%d\n",
-                      __func__, policy->cpu);
-               goto out_free_dvfs_info;
+       info = mtk_cpu_dvfs_info_lookup(policy->cpu);
+       if (!info) {
+               pr_err("dvfs info for cpu%d is not initialized.\n",
+                      policy->cpu);
+               return -EINVAL;
        }
 
        ret = dev_pm_opp_init_cpufreq_table(info->cpu_dev, &freq_table);
        if (ret) {
                pr_err("failed to init cpufreq table for cpu%d: %d\n",
                       policy->cpu, ret);
-               goto out_release_dvfs_info;
+               return ret;
        }
 
        ret = cpufreq_table_validate_and_show(policy, freq_table);
@@ -437,8 +487,7 @@ static int mtk_cpufreq_init(struct cpufreq_policy *policy)
                goto out_free_cpufreq_table;
        }
 
-       /* CPUs in the same cluster share a clock and power domain. */
-       cpumask_copy(policy->cpus, &cpu_topology[policy->cpu].core_sibling);
+       cpumask_copy(policy->cpus, &info->cpus);
        policy->driver_data = info;
        policy->clk = info->cpu_clk;
 
@@ -446,13 +495,6 @@ static int mtk_cpufreq_init(struct cpufreq_policy *policy)
 
 out_free_cpufreq_table:
        dev_pm_opp_free_cpufreq_table(info->cpu_dev, &freq_table);
-
-out_release_dvfs_info:
-       mtk_cpu_dvfs_info_release(info);
-
-out_free_dvfs_info:
-       kfree(info);
-
        return ret;
 }
 
@@ -462,14 +504,13 @@ static int mtk_cpufreq_exit(struct cpufreq_policy *policy)
 
        cpufreq_cooling_unregister(info->cdev);
        dev_pm_opp_free_cpufreq_table(info->cpu_dev, &policy->freq_table);
-       mtk_cpu_dvfs_info_release(info);
-       kfree(info);
 
        return 0;
 }
 
 static struct cpufreq_driver mt8173_cpufreq_driver = {
-       .flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK,
+       .flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK |
+                CPUFREQ_HAVE_GOVERNOR_PER_POLICY,
        .verify = cpufreq_generic_frequency_table_verify,
        .target_index = mtk_cpufreq_set_target,
        .get = cpufreq_generic_get,
@@ -482,11 +523,47 @@ static struct cpufreq_driver mt8173_cpufreq_driver = {
 
 static int mt8173_cpufreq_probe(struct platform_device *pdev)
 {
-       int ret;
+       struct mtk_cpu_dvfs_info *info;
+       struct list_head *list, *tmp;
+       int cpu, ret;
+
+       for_each_possible_cpu(cpu) {
+               info = mtk_cpu_dvfs_info_lookup(cpu);
+               if (info)
+                       continue;
+
+               info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+               if (!info) {
+                       ret = -ENOMEM;
+                       goto release_dvfs_info_list;
+               }
+
+               ret = mtk_cpu_dvfs_info_init(info, cpu);
+               if (ret) {
+                       dev_err(&pdev->dev,
+                               "failed to initialize dvfs info for cpu%d\n",
+                               cpu);
+                       goto release_dvfs_info_list;
+               }
+
+               list_add(&info->list_head, &dvfs_info_list);
+       }
 
        ret = cpufreq_register_driver(&mt8173_cpufreq_driver);
-       if (ret)
-               pr_err("failed to register mtk cpufreq driver\n");
+       if (ret) {
+               dev_err(&pdev->dev, "failed to register mtk cpufreq driver\n");
+               goto release_dvfs_info_list;
+       }
+
+       return 0;
+
+release_dvfs_info_list:
+       list_for_each_safe(list, tmp, &dvfs_info_list) {
+               info = list_entry(list, struct mtk_cpu_dvfs_info, list_head);
+
+               mtk_cpu_dvfs_info_release(info);
+               list_del(list);
+       }
 
        return ret;
 }
index 2a0d58959acfe2861cdf9e826ef397958fd6fef2..808a320e9d5d0cdb0a943de7d9af5c89e9b444d5 100644 (file)
@@ -555,6 +555,8 @@ static int pcc_cpufreq_cpu_init(struct cpufreq_policy *policy)
        policy->min = policy->cpuinfo.min_freq =
                ioread32(&pcch_hdr->minimum_frequency) * 1000;
 
+       policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+
        pr_debug("init: policy->max is %d, policy->min is %d\n",
                policy->max, policy->min);
 out:
index 358f0752c31e26956adc41b0a93867921069de8f..b23e525a7af3fc21ad9fa85be59d3cb6a3ba27ba 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <linux/clk.h>
 #include <linux/cpufreq.h>
+#include <linux/cpu_cooling.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -33,6 +34,7 @@
 struct cpu_data {
        struct clk **pclk;
        struct cpufreq_frequency_table *table;
+       struct thermal_cooling_device *cdev;
 };
 
 /**
@@ -321,6 +323,27 @@ static int qoriq_cpufreq_target(struct cpufreq_policy *policy,
        return clk_set_parent(policy->clk, parent);
 }
 
+
+static void qoriq_cpufreq_ready(struct cpufreq_policy *policy)
+{
+       struct cpu_data *cpud = policy->driver_data;
+       struct device_node *np = of_get_cpu_node(policy->cpu, NULL);
+
+       if (of_find_property(np, "#cooling-cells", NULL)) {
+               cpud->cdev = of_cpufreq_cooling_register(np,
+                                                        policy->related_cpus);
+
+               if (IS_ERR(cpud->cdev)) {
+                       pr_err("Failed to register cooling device cpu%d: %ld\n",
+                                       policy->cpu, PTR_ERR(cpud->cdev));
+
+                       cpud->cdev = NULL;
+               }
+       }
+
+       of_node_put(np);
+}
+
 static struct cpufreq_driver qoriq_cpufreq_driver = {
        .name           = "qoriq_cpufreq",
        .flags          = CPUFREQ_CONST_LOOPS,
@@ -329,6 +352,7 @@ static struct cpufreq_driver qoriq_cpufreq_driver = {
        .verify         = cpufreq_generic_frequency_table_verify,
        .target_index   = qoriq_cpufreq_target,
        .get            = cpufreq_generic_get,
+       .ready          = qoriq_cpufreq_ready,
        .attr           = cpufreq_generic_attr,
 };
 
diff --git a/drivers/cpufreq/sti-cpufreq.c b/drivers/cpufreq/sti-cpufreq.c
new file mode 100644 (file)
index 0000000..a9c659f
--- /dev/null
@@ -0,0 +1,294 @@
+/*
+ * Match running platform with pre-defined OPP values for CPUFreq
+ *
+ * Author: Ajit Pal Singh <ajitpal.singh@st.com>
+ *         Lee Jones <lee.jones@linaro.org>
+ *
+ * Copyright (C) 2015 STMicroelectronics (R&D) Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the version 2 of the GNU General Public License as
+ * published by the Free Software Foundation
+ */
+
+#include <linux/cpu.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/pm_opp.h>
+#include <linux/regmap.h>
+
+#define VERSION_ELEMENTS       3
+#define MAX_PCODE_NAME_LEN     7
+
+#define VERSION_SHIFT          28
+#define HW_INFO_INDEX          1
+#define MAJOR_ID_INDEX         1
+#define MINOR_ID_INDEX         2
+
+/*
+ * Only match on "suitable for ALL versions" entries
+ *
+ * This will be used with the BIT() macro.  It sets the
+ * top bit of a 32bit value and is equal to 0x80000000.
+ */
+#define DEFAULT_VERSION                31
+
+enum {
+       PCODE = 0,
+       SUBSTRATE,
+       DVFS_MAX_REGFIELDS,
+};
+
+/**
+ * ST CPUFreq Driver Data
+ *
+ * @cpu_node           CPU's OF node
+ * @syscfg_eng         Engineering Syscon register map
+ * @regmap             Syscon register map
+ */
+static struct sti_cpufreq_ddata {
+       struct device *cpu;
+       struct regmap *syscfg_eng;
+       struct regmap *syscfg;
+} ddata;
+
+static int sti_cpufreq_fetch_major(void) {
+       struct device_node *np = ddata.cpu->of_node;
+       struct device *dev = ddata.cpu;
+       unsigned int major_offset;
+       unsigned int socid;
+       int ret;
+
+       ret = of_property_read_u32_index(np, "st,syscfg",
+                                        MAJOR_ID_INDEX, &major_offset);
+       if (ret) {
+               dev_err(dev, "No major number offset provided in %s [%d]\n",
+                       np->full_name, ret);
+               return ret;
+       }
+
+       ret = regmap_read(ddata.syscfg, major_offset, &socid);
+       if (ret) {
+               dev_err(dev, "Failed to read major number from syscon [%d]\n",
+                       ret);
+               return ret;
+       }
+
+       return ((socid >> VERSION_SHIFT) & 0xf) + 1;
+}
+
+static int sti_cpufreq_fetch_minor(void)
+{
+       struct device *dev = ddata.cpu;
+       struct device_node *np = dev->of_node;
+       unsigned int minor_offset;
+       unsigned int minid;
+       int ret;
+
+       ret = of_property_read_u32_index(np, "st,syscfg-eng",
+                                        MINOR_ID_INDEX, &minor_offset);
+       if (ret) {
+               dev_err(dev,
+                       "No minor number offset provided %s [%d]\n",
+                       np->full_name, ret);
+               return ret;
+       }
+
+       ret = regmap_read(ddata.syscfg_eng, minor_offset, &minid);
+       if (ret) {
+               dev_err(dev,
+                       "Failed to read the minor number from syscon [%d]\n",
+                       ret);
+               return ret;
+       }
+
+       return minid & 0xf;
+}
+
+static int sti_cpufreq_fetch_regmap_field(const struct reg_field *reg_fields,
+                                         int hw_info_offset, int field)
+{
+       struct regmap_field *regmap_field;
+       struct reg_field reg_field = reg_fields[field];
+       struct device *dev = ddata.cpu;
+       unsigned int value;
+       int ret;
+
+       reg_field.reg = hw_info_offset;
+       regmap_field = devm_regmap_field_alloc(dev,
+                                              ddata.syscfg_eng,
+                                              reg_field);
+       if (IS_ERR(regmap_field)) {
+               dev_err(dev, "Failed to allocate reg field\n");
+               return PTR_ERR(regmap_field);
+       }
+
+       ret = regmap_field_read(regmap_field, &value);
+       if (ret) {
+               dev_err(dev, "Failed to read %s code\n",
+                       field ? "SUBSTRATE" : "PCODE");
+               return ret;
+       }
+
+       return value;
+}
+
+static const struct reg_field sti_stih407_dvfs_regfields[DVFS_MAX_REGFIELDS] = {
+       [PCODE]         = REG_FIELD(0, 16, 19),
+       [SUBSTRATE]     = REG_FIELD(0, 0, 2),
+};
+
+static const struct reg_field *sti_cpufreq_match(void)
+{
+       if (of_machine_is_compatible("st,stih407") ||
+           of_machine_is_compatible("st,stih410"))
+               return sti_stih407_dvfs_regfields;
+
+       return NULL;
+}
+
+static int sti_cpufreq_set_opp_info(void)
+{
+       struct device *dev = ddata.cpu;
+       struct device_node *np = dev->of_node;
+       const struct reg_field *reg_fields;
+       unsigned int hw_info_offset;
+       unsigned int version[VERSION_ELEMENTS];
+       int pcode, substrate, major, minor;
+       int ret;
+       char name[MAX_PCODE_NAME_LEN];
+
+       reg_fields = sti_cpufreq_match();
+       if (!reg_fields) {
+               dev_err(dev, "This SoC doesn't support voltage scaling");
+               return -ENODEV;
+       }
+
+       ret = of_property_read_u32_index(np, "st,syscfg-eng",
+                                        HW_INFO_INDEX, &hw_info_offset);
+       if (ret) {
+               dev_warn(dev, "Failed to read HW info offset from DT\n");
+               substrate = DEFAULT_VERSION;
+               pcode = 0;
+               goto use_defaults;
+       }
+
+       pcode = sti_cpufreq_fetch_regmap_field(reg_fields,
+                                              hw_info_offset,
+                                              PCODE);
+       if (pcode < 0) {
+               dev_warn(dev, "Failed to obtain process code\n");
+               /* Use default pcode */
+               pcode = 0;
+       }
+
+       substrate = sti_cpufreq_fetch_regmap_field(reg_fields,
+                                                  hw_info_offset,
+                                                  SUBSTRATE);
+       if (substrate) {
+               dev_warn(dev, "Failed to obtain substrate code\n");
+               /* Use default substrate */
+               substrate = DEFAULT_VERSION;
+       }
+
+use_defaults:
+       major = sti_cpufreq_fetch_major();
+       if (major < 0) {
+               dev_err(dev, "Failed to obtain major version\n");
+               /* Use default major number */
+               major = DEFAULT_VERSION;
+       }
+
+       minor = sti_cpufreq_fetch_minor();
+       if (minor < 0) {
+               dev_err(dev, "Failed to obtain minor version\n");
+               /* Use default minor number */
+               minor = DEFAULT_VERSION;
+       }
+
+       snprintf(name, MAX_PCODE_NAME_LEN, "pcode%d", pcode);
+
+       ret = dev_pm_opp_set_prop_name(dev, name);
+       if (ret) {
+               dev_err(dev, "Failed to set prop name\n");
+               return ret;
+       }
+
+       version[0] = BIT(major);
+       version[1] = BIT(minor);
+       version[2] = BIT(substrate);
+
+       ret = dev_pm_opp_set_supported_hw(dev, version, VERSION_ELEMENTS);
+       if (ret) {
+               dev_err(dev, "Failed to set supported hardware\n");
+               return ret;
+       }
+
+       dev_dbg(dev, "pcode: %d major: %d minor: %d substrate: %d\n",
+               pcode, major, minor, substrate);
+       dev_dbg(dev, "version[0]: %x version[1]: %x version[2]: %x\n",
+               version[0], version[1], version[2]);
+
+       return 0;
+}
+
+static int sti_cpufreq_fetch_syscon_regsiters(void)
+{
+       struct device *dev = ddata.cpu;
+       struct device_node *np = dev->of_node;
+
+       ddata.syscfg = syscon_regmap_lookup_by_phandle(np, "st,syscfg");
+       if (IS_ERR(ddata.syscfg)) {
+               dev_err(dev,  "\"st,syscfg\" not supplied\n");
+               return PTR_ERR(ddata.syscfg);
+       }
+
+       ddata.syscfg_eng = syscon_regmap_lookup_by_phandle(np, "st,syscfg-eng");
+       if (IS_ERR(ddata.syscfg_eng)) {
+               dev_err(dev, "\"st,syscfg-eng\" not supplied\n");
+               return PTR_ERR(ddata.syscfg_eng);
+       }
+
+       return 0;
+}
+
+static int sti_cpufreq_init(void)
+{
+       int ret;
+
+       ddata.cpu = get_cpu_device(0);
+       if (!ddata.cpu) {
+               dev_err(ddata.cpu, "Failed to get device for CPU0\n");
+               goto skip_voltage_scaling;
+       }
+
+       if (!of_get_property(ddata.cpu->of_node, "operating-points-v2", NULL)) {
+               dev_err(ddata.cpu, "OPP-v2 not supported\n");
+               goto skip_voltage_scaling;
+       }
+
+       ret = sti_cpufreq_fetch_syscon_regsiters();
+       if (ret)
+               goto skip_voltage_scaling;
+
+       ret = sti_cpufreq_set_opp_info();
+       if (!ret)
+               goto register_cpufreq_dt;
+
+skip_voltage_scaling:
+       dev_err(ddata.cpu, "Not doing voltage scaling\n");
+
+register_cpufreq_dt:
+       platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
+
+       return 0;
+}
+module_init(sti_cpufreq_init);
+
+MODULE_DESCRIPTION("STMicroelectronics CPUFreq/OPP driver");
+MODULE_AUTHOR("Ajitpal Singh <ajitpal.singh@st.com>");
+MODULE_AUTHOR("Lee Jones <lee.jones@linaro.org>");
+MODULE_LICENSE("GPL v2");
index 18a7f738050816924a924499e41f78b3b59d6074..66a9f231ec41160b52ab36d49626aecc2f91b414 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/cpuidle.h>
 #include <linux/err.h>
 #include <linux/io.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/platform_device.h>
 
 #define CLPS711X_CPUIDLE_NAME  "clps711x-cpuidle"
@@ -56,8 +56,4 @@ static struct platform_driver clps711x_cpuidle_driver = {
                .name   = CLPS711X_CPUIDLE_NAME,
        },
 };
-module_platform_driver_probe(clps711x_cpuidle_driver, clps711x_cpuidle_probe);
-
-MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");
-MODULE_DESCRIPTION("CLPS711X CPU idle driver");
-MODULE_LICENSE("GPL");
+builtin_platform_driver_probe(clps711x_cpuidle_driver, clps711x_cpuidle_probe);
index b5f0a9cc8185c593688a9b9f75b0ec6547800da3..00cd129b10a4614709b7501dd04f927b6d06fa17 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/cpuidle.h>
 #include <linux/cpu_pm.h>
 #include <linux/export.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/of.h>
 #include <linux/platform_data/cpuidle-exynos.h>
@@ -142,5 +142,4 @@ static struct platform_driver exynos_cpuidle_driver = {
                .name = "exynos_cpuidle",
        },
 };
-
-module_platform_driver(exynos_cpuidle_driver);
+builtin_platform_driver(exynos_cpuidle_driver);
index 8bf895c0017df0f7cefbb25d39e4805a7fa21a6a..7941a090bea6d4f3df0d3169d5a430f15af5f291 100644 (file)
@@ -9,7 +9,7 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/cpuidle.h>
 #include <linux/spinlock.h>
 #include <linux/atomic.h>
@@ -124,5 +124,4 @@ static struct platform_driver dbx500_cpuidle_plat_driver = {
        },
        .probe = dbx500_cpuidle_probe,
 };
-
-module_platform_driver(dbx500_cpuidle_plat_driver);
+builtin_platform_driver(dbx500_cpuidle_plat_driver);
index 22e4463d1787ab3d37aaaa61cfc402c16a315a2d..7b0971d97cc331e81ac19681029056fc9cda7cd5 100644 (file)
@@ -330,7 +330,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
         * We want to default to C1 (hlt), not to busy polling
         * unless the timer is happening really really soon.
         */
-       if (data->next_timer_us > 5 &&
+       if (interactivity_req > 20 &&
            !drv->states[CPUIDLE_DRIVER_STATE_START].disabled &&
                dev->states_usage[CPUIDLE_DRIVER_STATE_START].disable == 0)
                data->last_state_idx = CPUIDLE_DRIVER_STATE_START;
@@ -404,8 +404,10 @@ static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev)
        measured_us = cpuidle_get_last_residency(dev);
 
        /* Deduct exit latency */
-       if (measured_us > target->exit_latency)
+       if (measured_us > 2 * target->exit_latency)
                measured_us -= target->exit_latency;
+       else
+               measured_us /= 2;
 
        /* Make sure our coefficients do not exceed unity */
        if (measured_us > data->next_timer_us)
index 7067b6ddc1db6e7662f69bde5715639c479900d8..8b20930ade98149be6b1c831aba2d03a2fc8cf0e 100644 (file)
@@ -622,12 +622,17 @@ static void dw_dma_tasklet(unsigned long data)
 static irqreturn_t dw_dma_interrupt(int irq, void *dev_id)
 {
        struct dw_dma *dw = dev_id;
-       u32 status = dma_readl(dw, STATUS_INT);
+       u32 status;
 
+       /* Check if we have any interrupt from the DMAC which is not in use */
+       if (!dw->in_use)
+               return IRQ_NONE;
+
+       status = dma_readl(dw, STATUS_INT);
        dev_vdbg(dw->dma.dev, "%s: status=0x%x\n", __func__, status);
 
        /* Check if we have any interrupt from the DMAC */
-       if (!status || !dw->in_use)
+       if (!status)
                return IRQ_NONE;
 
        /*
index 68a4815750b514bcd94a312885607a83db7d99cf..127093a0c0e8d845a7ca6d4dcfd9f432ac8189a3 100644 (file)
@@ -155,7 +155,6 @@ static int dw_probe(struct platform_device *pdev)
        struct dw_dma_chip *chip;
        struct device *dev = &pdev->dev;
        struct resource *mem;
-       const struct acpi_device_id *id;
        struct dw_dma_platform_data *pdata;
        int err;
 
@@ -179,11 +178,6 @@ static int dw_probe(struct platform_device *pdev)
        pdata = dev_get_platdata(dev);
        if (!pdata)
                pdata = dw_dma_parse_dt(pdev);
-       if (!pdata && has_acpi_companion(dev)) {
-               id = acpi_match_device(dev->driver->acpi_match_table, dev);
-               if (id)
-                       pdata = (struct dw_dma_platform_data *)id->driver_data;
-       }
 
        chip->dev = dev;
 
@@ -239,7 +233,19 @@ static void dw_shutdown(struct platform_device *pdev)
 {
        struct dw_dma_chip *chip = platform_get_drvdata(pdev);
 
+       /*
+        * We have to call dw_dma_disable() to stop any ongoing transfer. On
+        * some platforms we can't do that since DMA device is powered off.
+        * Moreover we have no possibility to check if the platform is affected
+        * or not. That's why we call pm_runtime_get_sync() / pm_runtime_put()
+        * unconditionally. On the other hand we can't use
+        * pm_runtime_suspended() because runtime PM framework is not fully
+        * used by the driver.
+        */
+       pm_runtime_get_sync(chip->dev);
        dw_dma_disable(chip);
+       pm_runtime_put_sync_suspend(chip->dev);
+
        clk_disable_unprepare(chip->clk);
 }
 
@@ -252,17 +258,8 @@ MODULE_DEVICE_TABLE(of, dw_dma_of_id_table);
 #endif
 
 #ifdef CONFIG_ACPI
-static struct dw_dma_platform_data dw_dma_acpi_pdata = {
-       .nr_channels = 8,
-       .is_private = true,
-       .chan_allocation_order = CHAN_ALLOCATION_ASCENDING,
-       .chan_priority = CHAN_PRIORITY_ASCENDING,
-       .block_size = 4095,
-       .nr_masters = 2,
-};
-
 static const struct acpi_device_id dw_dma_acpi_id_table[] = {
-       { "INTL9C60", (kernel_ulong_t)&dw_dma_acpi_pdata },
+       { "INTL9C60", 0 },
        { }
 };
 MODULE_DEVICE_TABLE(acpi, dw_dma_acpi_id_table);
index 16a7b68167444bba93e24d3d59769f0a08d55440..cbbb67a6f1d6064d15481bba121eb4383a73409d 100644 (file)
@@ -417,10 +417,15 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data)
                 * ActiveLow is only specified for GpioInt resource. If
                 * GpioIo is used then the only way to set the flag is
                 * to use _DSD "gpios" property.
+                * Note: we expect here:
+                * - ACPI_ACTIVE_LOW == GPIO_ACTIVE_LOW
+                * - ACPI_ACTIVE_HIGH == GPIO_ACTIVE_HIGH
                 */
-               if (lookup->info.gpioint)
-                       lookup->info.active_low =
-                               agpio->polarity == ACPI_ACTIVE_LOW;
+               if (lookup->info.gpioint) {
+                       lookup->info.polarity = agpio->polarity;
+                       lookup->info.triggering = agpio->triggering;
+               }
+
        }
 
        return 1;
@@ -447,7 +452,7 @@ static int acpi_gpio_resource_lookup(struct acpi_gpio_lookup *lookup,
        if (info) {
                *info = lookup->info;
                if (lookup->active_low)
-                       info->active_low = lookup->active_low;
+                       info->polarity = lookup->active_low;
        }
        return 0;
 }
@@ -595,6 +600,7 @@ struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode,
 int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)
 {
        int idx, i;
+       unsigned int irq_flags;
 
        for (i = 0, idx = 0; idx <= index; i++) {
                struct acpi_gpio_info info;
@@ -603,8 +609,23 @@ int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)
                desc = acpi_get_gpiod_by_index(adev, NULL, i, &info);
                if (IS_ERR(desc))
                        break;
-               if (info.gpioint && idx++ == index)
-                       return gpiod_to_irq(desc);
+               if (info.gpioint && idx++ == index) {
+                       int irq = gpiod_to_irq(desc);
+
+                       if (irq < 0)
+                               return irq;
+
+                       irq_flags = acpi_dev_get_irq_type(info.triggering,
+                                                         info.polarity);
+
+                       /* Set type if specified and different than the current one */
+                       if (irq_flags != IRQ_TYPE_NONE &&
+                           irq_flags != irq_get_trigger_type(irq))
+                               irq_set_irq_type(irq, irq_flags);
+
+                       return irq;
+               }
+
        }
        return -ENOENT;
 }
index 4e4c3083ae567f02db4ff15444ec173ac53ebe0c..5d8d7ab969163e332ce795d61632d2d982b39ccd 100644 (file)
@@ -1879,7 +1879,7 @@ static struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id,
                        return desc;
        }
 
-       if (info.active_low)
+       if (info.polarity == GPIO_ACTIVE_LOW)
                *flags |= GPIO_ACTIVE_LOW;
 
        return desc;
@@ -2217,7 +2217,7 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
 
                desc = acpi_node_get_gpiod(fwnode, propname, 0, &info);
                if (!IS_ERR(desc))
-                       active_low = info.active_low;
+                       active_low = info.polarity == GPIO_ACTIVE_LOW;
        }
 
        if (IS_ERR(desc))
index 98ab08c0aa2d2d13344b6af003e6696129193907..5ac3b88a2e0acff769aad50376b92ce15a0272dd 100644 (file)
@@ -26,7 +26,8 @@ struct acpi_device;
  */
 struct acpi_gpio_info {
        bool gpioint;
-       bool active_low;
+       int polarity;
+       int triggering;
 };
 
 /* gpio suffixes used for ACPI and device tree lookup */
index 7d7ae97476e2c4cec01765e700e0748bece538bc..e38c2bbba94030d27976fec66d637d164fcd1e8c 100644 (file)
@@ -34,8 +34,7 @@ static int get_sem(struct device *dev, u32 *sem)
        u32 data;
        int ret;
 
-       ret = iosf_mbi_read(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_READ, PUNIT_SEMAPHORE,
-                               &data);
+       ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, PUNIT_SEMAPHORE, &data);
        if (ret) {
                dev_err(dev, "iosf failed to read punit semaphore\n");
                return ret;
@@ -50,21 +49,19 @@ static void reset_semaphore(struct device *dev)
 {
        u32 data;
 
-       if (iosf_mbi_read(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_READ,
-                               PUNIT_SEMAPHORE, &data)) {
+       if (iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, PUNIT_SEMAPHORE, &data)) {
                dev_err(dev, "iosf failed to reset punit semaphore during read\n");
                return;
        }
 
        data &= ~PUNIT_SEMAPHORE_BIT;
-       if (iosf_mbi_write(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_WRITE,
-                               PUNIT_SEMAPHORE, data))
+       if (iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, PUNIT_SEMAPHORE, data))
                dev_err(dev, "iosf failed to reset punit semaphore during write\n");
 }
 
 static int baytrail_i2c_acquire(struct dw_i2c_dev *dev)
 {
-       u32 sem;
+       u32 sem = PUNIT_SEMAPHORE_ACQUIRE;
        int ret;
        unsigned long start, end;
 
@@ -77,8 +74,7 @@ static int baytrail_i2c_acquire(struct dw_i2c_dev *dev)
                return 0;
 
        /* host driver writes to side band semaphore register */
-       ret = iosf_mbi_write(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_WRITE,
-                               PUNIT_SEMAPHORE, PUNIT_SEMAPHORE_ACQUIRE);
+       ret = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, PUNIT_SEMAPHORE, sem);
        if (ret) {
                dev_err(dev->dev, "iosf punit semaphore request failed\n");
                return ret;
@@ -102,8 +98,7 @@ static int baytrail_i2c_acquire(struct dw_i2c_dev *dev)
        dev_err(dev->dev, "punit semaphore timed out, resetting\n");
        reset_semaphore(dev->dev);
 
-       ret = iosf_mbi_read(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_READ,
-                               PUNIT_SEMAPHORE, &sem);
+       ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, PUNIT_SEMAPHORE, &sem);
        if (ret)
                dev_err(dev->dev, "iosf failed to read punit semaphore\n");
        else
index 6b00061c37469b98613880ffe71d26118c76d92a..bf72ae740fc17c3dfbab0f1c0004ee29ed73f03b 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/platform_device.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
+#include <linux/property.h>
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/acpi.h>
@@ -122,6 +123,7 @@ static const struct acpi_device_id dw_i2c_acpi_match[] = {
        { "80860F41", 0 },
        { "808622C1", 0 },
        { "AMD0010", ACCESS_INTR_MASK },
+       { "APMC0D0F", 0 },
        { }
 };
 MODULE_DEVICE_TABLE(acpi, dw_i2c_acpi_match);
@@ -134,10 +136,10 @@ static inline int dw_i2c_acpi_configure(struct platform_device *pdev)
 
 static int dw_i2c_plat_probe(struct platform_device *pdev)
 {
+       struct dw_i2c_platform_data *pdata = dev_get_platdata(&pdev->dev);
        struct dw_i2c_dev *dev;
        struct i2c_adapter *adap;
        struct resource *mem;
-       struct dw_i2c_platform_data *pdata;
        int irq, r;
        u32 clk_freq, ht = 0;
 
@@ -161,33 +163,28 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
        /* fast mode by default because of legacy reasons */
        clk_freq = 400000;
 
-       if (has_acpi_companion(&pdev->dev)) {
-               dw_i2c_acpi_configure(pdev);
-       } else if (pdev->dev.of_node) {
-               of_property_read_u32(pdev->dev.of_node,
-                                       "i2c-sda-hold-time-ns", &ht);
-
-               of_property_read_u32(pdev->dev.of_node,
-                                    "i2c-sda-falling-time-ns",
-                                    &dev->sda_falling_time);
-               of_property_read_u32(pdev->dev.of_node,
-                                    "i2c-scl-falling-time-ns",
-                                    &dev->scl_falling_time);
-
-               of_property_read_u32(pdev->dev.of_node, "clock-frequency",
-                                    &clk_freq);
-
-               /* Only standard mode at 100kHz and fast mode at 400kHz
-                * are supported.
-                */
-               if (clk_freq != 100000 && clk_freq != 400000) {
-                       dev_err(&pdev->dev, "Only 100kHz and 400kHz supported");
-                       return -EINVAL;
-               }
+       if (pdata) {
+               clk_freq = pdata->i2c_scl_freq;
        } else {
-               pdata = dev_get_platdata(&pdev->dev);
-               if (pdata)
-                       clk_freq = pdata->i2c_scl_freq;
+               device_property_read_u32(&pdev->dev, "i2c-sda-hold-time-ns",
+                                        &ht);
+               device_property_read_u32(&pdev->dev, "i2c-sda-falling-time-ns",
+                                        &dev->sda_falling_time);
+               device_property_read_u32(&pdev->dev, "i2c-scl-falling-time-ns",
+                                        &dev->scl_falling_time);
+               device_property_read_u32(&pdev->dev, "clock-frequency",
+                                        &clk_freq);
+       }
+
+       if (has_acpi_companion(&pdev->dev))
+               dw_i2c_acpi_configure(pdev);
+
+       /*
+        * Only standard mode at 100kHz and fast mode at 400kHz are supported.
+        */
+       if (clk_freq != 100000 && clk_freq != 400000) {
+               dev_err(&pdev->dev, "Only 100kHz and 400kHz supported");
+               return -EINVAL;
        }
 
        r = i2c_dw_eval_lock_support(dev);
index b6fd9041f82fcffec38325c140092de88adc3e57..06f00d60be4693039db3e3d6447c60e3cc2fbbea 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
 #include <linux/platform_device.h>
+#include <linux/property.h>
 
 #include "intel-lpss.h"
 
@@ -25,6 +26,20 @@ static const struct intel_lpss_platform_info spt_info = {
        .clk_rate = 120000000,
 };
 
+static struct property_entry spt_i2c_properties[] = {
+       PROPERTY_ENTRY_U32("i2c-sda-hold-time-ns", 230),
+       { },
+};
+
+static struct property_set spt_i2c_pset = {
+       .properties = spt_i2c_properties,
+};
+
+static const struct intel_lpss_platform_info spt_i2c_info = {
+       .clk_rate = 120000000,
+       .pset = &spt_i2c_pset,
+};
+
 static const struct intel_lpss_platform_info bxt_info = {
        .clk_rate = 100000000,
 };
@@ -35,8 +50,8 @@ static const struct intel_lpss_platform_info bxt_i2c_info = {
 
 static const struct acpi_device_id intel_lpss_acpi_ids[] = {
        /* SPT */
-       { "INT3446", (kernel_ulong_t)&spt_info },
-       { "INT3447", (kernel_ulong_t)&spt_info },
+       { "INT3446", (kernel_ulong_t)&spt_i2c_info },
+       { "INT3447", (kernel_ulong_t)&spt_i2c_info },
        /* BXT */
        { "80860AAC", (kernel_ulong_t)&bxt_i2c_info },
        { "80860ABC", (kernel_ulong_t)&bxt_info },
index 5bfdfccbb9a1acdea902c05a59394f01950ee5e3..a7136c7ae9fb4b2ed4e51c54534f5f2a99cba8d2 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/pci.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
+#include <linux/property.h>
 
 #include "intel-lpss.h"
 
@@ -65,9 +66,35 @@ static const struct intel_lpss_platform_info spt_info = {
        .clk_rate = 120000000,
 };
 
+static struct property_entry spt_i2c_properties[] = {
+       PROPERTY_ENTRY_U32("i2c-sda-hold-time-ns", 230),
+       { },
+};
+
+static struct property_set spt_i2c_pset = {
+       .properties = spt_i2c_properties,
+};
+
+static const struct intel_lpss_platform_info spt_i2c_info = {
+       .clk_rate = 120000000,
+       .pset = &spt_i2c_pset,
+};
+
+static struct property_entry uart_properties[] = {
+       PROPERTY_ENTRY_U32("reg-io-width", 4),
+       PROPERTY_ENTRY_U32("reg-shift", 2),
+       PROPERTY_ENTRY_BOOL("snps,uart-16550-compatible"),
+       { },
+};
+
+static struct property_set uart_pset = {
+       .properties = uart_properties,
+};
+
 static const struct intel_lpss_platform_info spt_uart_info = {
        .clk_rate = 120000000,
        .clk_con_id = "baudclk",
+       .pset = &uart_pset,
 };
 
 static const struct intel_lpss_platform_info bxt_info = {
@@ -77,6 +104,7 @@ static const struct intel_lpss_platform_info bxt_info = {
 static const struct intel_lpss_platform_info bxt_uart_info = {
        .clk_rate = 100000000,
        .clk_con_id = "baudclk",
+       .pset = &uart_pset,
 };
 
 static const struct intel_lpss_platform_info bxt_i2c_info = {
@@ -121,20 +149,20 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
        { PCI_VDEVICE(INTEL, 0x9d28), (kernel_ulong_t)&spt_uart_info },
        { PCI_VDEVICE(INTEL, 0x9d29), (kernel_ulong_t)&spt_info },
        { PCI_VDEVICE(INTEL, 0x9d2a), (kernel_ulong_t)&spt_info },
-       { PCI_VDEVICE(INTEL, 0x9d60), (kernel_ulong_t)&spt_info },
-       { PCI_VDEVICE(INTEL, 0x9d61), (kernel_ulong_t)&spt_info },
-       { PCI_VDEVICE(INTEL, 0x9d62), (kernel_ulong_t)&spt_info },
-       { PCI_VDEVICE(INTEL, 0x9d63), (kernel_ulong_t)&spt_info },
-       { PCI_VDEVICE(INTEL, 0x9d64), (kernel_ulong_t)&spt_info },
-       { PCI_VDEVICE(INTEL, 0x9d65), (kernel_ulong_t)&spt_info },
+       { PCI_VDEVICE(INTEL, 0x9d60), (kernel_ulong_t)&spt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x9d61), (kernel_ulong_t)&spt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x9d62), (kernel_ulong_t)&spt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x9d63), (kernel_ulong_t)&spt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x9d64), (kernel_ulong_t)&spt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x9d65), (kernel_ulong_t)&spt_i2c_info },
        { PCI_VDEVICE(INTEL, 0x9d66), (kernel_ulong_t)&spt_uart_info },
        /* SPT-H */
        { PCI_VDEVICE(INTEL, 0xa127), (kernel_ulong_t)&spt_uart_info },
        { PCI_VDEVICE(INTEL, 0xa128), (kernel_ulong_t)&spt_uart_info },
        { PCI_VDEVICE(INTEL, 0xa129), (kernel_ulong_t)&spt_info },
        { PCI_VDEVICE(INTEL, 0xa12a), (kernel_ulong_t)&spt_info },
-       { PCI_VDEVICE(INTEL, 0xa160), (kernel_ulong_t)&spt_info },
-       { PCI_VDEVICE(INTEL, 0xa161), (kernel_ulong_t)&spt_info },
+       { PCI_VDEVICE(INTEL, 0xa160), (kernel_ulong_t)&spt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0xa161), (kernel_ulong_t)&spt_i2c_info },
        { PCI_VDEVICE(INTEL, 0xa166), (kernel_ulong_t)&spt_uart_info },
        { }
 };
index 6255513f54c7c2df29da53edb6a1dd2521b2dd4e..1743788f1595671af62102f95979af1f61c5a14d 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/mfd/core.h>
 #include <linux/pm_qos.h>
 #include <linux/pm_runtime.h>
+#include <linux/property.h>
 #include <linux/seq_file.h>
 #include <linux/io-64-nonatomic-lo-hi.h>
 
@@ -72,7 +73,7 @@ struct intel_lpss {
        enum intel_lpss_dev_type type;
        struct clk *clk;
        struct clk_lookup *clock;
-       const struct mfd_cell *cell;
+       struct mfd_cell *cell;
        struct device *dev;
        void __iomem *priv;
        int devid;
@@ -217,6 +218,7 @@ static void intel_lpss_ltr_hide(struct intel_lpss *lpss)
 
 static int intel_lpss_assign_devs(struct intel_lpss *lpss)
 {
+       const struct mfd_cell *cell;
        unsigned int type;
 
        type = lpss->caps & LPSS_PRIV_CAPS_TYPE_MASK;
@@ -224,18 +226,22 @@ static int intel_lpss_assign_devs(struct intel_lpss *lpss)
 
        switch (type) {
        case LPSS_DEV_I2C:
-               lpss->cell = &intel_lpss_i2c_cell;
+               cell = &intel_lpss_i2c_cell;
                break;
        case LPSS_DEV_UART:
-               lpss->cell = &intel_lpss_uart_cell;
+               cell = &intel_lpss_uart_cell;
                break;
        case LPSS_DEV_SPI:
-               lpss->cell = &intel_lpss_spi_cell;
+               cell = &intel_lpss_spi_cell;
                break;
        default:
                return -ENODEV;
        }
 
+       lpss->cell = devm_kmemdup(lpss->dev, cell, sizeof(*cell), GFP_KERNEL);
+       if (!lpss->cell)
+               return -ENOMEM;
+
        lpss->type = type;
 
        return 0;
@@ -401,6 +407,8 @@ int intel_lpss_probe(struct device *dev,
        if (ret)
                return ret;
 
+       lpss->cell->pset = info->pset;
+
        intel_lpss_init_dev(lpss);
 
        lpss->devid = ida_simple_get(&intel_lpss_devid_ida, 0, 0, GFP_KERNEL);
index 2c7f8d7c0595e2d849183dfd0db91d2d945daa10..0dcea9eb2d0308cf63de7d79b826eff36f65f32b 100644 (file)
 
 struct device;
 struct resource;
+struct property_set;
 
 struct intel_lpss_platform_info {
        struct resource *mem;
        int irq;
        unsigned long clk_rate;
        const char *clk_con_id;
+       struct property_set *pset;
 };
 
 int intel_lpss_probe(struct device *dev,
index 60b60dc63dddbc610d0ac1cf02111066b4af5095..88bd1b1e47bedb650c83771de09d7a9e85316ee4 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/acpi.h>
+#include <linux/property.h>
 #include <linux/mfd/core.h>
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
@@ -192,6 +193,12 @@ static int mfd_add_device(struct device *parent, int id,
                        goto fail_alias;
        }
 
+       if (cell->pset) {
+               ret = platform_device_add_properties(pdev, cell->pset);
+               if (ret)
+                       goto fail_alias;
+       }
+
        ret = mfd_platform_add_cell(pdev, cell, usage_count);
        if (ret)
                goto fail_alias;
index 6146a293601a7fea098a353aeb11fc803f5523a4..368de5e5a04f64c46003a131a49546724d6fc7a6 100644 (file)
@@ -6366,12 +6366,13 @@ static u64 ath10k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 
 static int ath10k_ampdu_action(struct ieee80211_hw *hw,
                               struct ieee80211_vif *vif,
-                              enum ieee80211_ampdu_mlme_action action,
-                              struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-                              u8 buf_size, bool amsdu)
+                              struct ieee80211_ampdu_params *params)
 {
        struct ath10k *ar = hw->priv;
        struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+       struct ieee80211_sta *sta = params->sta;
+       enum ieee80211_ampdu_mlme_action action = params->action;
+       u16 tid = params->tid;
 
        ath10k_dbg(ar, ATH10K_DBG_MAC, "mac ampdu vdev_id %i sta %pM tid %hu action %d\n",
                   arvif->vdev_id, sta->addr, tid, action);
index fe1fd1a5ae1502a2c5d2947d1a40ff3ee6193d76..639294a9e34df6b2461b4c4c8052af75cbf2b258 100644 (file)
@@ -1657,13 +1657,14 @@ static void ath9k_htc_reset_tsf(struct ieee80211_hw *hw,
 
 static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw,
                                  struct ieee80211_vif *vif,
-                                 enum ieee80211_ampdu_mlme_action action,
-                                 struct ieee80211_sta *sta,
-                                 u16 tid, u16 *ssn, u8 buf_size, bool amsdu)
+                                 struct ieee80211_ampdu_params *params)
 {
        struct ath9k_htc_priv *priv = hw->priv;
        struct ath9k_htc_sta *ista;
        int ret = 0;
+       struct ieee80211_sta *sta = params->sta;
+       enum ieee80211_ampdu_mlme_action action = params->action;
+       u16 tid = params->tid;
 
        mutex_lock(&priv->mutex);
        ath9k_htc_ps_wakeup(priv);
index c1b33fdcca0875a20cd2be3b54b21e46c37b725c..cf58a304e9f0aa08d577dc00d49361b568f450d3 100644 (file)
@@ -1864,14 +1864,16 @@ static void ath9k_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 
 static int ath9k_ampdu_action(struct ieee80211_hw *hw,
                              struct ieee80211_vif *vif,
-                             enum ieee80211_ampdu_mlme_action action,
-                             struct ieee80211_sta *sta,
-                             u16 tid, u16 *ssn, u8 buf_size, bool amsdu)
+                             struct ieee80211_ampdu_params *params)
 {
        struct ath_softc *sc = hw->priv;
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
        bool flush = false;
        int ret = 0;
+       struct ieee80211_sta *sta = params->sta;
+       enum ieee80211_ampdu_mlme_action action = params->action;
+       u16 tid = params->tid;
+       u16 *ssn = &params->ssn;
 
        mutex_lock(&sc->mutex);
 
index 19d3d64416bf66825eb113590474b4e4a68f8ec2..4d1527a2e292a2ba2d29907554625cf0fbb980f4 100644 (file)
@@ -1413,10 +1413,12 @@ static void carl9170_ampdu_work(struct work_struct *work)
 
 static int carl9170_op_ampdu_action(struct ieee80211_hw *hw,
                                    struct ieee80211_vif *vif,
-                                   enum ieee80211_ampdu_mlme_action action,
-                                   struct ieee80211_sta *sta,
-                                   u16 tid, u16 *ssn, u8 buf_size, bool amsdu)
+                                   struct ieee80211_ampdu_params *params)
 {
+       struct ieee80211_sta *sta = params->sta;
+       enum ieee80211_ampdu_mlme_action action = params->action;
+       u16 tid = params->tid;
+       u16 *ssn = &params->ssn;
        struct ar9170 *ar = hw->priv;
        struct carl9170_sta_info *sta_info = (void *) sta->drv_priv;
        struct carl9170_sta_tid *tid_info;
index 7c169abdbafee95ccfe8f461e670fbb8ab5ca5eb..a27279c2c6950913c0b1f14fd4cacdd3bc650428 100644 (file)
@@ -857,12 +857,14 @@ static int wcn36xx_resume(struct ieee80211_hw *hw)
 
 static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
                    struct ieee80211_vif *vif,
-                   enum ieee80211_ampdu_mlme_action action,
-                   struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-                   u8 buf_size, bool amsdu)
+                   struct ieee80211_ampdu_params *params)
 {
        struct wcn36xx *wcn = hw->priv;
        struct wcn36xx_sta *sta_priv = NULL;
+       struct ieee80211_sta *sta = params->sta;
+       enum ieee80211_ampdu_mlme_action action = params->action;
+       u16 tid = params->tid;
+       u16 *ssn = &params->ssn;
 
        wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n",
                    action, tid);
index 20d07ef679e89d467170abae532819f36f283821..1f231cd0813861fa24bafdb378e2e8cbb0ed3ae1 100644 (file)
@@ -422,6 +422,11 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,
        if (sme->privacy && !rsn_eid)
                wil_info(wil, "WSC connection\n");
 
+       if (sme->pbss) {
+               wil_err(wil, "connect - PBSS not yet supported\n");
+               return -EOPNOTSUPP;
+       }
+
        bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid,
                               sme->ssid, sme->ssid_len,
                               IEEE80211_BSS_TYPE_ESS, IEEE80211_PRIVACY_ANY);
@@ -870,6 +875,11 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy,
                return -EINVAL;
        }
 
+       if (info->pbss) {
+               wil_err(wil, "AP: PBSS not yet supported\n");
+               return -EOPNOTSUPP;
+       }
+
        switch (info->hidden_ssid) {
        case NL80211_HIDDEN_SSID_NOT_IN_USE:
                hidden_ssid = WMI_HIDDEN_SSID_DISABLED;
index bec2dc1ca2e406bcf4ac0ee0d00fa27a704cf7f2..61ae2768132a0b16f0f98a57b3319c82adfda95b 100644 (file)
@@ -818,13 +818,15 @@ brcms_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 static int
 brcms_ops_ampdu_action(struct ieee80211_hw *hw,
                    struct ieee80211_vif *vif,
-                   enum ieee80211_ampdu_mlme_action action,
-                   struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-                   u8 buf_size, bool amsdu)
+                   struct ieee80211_ampdu_params *params)
 {
        struct brcms_info *wl = hw->priv;
        struct scb *scb = &wl->wlc->pri_scb;
        int status;
+       struct ieee80211_sta *sta = params->sta;
+       enum ieee80211_ampdu_mlme_action action = params->action;
+       u16 tid = params->tid;
+       u8 buf_size = params->buf_size;
 
        if (WARN_ON(scb->magic != SCB_MAGIC))
                return -EIDRM;
index fd38aa0763e4f5f30384d29249e7bf205b7d5eeb..b75f4ef3cdc7b278ec837f83fd576444f5ce0008 100644 (file)
@@ -5982,12 +5982,14 @@ il4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 
 int
 il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-                       enum ieee80211_ampdu_mlme_action action,
-                       struct ieee80211_sta *sta, u16 tid, u16 * ssn,
-                       u8 buf_size, bool amsdu)
+                       struct ieee80211_ampdu_params *params)
 {
        struct il_priv *il = hw->priv;
        int ret = -EINVAL;
+       struct ieee80211_sta *sta = params->sta;
+       enum ieee80211_ampdu_mlme_action action = params->action;
+       u16 tid = params->tid;
+       u16 *ssn = &params->ssn;
 
        D_HT("A-MPDU action on addr %pM tid %d\n", sta->addr, tid);
 
index 8ab8706f942267fcd2467928b1cbdf248a05921f..e432715e02d89dedcce89615d855233662c26d82 100644 (file)
@@ -182,9 +182,7 @@ void il4965_mac_update_tkip_key(struct ieee80211_hw *hw,
                                struct ieee80211_sta *sta, u32 iv32,
                                u16 *phase1key);
 int il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-                           enum ieee80211_ampdu_mlme_action action,
-                           struct ieee80211_sta *sta, u16 tid, u16 * ssn,
-                           u8 buf_size, bool amsdu);
+                           struct ieee80211_ampdu_params *params);
 int il4965_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                       struct ieee80211_sta *sta);
 void
index 4841be2aa4994cafa42254f362753136f5debfa5..1799469268ea8e8a24d8d3fd33b0221b92ccfcd3 100644 (file)
@@ -943,14 +943,16 @@ static void iwlagn_wowlan_program_keys(struct ieee80211_hw *hw,
        switch (key->cipher) {
        case WLAN_CIPHER_SUITE_TKIP:
                if (sta) {
+                       u64 pn64;
+
                        tkip_sc = data->rsc_tsc->all_tsc_rsc.tkip.unicast_rsc;
                        tkip_tx_sc = &data->rsc_tsc->all_tsc_rsc.tkip.tsc;
 
                        rx_p1ks = data->tkip->rx_uni;
 
-                       ieee80211_get_key_tx_seq(key, &seq);
-                       tkip_tx_sc->iv16 = cpu_to_le16(seq.tkip.iv16);
-                       tkip_tx_sc->iv32 = cpu_to_le32(seq.tkip.iv32);
+                       pn64 = atomic64_read(&key->tx_pn);
+                       tkip_tx_sc->iv16 = cpu_to_le16(TKIP_PN_TO_IV16(pn64));
+                       tkip_tx_sc->iv32 = cpu_to_le32(TKIP_PN_TO_IV32(pn64));
 
                        ieee80211_get_tkip_p1k_iv(key, seq.tkip.iv32, p1k);
                        iwlagn_convert_p1k(p1k, data->tkip->tx.p1k);
@@ -996,19 +998,13 @@ static void iwlagn_wowlan_program_keys(struct ieee80211_hw *hw,
                break;
        case WLAN_CIPHER_SUITE_CCMP:
                if (sta) {
-                       u8 *pn = seq.ccmp.pn;
+                       u64 pn64;
 
                        aes_sc = data->rsc_tsc->all_tsc_rsc.aes.unicast_rsc;
                        aes_tx_sc = &data->rsc_tsc->all_tsc_rsc.aes.tsc;
 
-                       ieee80211_get_key_tx_seq(key, &seq);
-                       aes_tx_sc->pn = cpu_to_le64(
-                                       (u64)pn[5] |
-                                       ((u64)pn[4] << 8) |
-                                       ((u64)pn[3] << 16) |
-                                       ((u64)pn[2] << 24) |
-                                       ((u64)pn[1] << 32) |
-                                       ((u64)pn[0] << 40));
+                       pn64 = atomic64_read(&key->tx_pn);
+                       aes_tx_sc->pn = cpu_to_le64(pn64);
                } else
                        aes_sc = data->rsc_tsc->all_tsc_rsc.aes.multicast_rsc;
 
index 4db4cb7aa73aa8593b0a3061281ab2c013885690..c63ea79571ff5f0d6b0bbfd07b4a6faba42f1593 100644 (file)
@@ -732,12 +732,15 @@ static inline bool iwl_enable_tx_ampdu(const struct iwl_cfg *cfg)
 
 static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
                                   struct ieee80211_vif *vif,
-                                  enum ieee80211_ampdu_mlme_action action,
-                                  struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-                                  u8 buf_size, bool amsdu)
+                                  struct ieee80211_ampdu_params *params)
 {
        struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
        int ret = -EINVAL;
+       struct ieee80211_sta *sta = params->sta;
+       enum ieee80211_ampdu_mlme_action action = params->action;
+       u16 tid = params->tid;
+       u16 *ssn = &params->ssn;
+       u8 buf_size = params->buf_size;
        struct iwl_station_priv *sta_priv = (void *) sta->drv_priv;
 
        IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",
index 346376187ef849455ae1b60da0039cc2e48fd633..5214482a04030fc3ca0325891c7e9c8f9873b420 100644 (file)
@@ -251,16 +251,19 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
                return;
        case WLAN_CIPHER_SUITE_TKIP:
                if (sta) {
+                       u64 pn64;
+
                        tkip_sc = data->rsc_tsc->all_tsc_rsc.tkip.unicast_rsc;
                        tkip_tx_sc = &data->rsc_tsc->all_tsc_rsc.tkip.tsc;
 
                        rx_p1ks = data->tkip->rx_uni;
 
-                       ieee80211_get_key_tx_seq(key, &seq);
-                       tkip_tx_sc->iv16 = cpu_to_le16(seq.tkip.iv16);
-                       tkip_tx_sc->iv32 = cpu_to_le32(seq.tkip.iv32);
+                       pn64 = atomic64_read(&key->tx_pn);
+                       tkip_tx_sc->iv16 = cpu_to_le16(TKIP_PN_TO_IV16(pn64));
+                       tkip_tx_sc->iv32 = cpu_to_le32(TKIP_PN_TO_IV32(pn64));
 
-                       ieee80211_get_tkip_p1k_iv(key, seq.tkip.iv32, p1k);
+                       ieee80211_get_tkip_p1k_iv(key, TKIP_PN_TO_IV32(pn64),
+                                                 p1k);
                        iwl_mvm_convert_p1k(p1k, data->tkip->tx.p1k);
 
                        memcpy(data->tkip->mic_keys.tx,
@@ -1614,7 +1617,9 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
                case WLAN_CIPHER_SUITE_TKIP:
                        iwl_mvm_tkip_sc_to_seq(&sc->tkip.tsc, &seq);
                        iwl_mvm_set_tkip_rx_seq(sc->tkip.unicast_rsc, key);
-                       ieee80211_set_key_tx_seq(key, &seq);
+                       atomic64_set(&key->tx_pn,
+                                    (u64)seq.tkip.iv16 |
+                                    ((u64)seq.tkip.iv32 << 16));
                        break;
                }
 
index 01476f5456956b199b262d58efa840eda62dbdb2..53156810185d432a1192061ee1c39ede81112a40 100644 (file)
@@ -837,13 +837,16 @@ iwl_mvm_ampdu_check_trigger(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 
 static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
                                    struct ieee80211_vif *vif,
-                                   enum ieee80211_ampdu_mlme_action action,
-                                   struct ieee80211_sta *sta, u16 tid,
-                                   u16 *ssn, u8 buf_size, bool amsdu)
+                                   struct ieee80211_ampdu_params *params)
 {
        struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
        int ret;
        bool tx_agg_ref = false;
+       struct ieee80211_sta *sta = params->sta;
+       enum ieee80211_ampdu_mlme_action action = params->action;
+       u16 tid = params->tid;
+       u16 *ssn = &params->ssn;
+       u8 buf_size = params->buf_size;
 
        IWL_DEBUG_HT(mvm, "A-MPDU action on addr %pM tid %d: action %d\n",
                     sta->addr, tid, action);
@@ -2582,7 +2585,7 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
        switch (key->cipher) {
        case WLAN_CIPHER_SUITE_TKIP:
                key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
-               key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+               key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE;
                break;
        case WLAN_CIPHER_SUITE_CCMP:
                key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE;
index 5d73db2534a0a24a54d9edd07c341bc28822a7de..caec54ba617a12e6b8bf8f3172425a493f15a26c 100644 (file)
@@ -299,6 +299,8 @@ static void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm,
 
        case WLAN_CIPHER_SUITE_TKIP:
                tx_cmd->sec_ctl = TX_CMD_SEC_TKIP;
+               pn = atomic64_inc_return(&keyconf->tx_pn);
+               ieee80211_tkip_add_iv(crypto_hdr, keyconf, pn);
                ieee80211_get_tkip_p2k(keyconf, skb_frag, tx_cmd->key);
                break;
 
index c32889a1e39cf53d4e2d1ab3a4bfc2b8b492af1e..ee37af1066d2fb7efb2a82e9ad3b7723f9895ed0 100644 (file)
@@ -1333,10 +1333,8 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
        data->tx_bytes += skb->len;
        ack = mac80211_hwsim_tx_frame_no_nl(hw, skb, channel);
 
-       if (ack && skb->len >= 16) {
-               struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+       if (ack && skb->len >= 16)
                mac80211_hwsim_monitor_ack(channel, hdr->addr2);
-       }
 
        ieee80211_tx_info_clear_status(txi);
 
@@ -1845,10 +1843,12 @@ static int mac80211_hwsim_testmode_cmd(struct ieee80211_hw *hw,
 
 static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw,
                                       struct ieee80211_vif *vif,
-                                      enum ieee80211_ampdu_mlme_action action,
-                                      struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-                                      u8 buf_size, bool amsdu)
+                                      struct ieee80211_ampdu_params *params)
 {
+       struct ieee80211_sta *sta = params->sta;
+       enum ieee80211_ampdu_mlme_action action = params->action;
+       u16 tid = params->tid;
+
        switch (action) {
        case IEEE80211_AMPDU_TX_START:
                ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
index 30e3aaae32e2288ed1f7541b6da7a42eb6a8729a..088429d0a634d8c4372d45e2dc1cd3b7d2fabf1e 100644 (file)
@@ -5421,11 +5421,13 @@ static int mwl8k_get_survey(struct ieee80211_hw *hw, int idx,
 
 static int
 mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-                  enum ieee80211_ampdu_mlme_action action,
-                  struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-                  u8 buf_size, bool amsdu)
+                  struct ieee80211_ampdu_params *params)
 {
-
+       struct ieee80211_sta *sta = params->sta;
+       enum ieee80211_ampdu_mlme_action action = params->action;
+       u16 tid = params->tid;
+       u16 *ssn = &params->ssn;
+       u8 buf_size = params->buf_size;
        int i, rc = 0;
        struct mwl8k_priv *priv = hw->priv;
        struct mwl8k_ampdu_stream *stream;
index f715eee398510df829a61ba0f431610d1ab32baa..e70dd95239117f7e0ef8a2d668b6798727a06b46 100644 (file)
@@ -334,11 +334,13 @@ static int mt7601u_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
 
 static int
 mt76_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-                 enum ieee80211_ampdu_mlme_action action,
-                 struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size,
-                 bool amsdu)
+                 struct ieee80211_ampdu_params *params)
 {
        struct mt7601u_dev *dev = hw->priv;
+       struct ieee80211_sta *sta = params->sta;
+       enum ieee80211_ampdu_mlme_action action = params->action;
+       u16 tid = params->tid;
+       u16 *ssn = &params->ssn;
        struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv;
 
        WARN_ON(msta->wcid.idx > GROUP_WCID(0));
index 9733b31a780d380fd2bfd550efe155943b0fdb34..69c1c09687a30c5c2338cc84f12981eb4133d40d 100644 (file)
@@ -7935,10 +7935,11 @@ u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 EXPORT_SYMBOL_GPL(rt2800_get_tsf);
 
 int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-                       enum ieee80211_ampdu_mlme_action action,
-                       struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-                       u8 buf_size, bool amsdu)
+                       struct ieee80211_ampdu_params *params)
 {
+       struct ieee80211_sta *sta = params->sta;
+       enum ieee80211_ampdu_mlme_action action = params->action;
+       u16 tid = params->tid;
        struct rt2x00_sta *sta_priv = (struct rt2x00_sta *)sta->drv_priv;
        int ret = 0;
 
index 440790b92b19e2927fd9b9d7446cbd3c8eef4f30..83f1a44fb9b481cb5f2a8dda9e9914b8113e91bb 100644 (file)
@@ -218,9 +218,7 @@ int rt2800_conf_tx(struct ieee80211_hw *hw,
                   const struct ieee80211_tx_queue_params *params);
 u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
 int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-                       enum ieee80211_ampdu_mlme_action action,
-                       struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-                       u8 buf_size, bool amsdu);
+                       struct ieee80211_ampdu_params *params);
 int rt2800_get_survey(struct ieee80211_hw *hw, int idx,
                      struct survey_info *survey);
 void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev);
index 6aed923a709ae3606225307cdcb2b7170442e11d..7d820c3953754260c05a5f7e21478e1cbf14555e 100644 (file)
@@ -5375,13 +5375,13 @@ static int rtl8xxxu_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 
 static int
 rtl8xxxu_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-                     enum ieee80211_ampdu_mlme_action action,
-                     struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size,
-                     bool amsdu)
+                     struct ieee80211_ampdu_params *params)
 {
        struct rtl8xxxu_priv *priv = hw->priv;
        struct device *dev = &priv->udev->dev;
        u8 ampdu_factor, ampdu_density;
+       struct ieee80211_sta *sta = params->sta;
+       enum ieee80211_ampdu_mlme_action action = params->action;
 
        switch (action) {
        case IEEE80211_AMPDU_TX_START:
index 4ae421ef30d94f4f8bc93d85645eeda4548ba835..f2507610314ba81b94accf2a94cfb0284c11b641 100644 (file)
@@ -1371,11 +1371,13 @@ static void rtl_op_sta_notify(struct ieee80211_hw *hw,
 
 static int rtl_op_ampdu_action(struct ieee80211_hw *hw,
                               struct ieee80211_vif *vif,
-                              enum ieee80211_ampdu_mlme_action action,
-                              struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-                              u8 buf_size, bool amsdu)
+                              struct ieee80211_ampdu_params *params)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct ieee80211_sta *sta = params->sta;
+       enum ieee80211_ampdu_mlme_action action = params->action;
+       u16 tid = params->tid;
+       u16 *ssn = &params->ssn;
 
        switch (action) {
        case IEEE80211_AMPDU_TX_START:
index b5bcc933a2a683df412139b1204fee320096a889..4df992de7d0731508a6c42fccf51096928156e9e 100644 (file)
@@ -659,29 +659,24 @@ static int rsi_mac80211_set_key(struct ieee80211_hw *hw,
  *                              informs the f/w regarding this.
  * @hw: Pointer to the ieee80211_hw structure.
  * @vif: Pointer to the ieee80211_vif structure.
- * @action: ieee80211_ampdu_mlme_action enum.
- * @sta: Pointer to the ieee80211_sta structure.
- * @tid: Traffic identifier.
- * @ssn: Pointer to ssn value.
- * @buf_size: Buffer size (for kernel version > 2.6.38).
- * @amsdu: is AMSDU in AMPDU allowed
+ * @params: Pointer to A-MPDU action parameters
  *
  * Return: status: 0 on success, negative error code on failure.
  */
 static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw,
                                     struct ieee80211_vif *vif,
-                                    enum ieee80211_ampdu_mlme_action action,
-                                    struct ieee80211_sta *sta,
-                                    unsigned short tid,
-                                    unsigned short *ssn,
-                                    unsigned char buf_size,
-                                    bool amsdu)
+                                    struct ieee80211_ampdu_params *params)
 {
        int status = -EOPNOTSUPP;
        struct rsi_hw *adapter = hw->priv;
        struct rsi_common *common = adapter->priv;
        u16 seq_no = 0;
        u8 ii = 0;
+       struct ieee80211_sta *sta = params->sta;
+       enum ieee80211_ampdu_mlme_action action = params->action;
+       u16 tid = params->tid;
+       u16 *ssn = &params->ssn;
+       u8 buf_size = params->buf_size;
 
        for (ii = 0; ii < RSI_MAX_VIFS; ii++) {
                if (vif == adapter->vifs[ii])
index 06321c799c902689825c89098c796e875c737079..d0ddcde6c695fb6c5efd9b2283c76e98328fdbdf 100644 (file)
@@ -2129,9 +2129,7 @@ void cw1200_mcast_timeout(unsigned long arg)
 
 int cw1200_ampdu_action(struct ieee80211_hw *hw,
                        struct ieee80211_vif *vif,
-                       enum ieee80211_ampdu_mlme_action action,
-                       struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-                       u8 buf_size, bool amsdu)
+                       struct ieee80211_ampdu_params *params)
 {
        /* Aggregation is implemented fully in firmware,
         * including block ack negotiation. Do not allow
index bebb3379017f6d40c3cd58b92ddfaabab1259f59..a0bacaa39b3193f230c61526afe6bdc68f38b7a0 100644 (file)
@@ -109,9 +109,7 @@ void cw1200_bss_info_changed(struct ieee80211_hw *dev,
                             u32 changed);
 int cw1200_ampdu_action(struct ieee80211_hw *hw,
                        struct ieee80211_vif *vif,
-                       enum ieee80211_ampdu_mlme_action action,
-                       struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-                       u8 buf_size, bool amsdu);
+                       struct ieee80211_ampdu_params *params);
 
 void cw1200_suspend_resume(struct cw1200_common *priv,
                          struct wsm_suspend_resume *arg);
index d1109c4f0f0d1d7570ec373734db3f93117556f9..45662cf3169f78dd20554cde3373336f84cb6516 100644 (file)
@@ -5187,14 +5187,16 @@ out:
 
 static int wl1271_op_ampdu_action(struct ieee80211_hw *hw,
                                  struct ieee80211_vif *vif,
-                                 enum ieee80211_ampdu_mlme_action action,
-                                 struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-                                 u8 buf_size, bool amsdu)
+                                 struct ieee80211_ampdu_params *params)
 {
        struct wl1271 *wl = hw->priv;
        struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
        int ret;
        u8 hlid, *ba_bitmap;
+       struct ieee80211_sta *sta = params->sta;
+       enum ieee80211_ampdu_mlme_action action = params->action;
+       u16 tid = params->tid;
+       u16 *ssn = &params->ssn;
 
        wl1271_debug(DEBUG_MAC80211, "mac80211 ampdu action %d tid %d", action,
                     tid);
index d3f32d6417ef099c74e8f9ec1728225d9bc67974..9a033e8ee9a438317cc67aecf90ff7d8793846a4 100644 (file)
@@ -531,7 +531,7 @@ static bool acpi_pci_need_resume(struct pci_dev *dev)
        return !!adev->power.flags.dsw_present;
 }
 
-static struct pci_platform_pm_ops acpi_pci_platform_pm = {
+static const struct pci_platform_pm_ops acpi_pci_platform_pm = {
        .is_manageable = acpi_pci_power_manageable,
        .set_state = acpi_pci_set_power_state,
        .choose_state = acpi_pci_choose_state,
index 314db8c1047a30228f68072f820d7f40babc2ad0..d1a7105b92760fe2b6bc269b238cb0000ed74527 100644 (file)
@@ -527,9 +527,9 @@ static void pci_restore_bars(struct pci_dev *dev)
                pci_update_resource(dev, i);
 }
 
-static struct pci_platform_pm_ops *pci_platform_pm;
+static const struct pci_platform_pm_ops *pci_platform_pm;
 
-int pci_set_platform_pm(struct pci_platform_pm_ops *ops)
+int pci_set_platform_pm(const struct pci_platform_pm_ops *ops)
 {
        if (!ops->is_manageable || !ops->set_state || !ops->choose_state
            || !ops->sleep_wake)
index d390fc1475eccf9f77491b5b401a823067b2995b..f6f151a421470d88ca0be2ca0ad8fc657d587833 100644 (file)
@@ -68,7 +68,7 @@ struct pci_platform_pm_ops {
        bool (*need_resume)(struct pci_dev *dev);
 };
 
-int pci_set_platform_pm(struct pci_platform_pm_ops *ops);
+int pci_set_platform_pm(const struct pci_platform_pm_ops *ops);
 void pci_update_current_state(struct pci_dev *dev, pci_power_t state);
 void pci_power_up(struct pci_dev *dev);
 void pci_disable_enabled_device(struct pci_dev *dev);
index f2d77fe696ac6577b605fb63e6a3b587d2121e74..cb8a9c2a3a1f6df4c3d7fdb1306676088e8bcbfc 100644 (file)
@@ -43,8 +43,6 @@ MODULE_LICENSE("GPL");
 
 #define DELL_EVENT_GUID "9DBB5994-A997-11DA-B012-B622A1EF5492"
 
-static int acpi_video;
-
 MODULE_ALIAS("wmi:"DELL_EVENT_GUID);
 
 /*
@@ -159,7 +157,8 @@ static void dell_wmi_process_key(int reported_key)
 
        /* Don't report brightness notifications that will also come via ACPI */
        if ((key->keycode == KEY_BRIGHTNESSUP ||
-            key->keycode == KEY_BRIGHTNESSDOWN) && acpi_video)
+            key->keycode == KEY_BRIGHTNESSDOWN) &&
+           acpi_video_handles_brightness_key_presses())
                return;
 
        sparse_keymap_report_entry(dell_wmi_input_dev, key, 1, true);
@@ -398,7 +397,6 @@ static int __init dell_wmi_init(void)
        }
 
        dmi_walk(find_hk_type, NULL);
-       acpi_video = acpi_video_get_backlight_type() != acpi_backlight_vendor;
 
        err = dell_wmi_input_setup();
        if (err)
index 0bed4733c4f04925831a174b6b58e674ca2fe56c..f453d5dc085eb2d7e595bb70f04f4529cf423c6b 100644 (file)
@@ -3488,7 +3488,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
        /* Do not issue duplicate brightness change events to
         * userspace. tpacpi_detect_brightness_capabilities() must have
         * been called before this point  */
-       if (acpi_video_get_backlight_type() != acpi_backlight_vendor) {
+       if (acpi_video_handles_brightness_key_presses()) {
                pr_info("This ThinkPad has standard ACPI backlight "
                        "brightness control, supported by the ACPI "
                        "video driver\n");
index 153a493b5413e06482dd9909bf0301e6d26eae1f..63452f20e3e97e5f567cec533ac74a4ab100ebf8 100644 (file)
@@ -74,7 +74,6 @@ void pnp_device_detach(struct pnp_dev *pnp_dev)
        if (pnp_dev->status == PNP_ATTACHED)
                pnp_dev->status = PNP_READY;
        mutex_unlock(&pnp_lock);
-       pnp_disable_dev(pnp_dev);
 }
 
 static int pnp_device_probe(struct device *dev)
@@ -131,6 +130,11 @@ static int pnp_device_remove(struct device *dev)
                        drv->remove(pnp_dev);
                pnp_dev->driver = NULL;
        }
+
+       if (pnp_dev->active &&
+           (!drv || !(drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE)))
+               pnp_disable_dev(pnp_dev);
+
        pnp_device_detach(pnp_dev);
        return 0;
 }
index 943c1cb9566c803b168aac842aa00187a4627720..f700723ca5d6b1a8a0c342c568908f9c53aa2435 100644 (file)
@@ -343,6 +343,7 @@ static void quirk_amd_mmconfig_area(struct pnp_dev *dev)
 static const unsigned int mch_quirk_devices[] = {
        0x0154, /* Ivy Bridge */
        0x0c00, /* Haswell */
+       0x1604, /* Broadwell */
 };
 
 static struct pci_dev *get_intel_host(void)
index 48747c28a43d4ac2fc1bed10f29cd1224ddd10f0..6c592dc71aeef9c360123365d2b177cda37ac0e8 100644 (file)
@@ -388,7 +388,7 @@ static int get_domain_enable(struct powercap_zone *power_zone, bool *mode)
 }
 
 /* per RAPL domain ops, in the order of rapl_domain_type */
-static struct powercap_zone_ops zone_ops[] = {
+static const struct powercap_zone_ops zone_ops[] = {
        /* RAPL_DOMAIN_PACKAGE */
        {
                .get_energy_uj = get_energy_counter,
@@ -584,7 +584,7 @@ static int get_max_power(struct powercap_zone *power_zone, int id,
        return ret;
 }
 
-static struct powercap_zone_constraint_ops constraint_ops = {
+static const struct powercap_zone_constraint_ops constraint_ops = {
        .set_power_limit_uw = set_power_limit,
        .get_power_limit_uw = get_current_power_limit,
        .set_time_window_us = set_time_window,
@@ -988,16 +988,16 @@ static void set_floor_freq_atom(struct rapl_domain *rd, bool enable)
        }
 
        if (!power_ctrl_orig_val)
-               iosf_mbi_read(BT_MBI_UNIT_PMC, BT_MBI_PMC_READ,
-                       rapl_defaults->floor_freq_reg_addr,
-                               &power_ctrl_orig_val);
+               iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_CR_READ,
+                             rapl_defaults->floor_freq_reg_addr,
+                             &power_ctrl_orig_val);
        mdata = power_ctrl_orig_val;
        if (enable) {
                mdata &= ~(0x7f << 8);
                mdata |= 1 << 8;
        }
-       iosf_mbi_write(BT_MBI_UNIT_PMC, BT_MBI_PMC_WRITE,
-               rapl_defaults->floor_freq_reg_addr, mdata);
+       iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_CR_WRITE,
+                      rapl_defaults->floor_freq_reg_addr, mdata);
 }
 
 static u64 rapl_compute_time_window_core(struct rapl_package *rp, u64 value,
index 84419af16f777095687eddb59d74c7ca6762e3bb..14bde0db8c245680fd010bf2f0aa39093af5a4c2 100644 (file)
@@ -293,8 +293,8 @@ err_alloc:
 }
 
 static int create_constraints(struct powercap_zone *power_zone,
-                               int nr_constraints,
-                               struct powercap_zone_constraint_ops *const_ops)
+                       int nr_constraints,
+                       const struct powercap_zone_constraint_ops *const_ops)
 {
        int i;
        int ret = 0;
@@ -492,13 +492,13 @@ static struct class powercap_class = {
 };
 
 struct powercap_zone *powercap_register_zone(
-                               struct powercap_zone *power_zone,
-                               struct powercap_control_type *control_type,
-                               const char *name,
-                               struct powercap_zone *parent,
-                               const struct powercap_zone_ops *ops,
-                               int nr_constraints,
-                               struct powercap_zone_constraint_ops *const_ops)
+                       struct powercap_zone *power_zone,
+                       struct powercap_control_type *control_type,
+                       const char *name,
+                       struct powercap_zone *parent,
+                       const struct powercap_zone_ops *ops,
+                       int nr_constraints,
+                       const struct powercap_zone_constraint_ops *const_ops)
 {
        int result;
        int nr_attrs;
index dee1cb87d24f4aaca1fd3d2e43b8101d3bf6e246..151b01c25b405cbea08f66849e722f546d407adc 100644 (file)
@@ -1623,6 +1623,9 @@ static acpi_status acpi_spi_add_device(acpi_handle handle, u32 level,
                return AE_OK;
        }
 
+       if (spi->irq < 0)
+               spi->irq = acpi_dev_gpio_irq_get(adev, 0);
+
        adev->power.flags.ignore_parent = true;
        strlcpy(spi->modalias, acpi_device_hid(adev), sizeof(spi->modalias));
        if (spi_add_device(spi)) {
index b668db6a45fbd98efd1aa8d6dba85d096086e61d..1a2dda09b69d70f706fc2420b633e34492935a5c 100644 (file)
@@ -1210,7 +1210,7 @@ static void vnt_fill_txkey(struct ieee80211_hdr *hdr, u8 *key_buffer,
                           struct sk_buff *skb, u16 payload_len,
                           struct vnt_mic_hdr *mic_hdr)
 {
-       struct ieee80211_key_seq seq;
+       u64 pn64;
        u8 *iv = ((u8 *)hdr + ieee80211_get_hdrlen_from_skb(skb));
 
        /* strip header and icv len from payload */
@@ -1243,9 +1243,13 @@ static void vnt_fill_txkey(struct ieee80211_hdr *hdr, u8 *key_buffer,
                mic_hdr->payload_len = cpu_to_be16(payload_len);
                ether_addr_copy(mic_hdr->mic_addr2, hdr->addr2);
 
-               ieee80211_get_key_tx_seq(tx_key, &seq);
-
-               memcpy(mic_hdr->ccmp_pn, seq.ccmp.pn, IEEE80211_CCMP_PN_LEN);
+               pn64 = atomic64_read(&tx_key->tx_pn);
+               mic_hdr->ccmp_pn[5] = pn64;
+               mic_hdr->ccmp_pn[4] = pn64 >> 8;
+               mic_hdr->ccmp_pn[3] = pn64 >> 16;
+               mic_hdr->ccmp_pn[2] = pn64 >> 24;
+               mic_hdr->ccmp_pn[1] = pn64 >> 32;
+               mic_hdr->ccmp_pn[0] = pn64 >> 40;
 
                if (ieee80211_has_a4(hdr->frame_control))
                        mic_hdr->hlen = cpu_to_be16(28);
index efb54f53b4f9eddd496a987078055041f559a895..76378d225b467fa47c84feaf7a0bef37c5b1c85a 100644 (file)
@@ -719,7 +719,7 @@ static void vnt_fill_txkey(struct vnt_usb_send_context *tx_context,
        u16 payload_len, struct vnt_mic_hdr *mic_hdr)
 {
        struct ieee80211_hdr *hdr = tx_context->hdr;
-       struct ieee80211_key_seq seq;
+       u64 pn64;
        u8 *iv = ((u8 *)hdr + ieee80211_get_hdrlen_from_skb(skb));
 
        /* strip header and icv len from payload */
@@ -752,9 +752,13 @@ static void vnt_fill_txkey(struct vnt_usb_send_context *tx_context,
                mic_hdr->payload_len = cpu_to_be16(payload_len);
                ether_addr_copy(mic_hdr->mic_addr2, hdr->addr2);
 
-               ieee80211_get_key_tx_seq(tx_key, &seq);
-
-               memcpy(mic_hdr->ccmp_pn, seq.ccmp.pn, IEEE80211_CCMP_PN_LEN);
+               pn64 = atomic64_read(&tx_key->tx_pn);
+               mic_hdr->ccmp_pn[5] = pn64;
+               mic_hdr->ccmp_pn[4] = pn64 >> 8;
+               mic_hdr->ccmp_pn[3] = pn64 >> 16;
+               mic_hdr->ccmp_pn[2] = pn64 >> 24;
+               mic_hdr->ccmp_pn[1] = pn64 >> 32;
+               mic_hdr->ccmp_pn[0] = pn64 >> 40;
 
                if (ieee80211_has_a4(hdr->frame_control))
                        mic_hdr->hlen = cpu_to_be16(28);
index 5ed90e6c8a64337bb968a937b50f8b92d49f07dc..5d33b350da1c68d937d2b7d97a4ea8650ea0c4a4 100644 (file)
@@ -125,8 +125,8 @@ static int soc_dts_enable(struct thermal_zone_device *tzd)
        struct soc_sensor_entry *aux_entry = tzd->devdata;
        int ret;
 
-       ret = iosf_mbi_read(QRK_MBI_UNIT_RMU, QRK_MBI_RMU_READ,
-                                       QRK_DTS_REG_OFFSET_ENABLE, &out);
+       ret = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ,
+                           QRK_DTS_REG_OFFSET_ENABLE, &out);
        if (ret)
                return ret;
 
@@ -137,8 +137,8 @@ static int soc_dts_enable(struct thermal_zone_device *tzd)
 
        if (!aux_entry->locked) {
                out |= QRK_DTS_ENABLE_BIT;
-               ret = iosf_mbi_write(QRK_MBI_UNIT_RMU, QRK_MBI_RMU_WRITE,
-                                       QRK_DTS_REG_OFFSET_ENABLE, out);
+               ret = iosf_mbi_write(QRK_MBI_UNIT_RMU, MBI_REG_WRITE,
+                                    QRK_DTS_REG_OFFSET_ENABLE, out);
                if (ret)
                        return ret;
 
@@ -158,8 +158,8 @@ static int soc_dts_disable(struct thermal_zone_device *tzd)
        struct soc_sensor_entry *aux_entry = tzd->devdata;
        int ret;
 
-       ret = iosf_mbi_read(QRK_MBI_UNIT_RMU, QRK_MBI_RMU_READ,
-                                       QRK_DTS_REG_OFFSET_ENABLE, &out);
+       ret = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ,
+                           QRK_DTS_REG_OFFSET_ENABLE, &out);
        if (ret)
                return ret;
 
@@ -170,8 +170,8 @@ static int soc_dts_disable(struct thermal_zone_device *tzd)
 
        if (!aux_entry->locked) {
                out &= ~QRK_DTS_ENABLE_BIT;
-               ret = iosf_mbi_write(QRK_MBI_UNIT_RMU, QRK_MBI_RMU_WRITE,
-                                       QRK_DTS_REG_OFFSET_ENABLE, out);
+               ret = iosf_mbi_write(QRK_MBI_UNIT_RMU, MBI_REG_WRITE,
+                                    QRK_DTS_REG_OFFSET_ENABLE, out);
 
                if (ret)
                        return ret;
@@ -192,8 +192,8 @@ static int _get_trip_temp(int trip, int *temp)
        u32 out;
 
        mutex_lock(&dts_update_mutex);
-       status = iosf_mbi_read(QRK_MBI_UNIT_RMU, QRK_MBI_RMU_READ,
-                               QRK_DTS_REG_OFFSET_PTPS, &out);
+       status = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ,
+                              QRK_DTS_REG_OFFSET_PTPS, &out);
        mutex_unlock(&dts_update_mutex);
 
        if (status)
@@ -236,8 +236,8 @@ static int update_trip_temp(struct soc_sensor_entry *aux_entry,
                goto failed;
        }
 
-       ret = iosf_mbi_read(QRK_MBI_UNIT_RMU, QRK_MBI_RMU_READ,
-                               QRK_DTS_REG_OFFSET_PTPS, &store_ptps);
+       ret = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ,
+                           QRK_DTS_REG_OFFSET_PTPS, &store_ptps);
        if (ret)
                goto failed;
 
@@ -262,8 +262,8 @@ static int update_trip_temp(struct soc_sensor_entry *aux_entry,
        out |= (temp_out & QRK_DTS_MASK_TP_THRES) <<
                (trip * QRK_DTS_SHIFT_TP);
 
-       ret = iosf_mbi_write(QRK_MBI_UNIT_RMU, QRK_MBI_RMU_WRITE,
-                               QRK_DTS_REG_OFFSET_PTPS, out);
+       ret = iosf_mbi_write(QRK_MBI_UNIT_RMU, MBI_REG_WRITE,
+                            QRK_DTS_REG_OFFSET_PTPS, out);
 
 failed:
        mutex_unlock(&dts_update_mutex);
@@ -294,8 +294,8 @@ static int sys_get_curr_temp(struct thermal_zone_device *tzd,
        int ret;
 
        mutex_lock(&dts_update_mutex);
-       ret = iosf_mbi_read(QRK_MBI_UNIT_RMU, QRK_MBI_RMU_READ,
-                                       QRK_DTS_REG_OFFSET_TEMP, &out);
+       ret = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ,
+                           QRK_DTS_REG_OFFSET_TEMP, &out);
        mutex_unlock(&dts_update_mutex);
 
        if (ret)
@@ -350,13 +350,13 @@ static void free_soc_dts(struct soc_sensor_entry *aux_entry)
        if (aux_entry) {
                if (!aux_entry->locked) {
                        mutex_lock(&dts_update_mutex);
-                       iosf_mbi_write(QRK_MBI_UNIT_RMU, QRK_MBI_RMU_WRITE,
-                                       QRK_DTS_REG_OFFSET_ENABLE,
-                                       aux_entry->store_dts_enable);
+                       iosf_mbi_write(QRK_MBI_UNIT_RMU, MBI_REG_WRITE,
+                                      QRK_DTS_REG_OFFSET_ENABLE,
+                                      aux_entry->store_dts_enable);
 
-                       iosf_mbi_write(QRK_MBI_UNIT_RMU, QRK_MBI_RMU_WRITE,
-                                       QRK_DTS_REG_OFFSET_PTPS,
-                                       aux_entry->store_ptps);
+                       iosf_mbi_write(QRK_MBI_UNIT_RMU, MBI_REG_WRITE,
+                                      QRK_DTS_REG_OFFSET_PTPS,
+                                      aux_entry->store_ptps);
                        mutex_unlock(&dts_update_mutex);
                }
                thermal_zone_device_unregister(aux_entry->tzone);
@@ -378,9 +378,8 @@ static struct soc_sensor_entry *alloc_soc_dts(void)
        }
 
        /* Check if DTS register is locked */
-       err = iosf_mbi_read(QRK_MBI_UNIT_RMU, QRK_MBI_RMU_READ,
-                                       QRK_DTS_REG_OFFSET_LOCK,
-                                       &out);
+       err = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ,
+                           QRK_DTS_REG_OFFSET_LOCK, &out);
        if (err)
                goto err_ret;
 
@@ -395,16 +394,16 @@ static struct soc_sensor_entry *alloc_soc_dts(void)
        /* Store DTS default state if DTS registers are not locked */
        if (!aux_entry->locked) {
                /* Store DTS default enable for restore on exit */
-               err = iosf_mbi_read(QRK_MBI_UNIT_RMU, QRK_MBI_RMU_READ,
-                                       QRK_DTS_REG_OFFSET_ENABLE,
-                                       &aux_entry->store_dts_enable);
+               err = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ,
+                                   QRK_DTS_REG_OFFSET_ENABLE,
+                                   &aux_entry->store_dts_enable);
                if (err)
                        goto err_ret;
 
                /* Store DTS default PTPS register for restore on exit */
-               err = iosf_mbi_read(QRK_MBI_UNIT_RMU, QRK_MBI_RMU_READ,
-                                       QRK_DTS_REG_OFFSET_PTPS,
-                                       &aux_entry->store_ptps);
+               err = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ,
+                                   QRK_DTS_REG_OFFSET_PTPS,
+                                   &aux_entry->store_ptps);
                if (err)
                        goto err_ret;
        }
index 5841d1d729966b85439f8aa27a51163e057c59ee..f72e1db3216f6f446458467964c9108986ea8c4f 100644 (file)
@@ -90,7 +90,7 @@ static int sys_get_trip_temp(struct thermal_zone_device *tzd, int trip,
        dts = tzd->devdata;
        sensors = dts->sensors;
        mutex_lock(&sensors->dts_update_lock);
-       status = iosf_mbi_read(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_READ,
+       status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
                               SOC_DTS_OFFSET_PTPS, &out);
        mutex_unlock(&sensors->dts_update_lock);
        if (status)
@@ -124,27 +124,27 @@ static int update_trip_temp(struct intel_soc_dts_sensor_entry *dts,
 
        temp_out = (sensors->tj_max - temp) / 1000;
 
-       status = iosf_mbi_read(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_READ,
+       status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
                               SOC_DTS_OFFSET_PTPS, &store_ptps);
        if (status)
                return status;
 
        out = (store_ptps & ~(0xFF << (thres_index * 8)));
        out |= (temp_out & 0xFF) << (thres_index * 8);
-       status = iosf_mbi_write(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_WRITE,
+       status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
                                SOC_DTS_OFFSET_PTPS, out);
        if (status)
                return status;
 
        pr_debug("update_trip_temp PTPS = %x\n", out);
-       status = iosf_mbi_read(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_READ,
+       status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
                               SOC_DTS_OFFSET_PTMC, &out);
        if (status)
                goto err_restore_ptps;
 
        store_ptmc = out;
 
-       status = iosf_mbi_read(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_READ,
+       status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
                               SOC_DTS_TE_AUX0 + thres_index,
                               &te_out);
        if (status)
@@ -167,12 +167,12 @@ static int update_trip_temp(struct intel_soc_dts_sensor_entry *dts,
                        out &= ~SOC_DTS_AUX0_ENABLE_BIT;
                te_out &= ~int_enable_bit;
        }
-       status = iosf_mbi_write(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_WRITE,
+       status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
                                SOC_DTS_OFFSET_PTMC, out);
        if (status)
                goto err_restore_te_out;
 
-       status = iosf_mbi_write(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_WRITE,
+       status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
                                SOC_DTS_TE_AUX0 + thres_index,
                                te_out);
        if (status)
@@ -182,13 +182,13 @@ static int update_trip_temp(struct intel_soc_dts_sensor_entry *dts,
 
        return 0;
 err_restore_te_out:
-       iosf_mbi_write(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_WRITE,
+       iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
                       SOC_DTS_OFFSET_PTMC, store_te_out);
 err_restore_ptmc:
-       iosf_mbi_write(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_WRITE,
+       iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
                       SOC_DTS_OFFSET_PTMC, store_ptmc);
 err_restore_ptps:
-       iosf_mbi_write(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_WRITE,
+       iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
                       SOC_DTS_OFFSET_PTPS, store_ptps);
        /* Nothing we can do if restore fails */
 
@@ -235,7 +235,7 @@ static int sys_get_curr_temp(struct thermal_zone_device *tzd,
 
        dts = tzd->devdata;
        sensors = dts->sensors;
-       status = iosf_mbi_read(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_READ,
+       status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
                               SOC_DTS_OFFSET_TEMP, &out);
        if (status)
                return status;
@@ -259,14 +259,14 @@ static int soc_dts_enable(int id)
        u32 out;
        int ret;
 
-       ret = iosf_mbi_read(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_READ,
+       ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
                            SOC_DTS_OFFSET_ENABLE, &out);
        if (ret)
                return ret;
 
        if (!(out & BIT(id))) {
                out |= BIT(id);
-               ret = iosf_mbi_write(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_WRITE,
+               ret = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
                                     SOC_DTS_OFFSET_ENABLE, out);
                if (ret)
                        return ret;
@@ -278,7 +278,7 @@ static int soc_dts_enable(int id)
 static void remove_dts_thermal_zone(struct intel_soc_dts_sensor_entry *dts)
 {
        if (dts) {
-               iosf_mbi_write(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_WRITE,
+               iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
                               SOC_DTS_OFFSET_ENABLE, dts->store_status);
                thermal_zone_device_unregister(dts->tzone);
        }
@@ -296,9 +296,8 @@ static int add_dts_thermal_zone(int id, struct intel_soc_dts_sensor_entry *dts,
        int i;
 
        /* Store status to restor on exit */
-       ret = iosf_mbi_read(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_READ,
-                           SOC_DTS_OFFSET_ENABLE,
-                           &dts->store_status);
+       ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
+                           SOC_DTS_OFFSET_ENABLE, &dts->store_status);
        if (ret)
                goto err_ret;
 
@@ -311,7 +310,7 @@ static int add_dts_thermal_zone(int id, struct intel_soc_dts_sensor_entry *dts,
        }
 
        /* Check if the writable trip we provide is not used by BIOS */
-       ret = iosf_mbi_read(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_READ,
+       ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
                            SOC_DTS_OFFSET_PTPS, &store_ptps);
        if (ret)
                trip_mask = 0;
@@ -374,19 +373,19 @@ void intel_soc_dts_iosf_interrupt_handler(struct intel_soc_dts_sensors *sensors)
 
        spin_lock_irqsave(&sensors->intr_notify_lock, flags);
 
-       status = iosf_mbi_read(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_READ,
+       status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
                               SOC_DTS_OFFSET_PTMC, &ptmc_out);
        ptmc_out |= SOC_DTS_PTMC_APIC_DEASSERT_BIT;
-       status = iosf_mbi_write(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_WRITE,
+       status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
                                SOC_DTS_OFFSET_PTMC, ptmc_out);
 
-       status = iosf_mbi_read(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_READ,
+       status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
                               SOC_DTS_OFFSET_PTTSS, &sticky_out);
        pr_debug("status %d PTTSS %x\n", status, sticky_out);
        if (sticky_out & SOC_DTS_TRIP_MASK) {
                int i;
                /* reset sticky bit */
-               status = iosf_mbi_write(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_WRITE,
+               status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
                                        SOC_DTS_OFFSET_PTTSS, sticky_out);
                spin_unlock_irqrestore(&sensors->intr_notify_lock, flags);
 
index 204f5819d464b6ec3c169d78b2ec9a30989be90e..cd84b12d1e608e469f1b463c0491a71c72e189be 100644 (file)
@@ -126,8 +126,9 @@ struct acpi_exception_info {
 #define AE_OWNER_ID_LIMIT               EXCEP_ENV (0x001B)
 #define AE_NOT_CONFIGURED               EXCEP_ENV (0x001C)
 #define AE_ACCESS                       EXCEP_ENV (0x001D)
+#define AE_IO_ERROR                     EXCEP_ENV (0x001E)
 
-#define AE_CODE_ENV_MAX                 0x001D
+#define AE_CODE_ENV_MAX                 0x001E
 
 /*
  * Programmer exceptions
@@ -263,7 +264,8 @@ static const struct acpi_exception_info acpi_gbl_exception_names_env[] = {
                  "There are no more Owner IDs available for ACPI tables or control methods"),
        EXCEP_TXT("AE_NOT_CONFIGURED",
                  "The interface is not part of the current subsystem configuration"),
-       EXCEP_TXT("AE_ACCESS", "Permission denied for the requested operation")
+       EXCEP_TXT("AE_ACCESS", "Permission denied for the requested operation"),
+       EXCEP_TXT("AE_IO_ERROR", "An I/O error occurred")
 };
 
 static const struct acpi_exception_info acpi_gbl_exception_names_pgm[] = {
index ad0a5ff3d4cd724128b36074d428f475155df1b4..14362a84c78e3ca1d5712d284d6dce22ed656ba1 100644 (file)
@@ -87,6 +87,8 @@ acpi_evaluate_dsm_typed(acpi_handle handle, const u8 *uuid, int rev, int func,
          .package.elements = (eles)                    \
        }
 
+bool acpi_dev_present(const char *hid);
+
 #ifdef CONFIG_ACPI
 
 #include <linux/proc_fs.h>
@@ -631,7 +633,9 @@ static inline bool acpi_device_can_wakeup(struct acpi_device *adev)
 
 static inline bool acpi_device_can_poweroff(struct acpi_device *adev)
 {
-       return adev->power.states[ACPI_STATE_D3_COLD].flags.valid;
+       return adev->power.states[ACPI_STATE_D3_COLD].flags.valid ||
+               ((acpi_gbl_FADT.header.revision < 6) &&
+               adev->power.states[ACPI_STATE_D3_HOT].flags.explicit_set);
 }
 
 #else  /* CONFIG_ACPI */
index fbc2baf2b9dc98ac6f7195decd71b27aeac4076d..0d824a28522d7cfb25014b7d48afa3cc72323c4a 100644 (file)
@@ -349,12 +349,28 @@ void acpi_os_redirect_output(void *destination);
 #endif
 
 /*
- * Debug input
+ * Debug IO
  */
 #ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_line
 acpi_status acpi_os_get_line(char *buffer, u32 buffer_length, u32 *bytes_read);
 #endif
 
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_initialize_command_signals
+acpi_status acpi_os_initialize_command_signals(void);
+#endif
+
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_terminate_command_signals
+void acpi_os_terminate_command_signals(void);
+#endif
+
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_wait_command_ready
+acpi_status acpi_os_wait_command_ready(void);
+#endif
+
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_notify_command_complete
+acpi_status acpi_os_notify_command_complete(void);
+#endif
+
 /*
  * Obtain ACPI table(s)
  */
index 3aaaa8630735c187d19943467f3242c1e0c9388a..012b2eed7a931cbc2b2e0c25f719ecbaba2b9b78 100644 (file)
@@ -46,7 +46,7 @@
 
 /* Current ACPICA subsystem version in YYYYMMDD format */
 
-#define ACPI_CA_VERSION                 0x20150930
+#define ACPI_CA_VERSION                 0x20151218
 
 #include <acpi/acconfig.h>
 #include <acpi/actypes.h>
@@ -189,6 +189,11 @@ ACPI_INIT_GLOBAL(u8, acpi_gbl_copy_dsdt_locally, FALSE);
  */
 ACPI_INIT_GLOBAL(u8, acpi_gbl_do_not_use_xsdt, FALSE);
 
+/*
+ * Optionally support group module level code.
+ */
+ACPI_INIT_GLOBAL(u8, acpi_gbl_group_module_level_code, TRUE);
+
 /*
  * Optionally use 32-bit FADT addresses if and when there is a conflict
  * (address mismatch) between the 32-bit and 64-bit versions of the
@@ -263,6 +268,19 @@ ACPI_INIT_GLOBAL(u32, acpi_gbl_trace_dbg_layer, ACPI_TRACE_LAYER_DEFAULT);
 ACPI_INIT_GLOBAL(u32, acpi_dbg_level, ACPI_DEBUG_DEFAULT);
 ACPI_INIT_GLOBAL(u32, acpi_dbg_layer, 0);
 
+/* Optionally enable timer output with Debug Object output */
+
+ACPI_INIT_GLOBAL(u8, acpi_gbl_display_debug_timer, FALSE);
+
+/*
+ * Debugger command handshake globals. Host OSes need to access these
+ * variables to implement their own command handshake mechanism.
+ */
+#ifdef ACPI_DEBUGGER
+ACPI_INIT_GLOBAL(u8, acpi_gbl_method_executing, FALSE);
+ACPI_GLOBAL(char, acpi_gbl_db_line_buf[ACPI_DB_LINE_BUFFER_SIZE]);
+#endif
+
 /*
  * Other miscellaneous globals
  */
@@ -366,6 +384,29 @@ ACPI_GLOBAL(u8, acpi_gbl_system_awake_and_running);
 
 #endif                         /* ACPI_APPLICATION */
 
+/*
+ * Debugger prototypes
+ *
+ * All interfaces used by debugger will be configured
+ * out of the ACPICA build unless the ACPI_DEBUGGER
+ * flag is defined.
+ */
+#ifdef ACPI_DEBUGGER
+#define ACPI_DBR_DEPENDENT_RETURN_OK(prototype) \
+       ACPI_EXTERNAL_RETURN_OK(prototype)
+
+#define ACPI_DBR_DEPENDENT_RETURN_VOID(prototype) \
+       ACPI_EXTERNAL_RETURN_VOID(prototype)
+
+#else
+#define ACPI_DBR_DEPENDENT_RETURN_OK(prototype) \
+       static ACPI_INLINE prototype {return(AE_OK);}
+
+#define ACPI_DBR_DEPENDENT_RETURN_VOID(prototype) \
+       static ACPI_INLINE prototype {return;}
+
+#endif                         /* ACPI_DEBUGGER */
+
 /*****************************************************************************
  *
  * ACPICA public interface prototypes
@@ -822,17 +863,9 @@ ACPI_EXTERNAL_RETURN_STATUS(acpi_status
 ACPI_EXTERNAL_RETURN_STATUS(acpi_status acpi_leave_sleep_state(u8 sleep_state))
 
 ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
-                               acpi_set_firmware_waking_vectors
+                               acpi_set_firmware_waking_vector
                                (acpi_physical_address physical_address,
                                 acpi_physical_address physical_address64))
-ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
-                                acpi_set_firmware_waking_vector(u32
-                                                                physical_address))
-#if ACPI_MACHINE_WIDTH == 64
-ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
-                               acpi_set_firmware_waking_vector64(u64
-                                                                 physical_address))
-#endif
 /*
  * ACPI Timer interfaces
  */
@@ -929,6 +962,8 @@ ACPI_EXTERNAL_RETURN_STATUS(acpi_status
                                               void **data,
                                               void (*callback)(void *)))
 
+void acpi_run_debugger(char *batch_buffer);
+
 void acpi_set_debugger_thread_id(acpi_thread_id thread_id);
 
 #endif                         /* __ACXFACE_H__ */
index f914958c4adbcce6ac8af1170811e9c96a5b3f1c..9633f606d89ec3a83392a33cc6671e6c9836680b 100644 (file)
@@ -1148,7 +1148,7 @@ u32 (*acpi_interface_handler) (acpi_string interface_name, u32 supported);
 
 #define ACPI_PCICLS_STRING_SIZE         7      /* Includes null terminator */
 
-/* Structures used for device/processor HID, UID, CID, and SUB */
+/* Structures used for device/processor HID, UID, CID */
 
 struct acpi_pnp_device_id {
        u32 length;             /* Length of string + null */
@@ -1178,7 +1178,6 @@ struct acpi_device_info {
        u64 address;    /* _ADR value */
        struct acpi_pnp_device_id hardware_id;  /* _HID value */
        struct acpi_pnp_device_id unique_id;    /* _UID value */
-       struct acpi_pnp_device_id subsystem_id; /* _SUB value */
        struct acpi_pnp_device_id class_code;   /* _CLS value */
        struct acpi_pnp_device_id_list compatible_id_list;      /* _CID list <must be last> */
 };
@@ -1193,13 +1192,12 @@ struct acpi_device_info {
 #define ACPI_VALID_ADR                  0x0002
 #define ACPI_VALID_HID                  0x0004
 #define ACPI_VALID_UID                  0x0008
-#define ACPI_VALID_SUB                  0x0010
 #define ACPI_VALID_CID                  0x0020
 #define ACPI_VALID_CLS                  0x0040
 #define ACPI_VALID_SXDS                 0x0100
 #define ACPI_VALID_SXWS                 0x0200
 
-/* Flags for _STA return value (current_status above) */
+/* Flags for _STA method */
 
 #define ACPI_STA_DEVICE_PRESENT         0x01
 #define ACPI_STA_DEVICE_ENABLED         0x02
index 323e5daece54999684144620cc644e4b64e1c707..e21857d2ec05df1b730e7387eba8949c6ff7bd28 100644 (file)
  */
 #define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_readable
 #define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_writable
+#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_initialize_command_signals
+#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_terminate_command_signals
 
 /*
  * OSL interfaces used by utilities
index fd6d70fe1219c35b12b65902759185e6bcbaa9cd..f903fe64259a6227ae89edeec985aa10186fddad 100644 (file)
@@ -129,6 +129,16 @@ static inline u8 acpi_os_readable(void *pointer, acpi_size length)
        return TRUE;
 }
 
+static inline acpi_status acpi_os_initialize_command_signals(void)
+{
+       return AE_OK;
+}
+
+static inline void acpi_os_terminate_command_signals(void)
+{
+       return;
+}
+
 /*
  * OSL interfaces added by Linux
  */
index c62392d9b52ad6ee06b98a3fd9e6832c73ebcae1..f11d342b45670f1137d695557388935df7f4cf18 100644 (file)
@@ -2,6 +2,7 @@
 #define __ACPI_VIDEO_H
 
 #include <linux/errno.h> /* for ENODEV */
+#include <linux/types.h> /* for bool */
 
 struct acpi_device;
 
@@ -31,6 +32,7 @@ extern int acpi_video_get_edid(struct acpi_device *device, int type,
                               int device_id, void **edid);
 extern enum acpi_backlight_type acpi_video_get_backlight_type(void);
 extern void acpi_video_set_dmi_backlight_type(enum acpi_backlight_type type);
+extern bool acpi_video_handles_brightness_key_presses(void);
 #else
 static inline int acpi_video_register(void) { return 0; }
 static inline void acpi_video_unregister(void) { return; }
@@ -46,6 +48,10 @@ static inline enum acpi_backlight_type acpi_video_get_backlight_type(void)
 static inline void acpi_video_set_dmi_backlight_type(enum acpi_backlight_type type)
 {
 }
+static inline bool acpi_video_handles_brightness_key_presses(void)
+{
+       return false;
+}
 #endif
 
 #endif
index 1991aea2ec4cff401b84db2841ac60fe28f00080..06ed7e54033e7ae5554e41461a51ca0be250695f 100644 (file)
@@ -37,6 +37,8 @@
 #include <linux/list.h>
 #include <linux/mod_devicetable.h>
 #include <linux/dynamic_debug.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
 
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
@@ -119,6 +121,75 @@ typedef int (*acpi_tbl_table_handler)(struct acpi_table_header *table);
 typedef int (*acpi_tbl_entry_handler)(struct acpi_subtable_header *header,
                                      const unsigned long end);
 
+/* Debugger support */
+
+struct acpi_debugger_ops {
+       int (*create_thread)(acpi_osd_exec_callback function, void *context);
+       ssize_t (*write_log)(const char *msg);
+       ssize_t (*read_cmd)(char *buffer, size_t length);
+       int (*wait_command_ready)(bool single_step, char *buffer, size_t length);
+       int (*notify_command_complete)(void);
+};
+
+struct acpi_debugger {
+       const struct acpi_debugger_ops *ops;
+       struct module *owner;
+       struct mutex lock;
+};
+
+#ifdef CONFIG_ACPI_DEBUGGER
+int __init acpi_debugger_init(void);
+int acpi_register_debugger(struct module *owner,
+                          const struct acpi_debugger_ops *ops);
+void acpi_unregister_debugger(const struct acpi_debugger_ops *ops);
+int acpi_debugger_create_thread(acpi_osd_exec_callback function, void *context);
+ssize_t acpi_debugger_write_log(const char *msg);
+ssize_t acpi_debugger_read_cmd(char *buffer, size_t buffer_length);
+int acpi_debugger_wait_command_ready(void);
+int acpi_debugger_notify_command_complete(void);
+#else
+static inline int acpi_debugger_init(void)
+{
+       return -ENODEV;
+}
+
+static inline int acpi_register_debugger(struct module *owner,
+                                        const struct acpi_debugger_ops *ops)
+{
+       return -ENODEV;
+}
+
+static inline void acpi_unregister_debugger(const struct acpi_debugger_ops *ops)
+{
+}
+
+static inline int acpi_debugger_create_thread(acpi_osd_exec_callback function,
+                                             void *context)
+{
+       return -ENODEV;
+}
+
+static inline int acpi_debugger_write_log(const char *msg)
+{
+       return -ENODEV;
+}
+
+static inline int acpi_debugger_read_cmd(char *buffer, u32 buffer_length)
+{
+       return -ENODEV;
+}
+
+static inline int acpi_debugger_wait_command_ready(void)
+{
+       return -ENODEV;
+}
+
+static inline int acpi_debugger_notify_command_complete(void)
+{
+       return -ENODEV;
+}
+#endif
+
 #ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
 void acpi_initrd_override(void *data, size_t size);
 #else
@@ -318,6 +389,7 @@ bool acpi_dev_resource_address_space(struct acpi_resource *ares,
 bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares,
                                         struct resource_win *win);
 unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable);
+unsigned int acpi_dev_get_irq_type(int triggering, int polarity);
 bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
                                 struct resource *res);
 
index e5f4164cbd993b8d3322a829eb6da8985bf6e1b0..7f540f7f588d8c8461af975a5ebd21a08e6cf14b 100644 (file)
@@ -34,17 +34,12 @@ struct seq_file;
 
 /* define the enumeration of all cgroup subsystems */
 #define SUBSYS(_x) _x ## _cgrp_id,
-#define SUBSYS_TAG(_t) CGROUP_ ## _t, \
-       __unused_tag_ ## _t = CGROUP_ ## _t - 1,
 enum cgroup_subsys_id {
 #include <linux/cgroup_subsys.h>
        CGROUP_SUBSYS_COUNT,
 };
-#undef SUBSYS_TAG
 #undef SUBSYS
 
-#define CGROUP_CANFORK_COUNT (CGROUP_CANFORK_END - CGROUP_CANFORK_START)
-
 /* bits in struct cgroup_subsys_state flags field */
 enum {
        CSS_NO_REF      = (1 << 0), /* no reference counting for this css */
@@ -66,7 +61,6 @@ enum {
 
 /* cgroup_root->flags */
 enum {
-       CGRP_ROOT_SANE_BEHAVIOR = (1 << 0), /* __DEVEL__sane_behavior specified */
        CGRP_ROOT_NOPREFIX      = (1 << 1), /* mounted subsystems have no named prefix */
        CGRP_ROOT_XATTR         = (1 << 2), /* supports extended attributes */
 };
@@ -439,9 +433,9 @@ struct cgroup_subsys {
        int (*can_attach)(struct cgroup_taskset *tset);
        void (*cancel_attach)(struct cgroup_taskset *tset);
        void (*attach)(struct cgroup_taskset *tset);
-       int (*can_fork)(struct task_struct *task, void **priv_p);
-       void (*cancel_fork)(struct task_struct *task, void *priv);
-       void (*fork)(struct task_struct *task, void *priv);
+       int (*can_fork)(struct task_struct *task);
+       void (*cancel_fork)(struct task_struct *task);
+       void (*fork)(struct task_struct *task);
        void (*exit)(struct task_struct *task);
        void (*free)(struct task_struct *task);
        void (*bind)(struct cgroup_subsys_state *root_css);
@@ -527,7 +521,6 @@ static inline void cgroup_threadgroup_change_end(struct task_struct *tsk)
 
 #else  /* CONFIG_CGROUPS */
 
-#define CGROUP_CANFORK_COUNT 0
 #define CGROUP_SUBSYS_COUNT 0
 
 static inline void cgroup_threadgroup_change_begin(struct task_struct *tsk) {}
index 322a2848274597c76f775b0008735bdd5ce6a881..2162dca88dc0881623272fd56017a84ae0f663de 100644 (file)
@@ -97,12 +97,9 @@ int proc_cgroup_show(struct seq_file *m, struct pid_namespace *ns,
                     struct pid *pid, struct task_struct *tsk);
 
 void cgroup_fork(struct task_struct *p);
-extern int cgroup_can_fork(struct task_struct *p,
-                          void *ss_priv[CGROUP_CANFORK_COUNT]);
-extern void cgroup_cancel_fork(struct task_struct *p,
-                              void *ss_priv[CGROUP_CANFORK_COUNT]);
-extern void cgroup_post_fork(struct task_struct *p,
-                            void *old_ss_priv[CGROUP_CANFORK_COUNT]);
+extern int cgroup_can_fork(struct task_struct *p);
+extern void cgroup_cancel_fork(struct task_struct *p);
+extern void cgroup_post_fork(struct task_struct *p);
 void cgroup_exit(struct task_struct *p);
 void cgroup_free(struct task_struct *p);
 
@@ -562,13 +559,9 @@ static inline int cgroupstats_build(struct cgroupstats *stats,
                                    struct dentry *dentry) { return -EINVAL; }
 
 static inline void cgroup_fork(struct task_struct *p) {}
-static inline int cgroup_can_fork(struct task_struct *p,
-                                 void *ss_priv[CGROUP_CANFORK_COUNT])
-{ return 0; }
-static inline void cgroup_cancel_fork(struct task_struct *p,
-                                     void *ss_priv[CGROUP_CANFORK_COUNT]) {}
-static inline void cgroup_post_fork(struct task_struct *p,
-                                   void *ss_priv[CGROUP_CANFORK_COUNT]) {}
+static inline int cgroup_can_fork(struct task_struct *p) { return 0; }
+static inline void cgroup_cancel_fork(struct task_struct *p) {}
+static inline void cgroup_post_fork(struct task_struct *p) {}
 static inline void cgroup_exit(struct task_struct *p) {}
 static inline void cgroup_free(struct task_struct *p) {}
 
index 1a96fdaa33d54befd4fde55b5af79c1c51b887ac..0df0336acee9ec10fef79f878c299f1aae33b143 100644 (file)
@@ -6,14 +6,8 @@
 
 /*
  * This file *must* be included with SUBSYS() defined.
- * SUBSYS_TAG() is a noop if undefined.
  */
 
-#ifndef SUBSYS_TAG
-#define __TMP_SUBSYS_TAG
-#define SUBSYS_TAG(_x)
-#endif
-
 #if IS_ENABLED(CONFIG_CPUSETS)
 SUBSYS(cpuset)
 #endif
@@ -58,17 +52,10 @@ SUBSYS(net_prio)
 SUBSYS(hugetlb)
 #endif
 
-/*
- * Subsystems that implement the can_fork() family of callbacks.
- */
-SUBSYS_TAG(CANFORK_START)
-
 #if IS_ENABLED(CONFIG_CGROUP_PIDS)
 SUBSYS(pids)
 #endif
 
-SUBSYS_TAG(CANFORK_END)
-
 /*
  * The following subsystems are not supported on the default hierarchy.
  */
@@ -76,11 +63,6 @@ SUBSYS_TAG(CANFORK_END)
 SUBSYS(debug)
 #endif
 
-#ifdef __TMP_SUBSYS_TAG
-#undef __TMP_SUBSYS_TAG
-#undef SUBSYS_TAG
-#endif
-
 /*
  * DO NOT ADD ANY SUBSYSTEM WITHOUT EXPLICIT ACKS FROM CGROUP MAINTAINERS.
  */
index 177c7680c1a8a81bcc942497ee228c148fbf5a0b..88a4215125bce6be0ac47ef1fda2948eead30c27 100644 (file)
@@ -278,7 +278,6 @@ struct cpufreq_driver {
        struct freq_attr **attr;
 
        /* platform specific boost support code */
-       bool            boost_supported;
        bool            boost_enabled;
        int             (*set_boost)(int state);
 };
@@ -574,7 +573,6 @@ ssize_t cpufreq_show_cpus(const struct cpumask *mask, char *buf);
 
 #ifdef CONFIG_CPU_FREQ
 int cpufreq_boost_trigger_state(int state);
-int cpufreq_boost_supported(void);
 int cpufreq_boost_enabled(void);
 int cpufreq_enable_boost_support(void);
 bool policy_has_boost_freq(struct cpufreq_policy *policy);
@@ -583,10 +581,6 @@ static inline int cpufreq_boost_trigger_state(int state)
 {
        return 0;
 }
-static inline int cpufreq_boost_supported(void)
-{
-       return 0;
-}
 static inline int cpufreq_boost_enabled(void)
 {
        return 0;
index b8f411b57dcb2c77fcaee7194fd439b739bf1e04..f627ba20a46cd892c8e8f993baf08137d617aba5 100644 (file)
@@ -191,6 +191,7 @@ extern int bus_unregister_notifier(struct bus_type *bus,
                                                      unbound */
 #define BUS_NOTIFY_UNBOUND_DRIVER      0x00000007 /* driver is unbound
                                                      from the device */
+#define BUS_NOTIFY_DRIVER_NOT_BOUND    0x00000008 /* driver fails to be bound */
 
 extern struct kset *bus_get_kset(struct bus_type *bus);
 extern struct klist *bus_get_device_klist(struct bus_type *bus);
index 60048c50404ee612aae6535ef8abfcf8475086d6..0639dcc9819523a002de1149da5629d24bce039b 100644 (file)
@@ -76,8 +76,8 @@ ftrace_func_t ftrace_ops_get_func(struct ftrace_ops *ops);
  * ENABLED - set/unset when ftrace_ops is registered/unregistered
  * DYNAMIC - set when ftrace_ops is registered to denote dynamically
  *           allocated ftrace_ops which need special care
- * CONTROL - set manualy by ftrace_ops user to denote the ftrace_ops
- *           could be controled by following calls:
+ * PER_CPU - set manualy by ftrace_ops user to denote the ftrace_ops
+ *           could be controlled by following calls:
  *             ftrace_function_local_enable
  *             ftrace_function_local_disable
  * SAVE_REGS - The ftrace_ops wants regs saved at each function called
@@ -121,7 +121,7 @@ ftrace_func_t ftrace_ops_get_func(struct ftrace_ops *ops);
 enum {
        FTRACE_OPS_FL_ENABLED                   = 1 << 0,
        FTRACE_OPS_FL_DYNAMIC                   = 1 << 1,
-       FTRACE_OPS_FL_CONTROL                   = 1 << 2,
+       FTRACE_OPS_FL_PER_CPU                   = 1 << 2,
        FTRACE_OPS_FL_SAVE_REGS                 = 1 << 3,
        FTRACE_OPS_FL_SAVE_REGS_IF_SUPPORTED    = 1 << 4,
        FTRACE_OPS_FL_RECURSION_SAFE            = 1 << 5,
@@ -134,6 +134,7 @@ enum {
        FTRACE_OPS_FL_ALLOC_TRAMP               = 1 << 12,
        FTRACE_OPS_FL_IPMODIFY                  = 1 << 13,
        FTRACE_OPS_FL_PID                       = 1 << 14,
+       FTRACE_OPS_FL_RCU                       = 1 << 15,
 };
 
 #ifdef CONFIG_DYNAMIC_FTRACE
@@ -146,11 +147,11 @@ struct ftrace_ops_hash {
 #endif
 
 /*
- * Note, ftrace_ops can be referenced outside of RCU protection.
- * (Although, for perf, the control ops prevent that). If ftrace_ops is
- * allocated and not part of kernel core data, the unregistering of it will
- * perform a scheduling on all CPUs to make sure that there are no more users.
- * Depending on the load of the system that may take a bit of time.
+ * Note, ftrace_ops can be referenced outside of RCU protection, unless
+ * the RCU flag is set. If ftrace_ops is allocated and not part of kernel
+ * core data, the unregistering of it will perform a scheduling on all CPUs
+ * to make sure that there are no more users. Depending on the load of the
+ * system that may take a bit of time.
  *
  * Any private data added must also take care not to be freed and if private
  * data is added to a ftrace_ops that is in core code, the user of the
@@ -196,34 +197,34 @@ int unregister_ftrace_function(struct ftrace_ops *ops);
 void clear_ftrace_function(void);
 
 /**
- * ftrace_function_local_enable - enable controlled ftrace_ops on current cpu
+ * ftrace_function_local_enable - enable ftrace_ops on current cpu
  *
  * This function enables tracing on current cpu by decreasing
  * the per cpu control variable.
  * It must be called with preemption disabled and only on ftrace_ops
- * registered with FTRACE_OPS_FL_CONTROL. If called without preemption
+ * registered with FTRACE_OPS_FL_PER_CPU. If called without preemption
  * disabled, this_cpu_ptr will complain when CONFIG_DEBUG_PREEMPT is enabled.
  */
 static inline void ftrace_function_local_enable(struct ftrace_ops *ops)
 {
-       if (WARN_ON_ONCE(!(ops->flags & FTRACE_OPS_FL_CONTROL)))
+       if (WARN_ON_ONCE(!(ops->flags & FTRACE_OPS_FL_PER_CPU)))
                return;
 
        (*this_cpu_ptr(ops->disabled))--;
 }
 
 /**
- * ftrace_function_local_disable - enable controlled ftrace_ops on current cpu
+ * ftrace_function_local_disable - disable ftrace_ops on current cpu
  *
- * This function enables tracing on current cpu by decreasing
+ * This function disables tracing on current cpu by increasing
  * the per cpu control variable.
  * It must be called with preemption disabled and only on ftrace_ops
- * registered with FTRACE_OPS_FL_CONTROL. If called without preemption
+ * registered with FTRACE_OPS_FL_PER_CPU. If called without preemption
  * disabled, this_cpu_ptr will complain when CONFIG_DEBUG_PREEMPT is enabled.
  */
 static inline void ftrace_function_local_disable(struct ftrace_ops *ops)
 {
-       if (WARN_ON_ONCE(!(ops->flags & FTRACE_OPS_FL_CONTROL)))
+       if (WARN_ON_ONCE(!(ops->flags & FTRACE_OPS_FL_PER_CPU)))
                return;
 
        (*this_cpu_ptr(ops->disabled))++;
@@ -235,12 +236,12 @@ static inline void ftrace_function_local_disable(struct ftrace_ops *ops)
  *
  * This function returns value of ftrace_ops::disabled on current cpu.
  * It must be called with preemption disabled and only on ftrace_ops
- * registered with FTRACE_OPS_FL_CONTROL. If called without preemption
+ * registered with FTRACE_OPS_FL_PER_CPU. If called without preemption
  * disabled, this_cpu_ptr will complain when CONFIG_DEBUG_PREEMPT is enabled.
  */
 static inline int ftrace_function_local_disabled(struct ftrace_ops *ops)
 {
-       WARN_ON_ONCE(!(ops->flags & FTRACE_OPS_FL_CONTROL));
+       WARN_ON_ONCE(!(ops->flags & FTRACE_OPS_FL_PER_CPU));
        return *this_cpu_ptr(ops->disabled);
 }
 
@@ -296,6 +297,21 @@ int ftrace_arch_code_modify_post_process(void);
 
 struct dyn_ftrace;
 
+enum ftrace_bug_type {
+       FTRACE_BUG_UNKNOWN,
+       FTRACE_BUG_INIT,
+       FTRACE_BUG_NOP,
+       FTRACE_BUG_CALL,
+       FTRACE_BUG_UPDATE,
+};
+extern enum ftrace_bug_type ftrace_bug_type;
+
+/*
+ * Archs can set this to point to a variable that holds the value that was
+ * expected at the call site before calling ftrace_bug().
+ */
+extern const void *ftrace_expected;
+
 void ftrace_bug(int err, struct dyn_ftrace *rec);
 
 struct seq_file;
@@ -341,6 +357,7 @@ bool is_ftrace_trampoline(unsigned long addr);
  *  REGS    - the record wants the function to save regs
  *  REGS_EN - the function is set up to save regs.
  *  IPMODIFY - the record allows for the IP address to be changed.
+ *  DISABLED - the record is not ready to be touched yet
  *
  * When a new ftrace_ops is registered and wants a function to save
  * pt_regs, the rec->flag REGS is set. When the function has been
@@ -355,10 +372,11 @@ enum {
        FTRACE_FL_TRAMP         = (1UL << 28),
        FTRACE_FL_TRAMP_EN      = (1UL << 27),
        FTRACE_FL_IPMODIFY      = (1UL << 26),
+       FTRACE_FL_DISABLED      = (1UL << 25),
 };
 
-#define FTRACE_REF_MAX_SHIFT   26
-#define FTRACE_FL_BITS         6
+#define FTRACE_REF_MAX_SHIFT   25
+#define FTRACE_FL_BITS         7
 #define FTRACE_FL_MASKED_BITS  ((1UL << FTRACE_FL_BITS) - 1)
 #define FTRACE_FL_MASK         (FTRACE_FL_MASKED_BITS << FTRACE_REF_MAX_SHIFT)
 #define FTRACE_REF_MAX         ((1UL << FTRACE_REF_MAX_SHIFT) - 1)
index 452c0b0d2f3219dc0f11bec80878e5ea0b8e8803..3b1f6cef95136fa381d06eb5ccb409dde3e030a0 100644 (file)
@@ -163,6 +163,14 @@ static inline u16 ieee80211_sn_sub(u16 sn1, u16 sn2)
 /* 30 byte 4 addr hdr, 2 byte QoS, 2304 byte MSDU, 12 byte crypt, 4 byte FCS */
 #define IEEE80211_MAX_FRAME_LEN                2352
 
+/* Maximal size of an A-MSDU */
+#define IEEE80211_MAX_MPDU_LEN_HT_3839         3839
+#define IEEE80211_MAX_MPDU_LEN_HT_7935         7935
+
+#define IEEE80211_MAX_MPDU_LEN_VHT_3895                3895
+#define IEEE80211_MAX_MPDU_LEN_VHT_7991                7991
+#define IEEE80211_MAX_MPDU_LEN_VHT_11454       11454
+
 #define IEEE80211_MAX_SSID_LEN         32
 
 #define IEEE80211_MAX_MESH_ID_LEN      32
@@ -843,6 +851,8 @@ enum ieee80211_vht_opmode_bits {
 };
 
 #define WLAN_SA_QUERY_TR_ID_LEN 2
+#define WLAN_MEMBERSHIP_LEN 8
+#define WLAN_USER_POSITION_LEN 16
 
 /**
  * struct ieee80211_tpc_report_ie
@@ -989,6 +999,11 @@ struct ieee80211_mgmt {
                                        u8 action_code;
                                        u8 operating_mode;
                                } __packed vht_opmode_notif;
+                               struct {
+                                       u8 action_code;
+                                       u8 membership[WLAN_MEMBERSHIP_LEN];
+                                       u8 position[WLAN_USER_POSITION_LEN];
+                               } __packed vht_group_notif;
                                struct {
                                        u8 action_code;
                                        u8 dialog_token;
@@ -1498,6 +1513,7 @@ struct ieee80211_vht_operation {
 #define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895                 0x00000000
 #define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991                 0x00000001
 #define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454                        0x00000002
+#define IEEE80211_VHT_CAP_MAX_MPDU_MASK                                0x00000003
 #define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ               0x00000004
 #define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ      0x00000008
 #define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK                 0x0000000C
@@ -2079,6 +2095,16 @@ enum ieee80211_tdls_actioncode {
 #define WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED    BIT(5)
 #define WLAN_EXT_CAPA8_OPMODE_NOTIF    BIT(6)
 
+/* Defines the maximal number of MSDUs in an A-MSDU. */
+#define WLAN_EXT_CAPA8_MAX_MSDU_IN_AMSDU_LSB   BIT(7)
+#define WLAN_EXT_CAPA9_MAX_MSDU_IN_AMSDU_MSB   BIT(0)
+
+/*
+ * Fine Timing Measurement Initiator - bit 71 of @WLAN_EID_EXT_CAPABILITY
+ * information element
+ */
+#define WLAN_EXT_CAPA9_FTM_INITIATOR   BIT(7)
+
 /* TDLS specific payload type in the LLC/SNAP header */
 #define WLAN_TDLS_SNAP_RFTYPE  0x2
 
index 27dac3ff18b949a0c32d508a3830f676992fc14c..bc6f7e00fb3de33438759c6c88184b7385dc86b7 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/platform_device.h>
 
 struct irq_domain;
+struct property_set;
 
 /* Matches ACPI PNP id, either _HID or _CID, or ACPI _ADR */
 struct mfd_cell_acpi_match {
@@ -44,6 +45,10 @@ struct mfd_cell {
        /* platform data passed to the sub devices drivers */
        void                    *platform_data;
        size_t                  pdata_size;
+
+       /* device properties passed to the sub devices drivers */
+       const struct property_set *pset;
+
        /*
         * Device Tree compatible string
         * See: Documentation/devicetree/usage-model.txt Chapter 2.2 for details
index 6abd019c76f8eff7d92cd71aa83c9e6d8b2ab471..03b755521fd9f4f1305971c8c7f31a86082c8ac0 100644 (file)
@@ -18,6 +18,7 @@
 #define PLATFORM_DEVID_AUTO    (-2)
 
 struct mfd_cell;
+struct property_set;
 
 struct platform_device {
        const char      *name;
@@ -71,6 +72,8 @@ struct platform_device_info {
                const void *data;
                size_t size_data;
                u64 dma_mask;
+
+               const struct property_set *pset;
 };
 extern struct platform_device *platform_device_register_full(
                const struct platform_device_info *pdevinfo);
@@ -168,6 +171,8 @@ extern int platform_device_add_resources(struct platform_device *pdev,
                                         unsigned int num);
 extern int platform_device_add_data(struct platform_device *pdev,
                                    const void *data, size_t size);
+extern int platform_device_add_properties(struct platform_device *pdev,
+                                         const struct property_set *pset);
 extern int platform_device_add(struct platform_device *pdev);
 extern void platform_device_del(struct platform_device *pdev);
 extern void platform_device_put(struct platform_device *pdev);
index 9a2e50337af9fd233656b8fb6f06a91c10b2e7bf..95403d2ccaf56b70207fa09e65c592d882fb30fd 100644 (file)
@@ -55,6 +55,11 @@ int dev_pm_opp_enable(struct device *dev, unsigned long freq);
 int dev_pm_opp_disable(struct device *dev, unsigned long freq);
 
 struct srcu_notifier_head *dev_pm_opp_get_notifier(struct device *dev);
+int dev_pm_opp_set_supported_hw(struct device *dev, const u32 *versions,
+                               unsigned int count);
+void dev_pm_opp_put_supported_hw(struct device *dev);
+int dev_pm_opp_set_prop_name(struct device *dev, const char *name);
+void dev_pm_opp_put_prop_name(struct device *dev);
 #else
 static inline unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp)
 {
@@ -129,6 +134,23 @@ static inline struct srcu_notifier_head *dev_pm_opp_get_notifier(
 {
        return ERR_PTR(-EINVAL);
 }
+
+static inline int dev_pm_opp_set_supported_hw(struct device *dev,
+                                             const u32 *versions,
+                                             unsigned int count)
+{
+       return -EINVAL;
+}
+
+static inline void dev_pm_opp_put_supported_hw(struct device *dev) {}
+
+static inline int dev_pm_opp_set_prop_name(struct device *dev, const char *name)
+{
+       return -EINVAL;
+}
+
+static inline void dev_pm_opp_put_prop_name(struct device *dev) {}
+
 #endif         /* CONFIG_PM_OPP */
 
 #if defined(CONFIG_PM_OPP) && defined(CONFIG_OF)
index 3bdbb4189780043f4e83af2e7d02401251f181a7..7af093d6a4dd16016ef5699ec2b593dda1902e06 100644 (file)
@@ -39,6 +39,7 @@ extern int pm_runtime_force_resume(struct device *dev);
 extern int __pm_runtime_idle(struct device *dev, int rpmflags);
 extern int __pm_runtime_suspend(struct device *dev, int rpmflags);
 extern int __pm_runtime_resume(struct device *dev, int rpmflags);
+extern int pm_runtime_get_if_in_use(struct device *dev);
 extern int pm_schedule_suspend(struct device *dev, unsigned int delay);
 extern int __pm_runtime_set_status(struct device *dev, unsigned int status);
 extern int pm_runtime_barrier(struct device *dev);
@@ -143,6 +144,10 @@ static inline int pm_schedule_suspend(struct device *dev, unsigned int delay)
 {
        return -ENOSYS;
 }
+static inline int pm_runtime_get_if_in_use(struct device *dev)
+{
+       return -EINVAL;
+}
 static inline int __pm_runtime_set_status(struct device *dev,
                                            unsigned int status) { return 0; }
 static inline int pm_runtime_barrier(struct device *dev) { return 0; }
index 4e250417ee30b803838e156c7b74d1da2cb5ef65..f0a4e6257dcc8e8785304cf4a785d91f9d41bedb 100644 (file)
@@ -208,7 +208,7 @@ struct powercap_zone_constraint_ops {
 struct powercap_zone_constraint {
        int id;
        struct powercap_zone *power_zone;
-       struct powercap_zone_constraint_ops *ops;
+       const struct powercap_zone_constraint_ops *ops;
 };
 
 
@@ -309,7 +309,7 @@ struct powercap_zone *powercap_register_zone(
                        struct powercap_zone *parent,
                        const struct powercap_zone_ops *ops,
                        int nr_constraints,
-                       struct powercap_zone_constraint_ops *const_ops);
+                       const struct powercap_zone_constraint_ops *const_ops);
 
 /**
 * powercap_unregister_zone() - Unregister a zone device
index 0a3705a7c9f2a9cafeee00ab8d901b202d631c47..b51fcd36d8925dbba20564997463555bef109ed2 100644 (file)
@@ -73,8 +73,8 @@ int fwnode_property_match_string(struct fwnode_handle *fwnode,
 struct fwnode_handle *device_get_next_child_node(struct device *dev,
                                                 struct fwnode_handle *child);
 
-#define device_for_each_child_node(dev, child) \
-       for (child = device_get_next_child_node(dev, NULL); child; \
+#define device_for_each_child_node(dev, child)                         \
+       for (child = device_get_next_child_node(dev, NULL); child;      \
             child = device_get_next_child_node(dev, child))
 
 void fwnode_handle_put(struct fwnode_handle *fwnode);
@@ -144,24 +144,100 @@ static inline int fwnode_property_read_u64(struct fwnode_handle *fwnode,
 /**
  * struct property_entry - "Built-in" device property representation.
  * @name: Name of the property.
- * @type: Type of the property.
- * @nval: Number of items of type @type making up the value.
- * @value: Value of the property (an array of @nval items of type @type).
+ * @length: Length of data making up the value.
+ * @is_array: True when the property is an array.
+ * @is_string: True when property is a string.
+ * @pointer: Pointer to the property (an array of items of the given type).
+ * @value: Value of the property (when it is a single item of the given type).
  */
 struct property_entry {
        const char *name;
-       enum dev_prop_type type;
-       size_t nval;
+       size_t length;
+       bool is_array;
+       bool is_string;
        union {
-               void *raw_data;
-               u8 *u8_data;
-               u16 *u16_data;
-               u32 *u32_data;
-               u64 *u64_data;
-               const char **str;
-       } value;
+               union {
+                       void *raw_data;
+                       u8 *u8_data;
+                       u16 *u16_data;
+                       u32 *u32_data;
+                       u64 *u64_data;
+                       const char **str;
+               } pointer;
+               union {
+                       unsigned long long raw_data;
+                       u8 u8_data;
+                       u16 u16_data;
+                       u32 u32_data;
+                       u64 u64_data;
+                       const char *str;
+               } value;
+       };
 };
 
+/*
+ * Note: the below four initializers for the anonymous union are carefully
+ * crafted to avoid gcc-4.4.4's problems with initialization of anon unions
+ * and structs.
+ */
+
+#define PROPERTY_ENTRY_INTEGER_ARRAY(_name_, _type_, _val_)    \
+{                                                              \
+       .name = _name_,                                         \
+       .length = ARRAY_SIZE(_val_) * sizeof(_type_),           \
+       .is_array = true,                                       \
+       .is_string = false,                                     \
+       { .pointer = { _type_##_data = _val_ } },               \
+}
+
+#define PROPERTY_ENTRY_U8_ARRAY(_name_, _val_)                 \
+       PROPERTY_ENTRY_INTEGER_ARRAY(_name_, u8, _val_)
+#define PROPERTY_ENTRY_U16_ARRAY(_name_, _val_)                        \
+       PROPERTY_ENTRY_INTEGER_ARRAY(_name_, u16, _val_)
+#define PROPERTY_ENTRY_U32_ARRAY(_name_, _val_)                        \
+       PROPERTY_ENTRY_INTEGER_ARRAY(_name_, u32, _val_)
+#define PROPERTY_ENTRY_U64_ARRAY(_name_, _val_)                        \
+       PROPERTY_ENTRY_INTEGER_ARRAY(_name_, u64, _val_)
+
+#define PROPERTY_ENTRY_STRING_ARRAY(_name_, _val_)             \
+{                                                              \
+       .name = _name_,                                         \
+       .length = ARRAY_SIZE(_val_) * sizeof(const char *),     \
+       .is_array = true,                                       \
+       .is_string = true,                                      \
+       { .pointer = { .str = _val_ } },                        \
+}
+
+#define PROPERTY_ENTRY_INTEGER(_name_, _type_, _val_)  \
+{                                                      \
+       .name = _name_,                                 \
+       .length = sizeof(_type_),                       \
+       .is_string = false,                             \
+       { .value = { ._type_##_data = _val_ } },        \
+}
+
+#define PROPERTY_ENTRY_U8(_name_, _val_)               \
+       PROPERTY_ENTRY_INTEGER(_name_, u8, _val_)
+#define PROPERTY_ENTRY_U16(_name_, _val_)              \
+       PROPERTY_ENTRY_INTEGER(_name_, u16, _val_)
+#define PROPERTY_ENTRY_U32(_name_, _val_)              \
+       PROPERTY_ENTRY_INTEGER(_name_, u32, _val_)
+#define PROPERTY_ENTRY_U64(_name_, _val_)              \
+       PROPERTY_ENTRY_INTEGER(_name_, u64, _val_)
+
+#define PROPERTY_ENTRY_STRING(_name_, _val_)           \
+{                                                      \
+       .name = _name_,                                 \
+       .length = sizeof(_val_),                        \
+       .is_string = true,                              \
+       { .value = { .str = _val_ } },                  \
+}
+
+#define PROPERTY_ENTRY_BOOL(_name_)            \
+{                                              \
+       .name = _name_,                         \
+}
+
 /**
  * struct property_set - Collection of "built-in" device properties.
  * @fwnode: Handle to be pointed to by the fwnode field of struct device.
@@ -172,7 +248,8 @@ struct property_set {
        struct property_entry *properties;
 };
 
-void device_add_property_set(struct device *dev, struct property_set *pset);
+int device_add_property_set(struct device *dev, const struct property_set *pset);
+void device_remove_property_set(struct device *dev);
 
 bool device_dma_supported(struct device *dev);
 
diff --git a/include/linux/rfkill-gpio.h b/include/linux/rfkill-gpio.h
deleted file mode 100644 (file)
index 20bcb55..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2011, NVIDIA Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-
-#ifndef __RFKILL_GPIO_H
-#define __RFKILL_GPIO_H
-
-#include <linux/types.h>
-#include <linux/rfkill.h>
-
-/**
- * struct rfkill_gpio_platform_data - platform data for rfkill gpio device.
- * for unused gpio's, the expected value is -1.
- * @name:              name for the gpio rf kill instance
- */
-
-struct rfkill_gpio_platform_data {
-       char                    *name;
-       enum rfkill_type        type;
-};
-
-#endif /* __RFKILL_GPIO_H */
index d9010789b4e8215cc74a2ffc12e83f3cfd9b73cd..e6a0031d1b1fdc1793200d1fc93f48bf1973ecfc 100644 (file)
@@ -104,7 +104,8 @@ int __must_check rfkill_register(struct rfkill *rfkill);
  *
  * Pause polling -- say transmitter is off for other reasons.
  * NOTE: not necessary for suspend/resume -- in that case the
- * core stops polling anyway
+ * core stops polling anyway (but will also correctly handle
+ * the case of polling having been paused before suspend.)
  */
 void rfkill_pause_polling(struct rfkill *rfkill);
 
@@ -212,6 +213,15 @@ void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw);
  * @rfkill: rfkill struct to query
  */
 bool rfkill_blocked(struct rfkill *rfkill);
+
+/**
+ * rfkill_find_type - Helpper for finding rfkill type by name
+ * @name: the name of the type
+ *
+ * Returns enum rfkill_type that conrresponds the name.
+ */
+enum rfkill_type rfkill_find_type(const char *name);
+
 #else /* !RFKILL */
 static inline struct rfkill * __must_check
 rfkill_alloc(const char *name,
@@ -268,6 +278,12 @@ static inline bool rfkill_blocked(struct rfkill *rfkill)
 {
        return false;
 }
+
+static inline enum rfkill_type rfkill_find_type(const char *name)
+{
+       return RFKILL_TYPE_ALL;
+}
+
 #endif /* RFKILL || RFKILL_MODULE */
 
 
index 78e8397a1800334f329637baa152f3ed6c79718a..acd522a91539155db94143d5da4e4848a44a437e 100644 (file)
@@ -479,6 +479,10 @@ extern void syscall_unregfunc(void);
 #define TRACE_EVENT_FN(name, proto, args, struct,              \
                assign, print, reg, unreg)                      \
        DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
+#define TRACE_EVENT_FN_COND(name, proto, args, cond, struct,           \
+               assign, print, reg, unreg)                      \
+       DECLARE_TRACE_CONDITION(name, PARAMS(proto),    \
+                       PARAMS(args), PARAMS(cond))
 #define TRACE_EVENT_CONDITION(name, proto, args, cond,         \
                              struct, assign, print)            \
        DECLARE_TRACE_CONDITION(name, PARAMS(proto),            \
index 9bcaaf7cd15ab053a5de9cbf92fd02f0fb0ffaf7..9e1b24c29f0c65ce997d71a566e63125f7a6e248 100644 (file)
@@ -712,6 +712,8 @@ struct cfg80211_acl_data {
  * @p2p_opp_ps: P2P opportunistic PS
  * @acl: ACL configuration used by the drivers which has support for
  *     MAC address based access control
+ * @pbss: If set, start as a PCP instead of AP. Relevant for DMG
+ *     networks.
  */
 struct cfg80211_ap_settings {
        struct cfg80211_chan_def chandef;
@@ -730,6 +732,7 @@ struct cfg80211_ap_settings {
        u8 p2p_ctwindow;
        bool p2p_opp_ps;
        const struct cfg80211_acl_data *acl;
+       bool pbss;
 };
 
 /**
@@ -1888,6 +1891,8 @@ struct cfg80211_ibss_params {
  * @ht_capa_mask:  The bits of ht_capa which are to be used.
  * @vht_capa:  VHT Capability overrides
  * @vht_capa_mask: The bits of vht_capa which are to be used.
+ * @pbss: if set, connect to a PCP instead of AP. Valid for DMG
+ *     networks.
  */
 struct cfg80211_connect_params {
        struct ieee80211_channel *channel;
@@ -1910,6 +1915,7 @@ struct cfg80211_connect_params {
        struct ieee80211_ht_cap ht_capa_mask;
        struct ieee80211_vht_cap vht_capa;
        struct ieee80211_vht_cap vht_capa_mask;
+       bool pbss;
 };
 
 /**
@@ -3489,6 +3495,7 @@ struct cfg80211_cached_keys;
  *     registered for unexpected class 3 frames (AP mode)
  * @conn: (private) cfg80211 software SME connection state machine data
  * @connect_keys: (private) keys to set after connection is established
+ * @conn_bss_type: connecting/connected BSS type
  * @ibss_fixed: (private) IBSS is using fixed BSSID
  * @ibss_dfs_possible: (private) IBSS may change to a DFS channel
  * @event_list: (private) list for internal event processing
@@ -3519,6 +3526,7 @@ struct wireless_dev {
        u8 ssid_len, mesh_id_len, mesh_id_up_len;
        struct cfg80211_conn *conn;
        struct cfg80211_cached_keys *connect_keys;
+       enum ieee80211_bss_type conn_bss_type;
 
        struct list_head event_list;
        spinlock_t event_lock;
index 7c30faff245f262a59831132f84f5cb37c2cc8a5..0c09da34b67a7e7ca4ab45fd1da8f132d8bedc63 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
  * Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
- * Copyright (C) 2015 Intel Deutschland GmbH
+ * Copyright (C) 2015 - 2016 Intel Deutschland GmbH
  *
  * 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
@@ -298,6 +298,7 @@ struct ieee80211_vif_chanctx_switch {
  *     note that this is only called when it changes after the channel
  *     context had been assigned.
  * @BSS_CHANGED_OCB: OCB join status changed
+ * @BSS_CHANGED_MU_GROUPS: VHT MU-MIMO group id or user position changed
  */
 enum ieee80211_bss_change {
        BSS_CHANGED_ASSOC               = 1<<0,
@@ -323,6 +324,7 @@ enum ieee80211_bss_change {
        BSS_CHANGED_BEACON_INFO         = 1<<20,
        BSS_CHANGED_BANDWIDTH           = 1<<21,
        BSS_CHANGED_OCB                 = 1<<22,
+       BSS_CHANGED_MU_GROUPS           = 1<<23,
 
        /* when adding here, make sure to change ieee80211_reconfig */
 };
@@ -435,6 +437,19 @@ struct ieee80211_event {
        } u;
 };
 
+/**
+ * struct ieee80211_mu_group_data - STA's VHT MU-MIMO group data
+ *
+ * This structure describes the group id data of VHT MU-MIMO
+ *
+ * @membership: 64 bits array - a bit is set if station is member of the group
+ * @position: 2 bits per group id indicating the position in the group
+ */
+struct ieee80211_mu_group_data {
+       u8 membership[WLAN_MEMBERSHIP_LEN];
+       u8 position[WLAN_USER_POSITION_LEN];
+};
+
 /**
  * struct ieee80211_bss_conf - holds the BSS's changing parameters
  *
@@ -477,6 +492,7 @@ struct ieee80211_event {
  * @enable_beacon: whether beaconing should be enabled or not
  * @chandef: Channel definition for this BSS -- the hardware might be
  *     configured a higher bandwidth than this BSS uses, for example.
+ * @mu_group: VHT MU-MIMO group membership data
  * @ht_operation_mode: HT operation mode like in &struct ieee80211_ht_operation.
  *     This field is only valid when the channel is a wide HT/VHT channel.
  *     Note that with TDLS this can be the case (channel is HT, protection must
@@ -535,6 +551,7 @@ struct ieee80211_bss_conf {
        s32 cqm_rssi_thold;
        u32 cqm_rssi_hyst;
        struct cfg80211_chan_def chandef;
+       struct ieee80211_mu_group_data mu_group;
        __be32 arp_addr_list[IEEE80211_BSS_ARP_ADDR_LIST_LEN];
        int arp_addr_cnt;
        bool qos;
@@ -691,12 +708,14 @@ enum mac80211_tx_info_flags {
  *     protocol frame (e.g. EAP)
  * @IEEE80211_TX_CTRL_PS_RESPONSE: This frame is a response to a poll
  *     frame (PS-Poll or uAPSD).
+ * @IEEE80211_TX_CTRL_RATE_INJECT: This frame is injected with rate information
  *
  * These flags are used in tx_info->control.flags.
  */
 enum mac80211_tx_control_flags {
        IEEE80211_TX_CTRL_PORT_CTRL_PROTO       = BIT(0),
        IEEE80211_TX_CTRL_PS_RESPONSE           = BIT(1),
+       IEEE80211_TX_CTRL_RATE_INJECT           = BIT(2),
 };
 
 /*
@@ -993,6 +1012,8 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
  * @RX_FLAG_MACTIME_END: The timestamp passed in the RX status (@mactime
  *     field) is valid and contains the time the last symbol of the MPDU
  *     (including FCS) was received.
+ * @RX_FLAG_MACTIME_PLCP_START: The timestamp passed in the RX status (@mactime
+ *     field) is valid and contains the time the SYNC preamble was received.
  * @RX_FLAG_SHORTPRE: Short preamble was used for this frame
  * @RX_FLAG_HT: HT MCS was used and rate_idx is MCS index
  * @RX_FLAG_VHT: VHT MCS was used and rate_index is MCS index
@@ -1014,6 +1035,14 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
  * @RX_FLAG_AMPDU_DELIM_CRC_KNOWN: The delimiter CRC field is known (the CRC
  *     is stored in the @ampdu_delimiter_crc field)
  * @RX_FLAG_LDPC: LDPC was used
+ * @RX_FLAG_ONLY_MONITOR: Report frame only to monitor interfaces without
+ *     processing it in any regular way.
+ *     This is useful if drivers offload some frames but still want to report
+ *     them for sniffing purposes.
+ * @RX_FLAG_SKIP_MONITOR: Process and report frame to all interfaces except
+ *     monitor interfaces.
+ *     This is useful if drivers offload some frames but still want to report
+ *     them for sniffing purposes.
  * @RX_FLAG_STBC_MASK: STBC 2 bit bitmask. 1 - Nss=1, 2 - Nss=2, 3 - Nss=3
  * @RX_FLAG_10MHZ: 10 MHz (half channel) was used
  * @RX_FLAG_5MHZ: 5 MHz (quarter channel) was used
@@ -1033,6 +1062,7 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
 enum mac80211_rx_flags {
        RX_FLAG_MMIC_ERROR              = BIT(0),
        RX_FLAG_DECRYPTED               = BIT(1),
+       RX_FLAG_MACTIME_PLCP_START      = BIT(2),
        RX_FLAG_MMIC_STRIPPED           = BIT(3),
        RX_FLAG_IV_STRIPPED             = BIT(4),
        RX_FLAG_FAILED_FCS_CRC          = BIT(5),
@@ -1046,7 +1076,7 @@ enum mac80211_rx_flags {
        RX_FLAG_HT_GF                   = BIT(13),
        RX_FLAG_AMPDU_DETAILS           = BIT(14),
        RX_FLAG_PN_VALIDATED            = BIT(15),
-       /* bit 16 free */
+       RX_FLAG_DUP_VALIDATED           = BIT(16),
        RX_FLAG_AMPDU_LAST_KNOWN        = BIT(17),
        RX_FLAG_AMPDU_IS_LAST           = BIT(18),
        RX_FLAG_AMPDU_DELIM_CRC_ERROR   = BIT(19),
@@ -1054,6 +1084,8 @@ enum mac80211_rx_flags {
        RX_FLAG_MACTIME_END             = BIT(21),
        RX_FLAG_VHT                     = BIT(22),
        RX_FLAG_LDPC                    = BIT(23),
+       RX_FLAG_ONLY_MONITOR            = BIT(24),
+       RX_FLAG_SKIP_MONITOR            = BIT(25),
        RX_FLAG_STBC_MASK               = BIT(26) | BIT(27),
        RX_FLAG_10MHZ                   = BIT(28),
        RX_FLAG_5MHZ                    = BIT(29),
@@ -1072,6 +1104,7 @@ enum mac80211_rx_flags {
  * @RX_VHT_FLAG_160MHZ: 160 MHz was used
  * @RX_VHT_FLAG_BF: packet was beamformed
  */
+
 enum mac80211_rx_vht_flags {
        RX_VHT_FLAG_80MHZ               = BIT(0),
        RX_VHT_FLAG_160MHZ              = BIT(1),
@@ -1091,6 +1124,8 @@ enum mac80211_rx_vht_flags {
  *     it but can store it and pass it back to the driver for synchronisation
  * @band: the active band when this frame was received
  * @freq: frequency the radio was tuned to when receiving this frame, in MHz
+ *     This field must be set for management frames, but isn't strictly needed
+ *     for data (other) frames - for those it only affects radiotap reporting.
  * @signal: signal strength when receiving this frame, either in dBm, in dB or
  *     unspecified depending on the hardware capabilities flags
  *     @IEEE80211_HW_SIGNAL_*
@@ -1347,6 +1382,7 @@ enum ieee80211_vif_flags {
  * @csa_active: marks whether a channel switch is going on. Internally it is
  *     write-protected by sdata_lock and local->mtx so holding either is fine
  *     for read access.
+ * @mu_mimo_owner: indicates interface owns MU-MIMO capability
  * @driver_flags: flags/capabilities the driver has for this interface,
  *     these need to be set (or cleared) when the interface is added
  *     or, if supported by the driver, the interface type is changed
@@ -1373,6 +1409,7 @@ struct ieee80211_vif {
        u8 addr[ETH_ALEN];
        bool p2p;
        bool csa_active;
+       bool mu_mimo_owner;
 
        u8 cab_queue;
        u8 hw_queue[IEEE80211_NUM_ACS];
@@ -1486,9 +1523,8 @@ enum ieee80211_key_flags {
  *     wants to be given when a frame is transmitted and needs to be
  *     encrypted in hardware.
  * @cipher: The key's cipher suite selector.
- * @tx_pn: PN used for TX on non-TKIP keys, may be used by the driver
- *     as well if it needs to do software PN assignment by itself
- *     (e.g. due to TSO)
+ * @tx_pn: PN used for TX keys, may be used by the driver as well if it
+ *     needs to do software PN assignment by itself (e.g. due to TSO)
  * @flags: key flags, see &enum ieee80211_key_flags.
  * @keyidx: the key index (0-3)
  * @keylen: key material length
@@ -1514,6 +1550,9 @@ struct ieee80211_key_conf {
 
 #define IEEE80211_MAX_PN_LEN   16
 
+#define TKIP_PN_TO_IV16(pn) ((u16)(pn & 0xffff))
+#define TKIP_PN_TO_IV32(pn) ((u32)((pn >> 16) & 0xffffffff))
+
 /**
  * struct ieee80211_key_seq - key sequence counter
  *
@@ -1684,6 +1723,18 @@ struct ieee80211_sta_rates {
  * @tdls_initiator: indicates the STA is an initiator of the TDLS link. Only
  *     valid if the STA is a TDLS peer in the first place.
  * @mfp: indicates whether the STA uses management frame protection or not.
+ * @max_amsdu_subframes: indicates the maximal number of MSDUs in a single
+ *     A-MSDU. Taken from the Extended Capabilities element. 0 means
+ *     unlimited.
+ * @max_amsdu_len: indicates the maximal length of an A-MSDU in bytes. This
+ *     field is always valid for packets with a VHT preamble. For packets
+ *     with a HT preamble, additional limits apply:
+ *             + If the skb is transmitted as part of a BA agreement, the
+ *               A-MSDU maximal size is min(max_amsdu_len, 4065) bytes.
+ *             + If the skb is not part of a BA aggreement, the A-MSDU maximal
+ *               size is min(max_amsdu_len, 7935) bytes.
+ *     Both additional HT limits must be enforced by the low level driver.
+ *     This is defined by the spec (IEEE 802.11-2012 section 8.3.2.2 NOTE 2).
  * @txq: per-TID data TX queues (if driver uses the TXQ abstraction)
  */
 struct ieee80211_sta {
@@ -1702,6 +1753,8 @@ struct ieee80211_sta {
        bool tdls;
        bool tdls_initiator;
        bool mfp;
+       u8 max_amsdu_subframes;
+       u16 max_amsdu_len;
 
        struct ieee80211_txq *txq[IEEE80211_NUM_TIDS];
 
@@ -1910,6 +1963,11 @@ struct ieee80211_txq {
  *     by just its MAC address; this prevents, for example, the same station
  *     from connecting to two virtual AP interfaces at the same time.
  *
+ * @IEEE80211_HW_SUPPORTS_REORDERING_BUFFER: Hardware (or driver) manages the
+ *     reordering buffer internally, guaranteeing mac80211 receives frames in
+ *     order and does not need to manage its own reorder buffer or BA session
+ *     timeout.
+ *
  * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
  */
 enum ieee80211_hw_flags {
@@ -1946,6 +2004,7 @@ enum ieee80211_hw_flags {
        IEEE80211_HW_SUPPORTS_AMSDU_IN_AMPDU,
        IEEE80211_HW_BEACON_TX_STATUS,
        IEEE80211_HW_NEEDS_UNIQUE_STA_ADDR,
+       IEEE80211_HW_SUPPORTS_REORDERING_BUFFER,
 
        /* keep last, obviously */
        NUM_IEEE80211_HW_FLAGS
@@ -2167,7 +2226,7 @@ static inline void SET_IEEE80211_DEV(struct ieee80211_hw *hw, struct device *dev
  * @hw: the &struct ieee80211_hw to set the MAC address for
  * @addr: the address to set
  */
-static inline void SET_IEEE80211_PERM_ADDR(struct ieee80211_hw *hw, u8 *addr)
+static inline void SET_IEEE80211_PERM_ADDR(struct ieee80211_hw *hw, const u8 *addr)
 {
        memcpy(hw->wiphy->perm_addr, addr, ETH_ALEN);
 }
@@ -2683,6 +2742,33 @@ enum ieee80211_ampdu_mlme_action {
        IEEE80211_AMPDU_TX_OPERATIONAL,
 };
 
+/**
+ * struct ieee80211_ampdu_params - AMPDU action parameters
+ *
+ * @action: the ampdu action, value from %ieee80211_ampdu_mlme_action.
+ * @sta: peer of this AMPDU session
+ * @tid: tid of the BA session
+ * @ssn: start sequence number of the session. TX/RX_STOP can pass 0. When
+ *     action is set to %IEEE80211_AMPDU_RX_START the driver passes back the
+ *     actual ssn value used to start the session and writes the value here.
+ * @buf_size: reorder buffer size  (number of subframes). Valid only when the
+ *     action is set to %IEEE80211_AMPDU_RX_START or
+ *     %IEEE80211_AMPDU_TX_OPERATIONAL
+ * @amsdu: indicates the peer's ability to receive A-MSDU within A-MPDU.
+ *     valid when the action is set to %IEEE80211_AMPDU_TX_OPERATIONAL
+ * @timeout: BA session timeout. Valid only when the action is set to
+ *     %IEEE80211_AMPDU_RX_START
+ */
+struct ieee80211_ampdu_params {
+       enum ieee80211_ampdu_mlme_action action;
+       struct ieee80211_sta *sta;
+       u16 tid;
+       u16 ssn;
+       u8 buf_size;
+       bool amsdu;
+       u16 timeout;
+};
+
 /**
  * enum ieee80211_frame_release_type - frame release reason
  * @IEEE80211_FRAME_RELEASE_PSPOLL: frame released for PS-Poll
@@ -3027,13 +3113,9 @@ enum ieee80211_reconfig_type {
  * @ampdu_action: Perform a certain A-MPDU action
  *     The RA/TID combination determines the destination and TID we want
  *     the ampdu action to be performed for. The action is defined through
- *     ieee80211_ampdu_mlme_action. Starting sequence number (@ssn)
- *     is the first frame we expect to perform the action on. Notice
- *     that TX/RX_STOP can pass NULL for this parameter.
- *     The @buf_size parameter is only valid when the action is set to
- *     %IEEE80211_AMPDU_TX_OPERATIONAL and indicates the peer's reorder
- *     buffer size (number of subframes) for this session -- the driver
- *     may neither send aggregates containing more subframes than this
+ *     ieee80211_ampdu_mlme_action.
+ *     When the action is set to %IEEE80211_AMPDU_TX_OPERATIONAL the driver
+ *     may neither send aggregates containing more subframes than @buf_size
  *     nor send aggregates in a way that lost frames would exceed the
  *     buffer size. If just limiting the aggregate size, this would be
  *     possible with a buf_size of 8:
@@ -3044,9 +3126,6 @@ enum ieee80211_reconfig_type {
  *     buffer size of 8. Correct ways to retransmit #1 would be:
  *      - TX:       1 or 18 or 81
  *     Even "189" would be wrong since 1 could be lost again.
- *     The @amsdu parameter is valid when the action is set to
- *     %IEEE80211_AMPDU_TX_OPERATIONAL and indicates the peer's ability
- *     to receive A-MSDU within A-MPDU.
  *
  *     Returns a negative error code on failure.
  *     The callback can sleep.
@@ -3388,9 +3467,7 @@ struct ieee80211_ops {
        int (*tx_last_beacon)(struct ieee80211_hw *hw);
        int (*ampdu_action)(struct ieee80211_hw *hw,
                            struct ieee80211_vif *vif,
-                           enum ieee80211_ampdu_mlme_action action,
-                           struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-                           u8 buf_size, bool amsdu);
+                           struct ieee80211_ampdu_params *params);
        int (*get_survey)(struct ieee80211_hw *hw, int idx,
                struct survey_info *survey);
        void (*rfkill_poll)(struct ieee80211_hw *hw);
@@ -4374,21 +4451,19 @@ void ieee80211_get_tkip_p2k(struct ieee80211_key_conf *keyconf,
                            struct sk_buff *skb, u8 *p2k);
 
 /**
- * ieee80211_get_key_tx_seq - get key TX sequence counter
+ * ieee80211_tkip_add_iv - write TKIP IV and Ext. IV to pos
  *
+ * @pos: start of crypto header
  * @keyconf: the parameter passed with the set key
- * @seq: buffer to receive the sequence data
+ * @pn: PN to add
  *
- * This function allows a driver to retrieve the current TX IV/PN
- * for the given key. It must not be called if IV generation is
- * offloaded to the device.
+ * Returns: pointer to the octet following IVs (i.e. beginning of
+ * the packet payload)
  *
- * Note that this function may only be called when no TX processing
- * can be done concurrently, for example when queues are stopped
- * and the stop has been synchronized.
+ * This function writes the tkip IV value to pos (which should
+ * point to the crypto header)
  */
-void ieee80211_get_key_tx_seq(struct ieee80211_key_conf *keyconf,
-                             struct ieee80211_key_seq *seq);
+u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key_conf *keyconf, u64 pn);
 
 /**
  * ieee80211_get_key_rx_seq - get key RX sequence counter
@@ -4409,23 +4484,6 @@ void ieee80211_get_key_tx_seq(struct ieee80211_key_conf *keyconf,
 void ieee80211_get_key_rx_seq(struct ieee80211_key_conf *keyconf,
                              int tid, struct ieee80211_key_seq *seq);
 
-/**
- * ieee80211_set_key_tx_seq - set key TX sequence counter
- *
- * @keyconf: the parameter passed with the set key
- * @seq: new sequence data
- *
- * This function allows a driver to set the current TX IV/PNs for the
- * given key. This is useful when resuming from WoWLAN sleep and the
- * device may have transmitted frames using the PTK, e.g. replies to
- * ARP requests.
- *
- * Note that this function may only be called when no TX processing
- * can be done concurrently.
- */
-void ieee80211_set_key_tx_seq(struct ieee80211_key_conf *keyconf,
-                             struct ieee80211_key_seq *seq);
-
 /**
  * ieee80211_set_key_rx_seq - set key RX sequence counter
  *
@@ -5120,6 +5178,24 @@ void ieee80211_remain_on_channel_expired(struct ieee80211_hw *hw);
 void ieee80211_stop_rx_ba_session(struct ieee80211_vif *vif, u16 ba_rx_bitmap,
                                  const u8 *addr);
 
+/**
+ * ieee80211_mark_rx_ba_filtered_frames - move RX BA window and mark filtered
+ * @pubsta: station struct
+ * @tid: the session's TID
+ * @ssn: starting sequence number of the bitmap, all frames before this are
+ *     assumed to be out of the window after the call
+ * @filtered: bitmap of filtered frames, BIT(0) is the @ssn entry etc.
+ * @received_mpdus: number of received mpdus in firmware
+ *
+ * This function moves the BA window and releases all frames before @ssn, and
+ * marks frames marked in the bitmap as having been filtered. Afterwards, it
+ * checks if any frames in the window starting from @ssn can now be released
+ * (in case they were only waiting for frames that were filtered.)
+ */
+void ieee80211_mark_rx_ba_filtered_frames(struct ieee80211_sta *pubsta, u8 tid,
+                                         u16 ssn, u64 filtered,
+                                         u16 received_mpdus);
+
 /**
  * ieee80211_send_bar - send a BlockAckReq frame
  *
@@ -5371,6 +5447,21 @@ ieee80211_vif_type_p2p(struct ieee80211_vif *vif)
        return ieee80211_iftype_p2p(vif->type, vif->p2p);
 }
 
+/**
+ * ieee80211_update_mu_groups - set the VHT MU-MIMO groud data
+ *
+ * @vif: the specified virtual interface
+ * @membership: 64 bits array - a bit is set if station is member of the group
+ * @position: 2 bits per group id indicating the position in the group
+ *
+ * Note: This function assumes that the given vif is valid and the position and
+ * membership data is of the correct size and are in the same byte order as the
+ * matching GroupId management frame.
+ * Calls to this function need to be serialized with RX path.
+ */
+void ieee80211_update_mu_groups(struct ieee80211_vif *vif,
+                               const u8 *membership, const u8 *position);
+
 void ieee80211_enable_rssi_reports(struct ieee80211_vif *vif,
                                   int rssi_min_thold,
                                   int rssi_max_thold);
@@ -5523,4 +5614,19 @@ void ieee80211_unreserve_tid(struct ieee80211_sta *sta, u8 tid);
  */
 struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
                                     struct ieee80211_txq *txq);
+
+/**
+ * ieee80211_txq_get_depth - get pending frame/byte count of given txq
+ *
+ * The values are not guaranteed to be coherent with regard to each other, i.e.
+ * txq state can change half-way of this function and the caller may end up
+ * with "new" frame_cnt and "old" byte_cnt or vice-versa.
+ *
+ * @txq: pointer obtained from station or virtual interface
+ * @frame_cnt: pointer to store frame count
+ * @byte_cnt: pointer to store byte count
+ */
+void ieee80211_txq_get_depth(struct ieee80211_txq *txq,
+                            unsigned long *frame_cnt,
+                            unsigned long *byte_cnt);
 #endif /* MAC80211_H */
index 2d8639ea64d54dd7dd0f314281cfe1798a392250..6e3945f64102c275669fc3a0c21f910c3be7be03 100644 (file)
                assign, print, reg, unreg)                      \
        DEFINE_TRACE_FN(name, reg, unreg)
 
+#undef TRACE_EVENT_FN_COND
+#define TRACE_EVENT_FN_COND(name, proto, args, cond, tstruct,          \
+               assign, print, reg, unreg)                      \
+       DEFINE_TRACE_FN(name, reg, unreg)
+
 #undef DEFINE_EVENT
 #define DEFINE_EVENT(template, name, proto, args) \
        DEFINE_TRACE(name)
@@ -93,6 +98,7 @@
 
 #undef TRACE_EVENT
 #undef TRACE_EVENT_FN
+#undef TRACE_EVENT_FN_COND
 #undef TRACE_EVENT_CONDITION
 #undef DECLARE_EVENT_CLASS
 #undef DEFINE_EVENT
index de996cf610536ee0da0657f2a4e9aae071793755..170c93bbdbb75e1be7a4efb71c7873d6c84d9e35 100644 (file)
@@ -123,6 +123,12 @@ TRACE_MAKE_SYSTEM_STR();
        TRACE_EVENT(name, PARAMS(proto), PARAMS(args),                  \
                PARAMS(tstruct), PARAMS(assign), PARAMS(print))         \
 
+#undef TRACE_EVENT_FN_COND
+#define TRACE_EVENT_FN_COND(name, proto, args, cond, tstruct,  \
+               assign, print, reg, unreg)                              \
+       TRACE_EVENT_CONDITION(name, PARAMS(proto), PARAMS(args), PARAMS(cond),          \
+               PARAMS(tstruct), PARAMS(assign), PARAMS(print))         \
+
 #undef TRACE_EVENT_FLAGS
 #define TRACE_EVENT_FLAGS(name, value)                                 \
        __TRACE_EVENT_FLAGS(name, value)
index accb036bbc9c3621d9929dda225b6d0689348860..b283d56c1db97955f0558776fdc98e03294b7ce0 100644 (file)
@@ -54,6 +54,7 @@
 
 #define SMB_SUPER_MAGIC                0x517B
 #define CGROUP_SUPER_MAGIC     0x27e0eb
+#define CGROUP2_SUPER_MAGIC    0x63677270
 
 
 #define STACK_END_MAGIC                0x57AC6E9D
index 5b7b5ebe7ca8731868e38bfab6218c166cb0317d..5a30a75636338364f0400eeb82954f059da17b22 100644 (file)
@@ -1727,6 +1727,8 @@ enum nl80211_commands {
  *     underlying device supports these minimal RRM features:
  *             %NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES,
  *             %NL80211_FEATURE_QUIET,
+ *     Or, if global RRM is supported, see:
+ *             %NL80211_EXT_FEATURE_RRM
  *     If this flag is used, driver must add the Power Capabilities IE to the
  *     association request. In addition, it must also set the RRM capability
  *     flag in the association request's Capability Info field.
@@ -1789,6 +1791,10 @@ enum nl80211_commands {
  *     thus it must not specify the number of iterations, only the interval
  *     between scans. The scan plans are executed sequentially.
  *     Each scan plan is a nested attribute of &enum nl80211_sched_scan_plan.
+ * @NL80211_ATTR_PBSS: flag attribute. If set it means operate
+ *     in a PBSS. Specified in %NL80211_CMD_CONNECT to request
+ *     connecting to a PCP, and in %NL80211_CMD_START_AP to start
+ *     a PCP instead of AP. Relevant for DMG networks only.
  *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
@@ -2164,6 +2170,8 @@ enum nl80211_attrs {
        NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS,
        NL80211_ATTR_SCHED_SCAN_PLANS,
 
+       NL80211_ATTR_PBSS,
+
        /* add attributes here, update the policy in nl80211.c */
 
        __NL80211_ATTR_AFTER_LAST,
@@ -4396,12 +4404,18 @@ enum nl80211_feature_flags {
 /**
  * enum nl80211_ext_feature_index - bit index of extended features.
  * @NL80211_EXT_FEATURE_VHT_IBSS: This driver supports IBSS with VHT datarates.
+ * @NL80211_EXT_FEATURE_RRM: This driver supports RRM. When featured, user can
+ *     can request to use RRM (see %NL80211_ATTR_USE_RRM) with
+ *     %NL80211_CMD_ASSOCIATE and %NL80211_CMD_CONNECT requests, which will set
+ *     the ASSOC_REQ_USE_RRM flag in the association request even if
+ *     NL80211_FEATURE_QUIET is not advertized.
  *
  * @NUM_NL80211_EXT_FEATURES: number of extended features.
  * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
  */
 enum nl80211_ext_feature_index {
        NL80211_EXT_FEATURE_VHT_IBSS,
+       NL80211_EXT_FEATURE_RRM,
 
        /* add new features before the definition below */
        NUM_NL80211_EXT_FEATURES,
index 058757f7a7339b104f9f44ebd77569cf20f35ef6..2e00dcebebd0700ac835d0d98221ef1cb4717974 100644 (file)
@@ -59,6 +59,8 @@ enum rfkill_type {
  * @RFKILL_OP_DEL: a device was removed
  * @RFKILL_OP_CHANGE: a device's state changed -- userspace changes one device
  * @RFKILL_OP_CHANGE_ALL: userspace changes all devices (of a type, or all)
+ *     into a state, also updating the default state used for devices that
+ *     are hot-plugged later.
  */
 enum rfkill_operation {
        RFKILL_OP_ADD = 0,
index 235c7a2c0d2004f1121b7d98f4140683ab45ef53..5481b49e8c3f2a1e732fbe751e97b2d7b7d0bc0a 100644 (file)
@@ -940,95 +940,24 @@ menuconfig CGROUPS
 
 if CGROUPS
 
-config CGROUP_DEBUG
-       bool "Example debug cgroup subsystem"
-       default n
-       help
-         This option enables a simple cgroup subsystem that
-         exports useful debugging information about the cgroups
-         framework.
-
-         Say N if unsure.
-
-config CGROUP_FREEZER
-       bool "Freezer cgroup subsystem"
-       help
-         Provides a way to freeze and unfreeze all tasks in a
-         cgroup.
-
-config CGROUP_PIDS
-       bool "PIDs cgroup subsystem"
-       help
-         Provides enforcement of process number limits in the scope of a
-         cgroup. Any attempt to fork more processes than is allowed in the
-         cgroup will fail. PIDs are fundamentally a global resource because it
-         is fairly trivial to reach PID exhaustion before you reach even a
-         conservative kmemcg limit. As a result, it is possible to grind a
-         system to halt without being limited by other cgroup policies. The
-         PIDs cgroup subsystem is designed to stop this from happening.
-
-         It should be noted that organisational operations (such as attaching
-         to a cgroup hierarchy will *not* be blocked by the PIDs subsystem),
-         since the PIDs limit only affects a process's ability to fork, not to
-         attach to a cgroup.
-
-config CGROUP_DEVICE
-       bool "Device controller for cgroups"
-       help
-         Provides a cgroup implementing whitelists for devices which
-         a process in the cgroup can mknod or open.
-
-config CPUSETS
-       bool "Cpuset support"
-       help
-         This option will let you create and manage CPUSETs which
-         allow dynamically partitioning a system into sets of CPUs and
-         Memory Nodes and assigning tasks to run only within those sets.
-         This is primarily useful on large SMP or NUMA systems.
-
-         Say N if unsure.
-
-config PROC_PID_CPUSET
-       bool "Include legacy /proc/<pid>/cpuset file"
-       depends on CPUSETS
-       default y
-
-config CGROUP_CPUACCT
-       bool "Simple CPU accounting cgroup subsystem"
-       help
-         Provides a simple Resource Controller for monitoring the
-         total CPU consumed by the tasks in a cgroup.
-
 config PAGE_COUNTER
        bool
 
 config MEMCG
-       bool "Memory Resource Controller for Control Groups"
+       bool "Memory controller"
        select PAGE_COUNTER
        select EVENTFD
        help
-         Provides a memory resource controller that manages both anonymous
-         memory and page cache. (See Documentation/cgroups/memory.txt)
+         Provides control over the memory footprint of tasks in a cgroup.
 
 config MEMCG_SWAP
-       bool "Memory Resource Controller Swap Extension"
+       bool "Swap controller"
        depends on MEMCG && SWAP
        help
-         Add swap management feature to memory resource controller. When you
-         enable this, you can limit mem+swap usage per cgroup. In other words,
-         when you disable this, memory resource controller has no cares to
-         usage of swap...a process can exhaust all of the swap. This extension
-         is useful when you want to avoid exhaustion swap but this itself
-         adds more overheads and consumes memory for remembering information.
-         Especially if you use 32bit system or small memory system, please
-         be careful about enabling this. When memory resource controller
-         is disabled by boot option, this will be automatically disabled and
-         there will be no overhead from this. Even when you set this config=y,
-         if boot option "swapaccount=0" is set, swap will not be accounted.
-         Now, memory usage of swap_cgroup is 2 bytes per entry. If swap page
-         size is 4096bytes, 512k per 1Gbytes of swap.
+         Provides control over the swap space consumed by tasks in a cgroup.
+
 config MEMCG_SWAP_ENABLED
-       bool "Memory Resource Controller Swap Extension enabled by default"
+       bool "Swap controller enabled by default"
        depends on MEMCG_SWAP
        default y
        help
@@ -1052,34 +981,43 @@ config MEMCG_KMEM
          the kmem extension can use it to guarantee that no group of processes
          will ever exhaust kernel resources alone.
 
-config CGROUP_HUGETLB
-       bool "HugeTLB Resource Controller for Control Groups"
-       depends on HUGETLB_PAGE
-       select PAGE_COUNTER
+config BLK_CGROUP
+       bool "IO controller"
+       depends on BLOCK
        default n
-       help
-         Provides a cgroup Resource Controller for HugeTLB pages.
-         When you enable this, you can put a per cgroup limit on HugeTLB usage.
-         The limit is enforced during page fault. Since HugeTLB doesn't
-         support page reclaim, enforcing the limit at page fault time implies
-         that, the application will get SIGBUS signal if it tries to access
-         HugeTLB pages beyond its limit. This requires the application to know
-         beforehand how much HugeTLB pages it would require for its use. The
-         control group is tracked in the third page lru pointer. This means
-         that we cannot use the controller with huge page less than 3 pages.
+       ---help---
+       Generic block IO controller cgroup interface. This is the common
+       cgroup interface which should be used by various IO controlling
+       policies.
 
-config CGROUP_PERF
-       bool "Enable perf_event per-cpu per-container group (cgroup) monitoring"
-       depends on PERF_EVENTS && CGROUPS
-       help
-         This option extends the per-cpu mode to restrict monitoring to
-         threads which belong to the cgroup specified and run on the
-         designated cpu.
+       Currently, CFQ IO scheduler uses it to recognize task groups and
+       control disk bandwidth allocation (proportional time slice allocation)
+       to such task groups. It is also used by bio throttling logic in
+       block layer to implement upper limit in IO rates on a device.
 
-         Say N if unsure.
+       This option only enables generic Block IO controller infrastructure.
+       One needs to also enable actual IO controlling logic/policy. For
+       enabling proportional weight division of disk bandwidth in CFQ, set
+       CONFIG_CFQ_GROUP_IOSCHED=y; for enabling throttling policy, set
+       CONFIG_BLK_DEV_THROTTLING=y.
+
+       See Documentation/cgroups/blkio-controller.txt for more information.
+
+config DEBUG_BLK_CGROUP
+       bool "IO controller debugging"
+       depends on BLK_CGROUP
+       default n
+       ---help---
+       Enable some debugging help. Currently it exports additional stat
+       files in a cgroup which can be useful for debugging.
+
+config CGROUP_WRITEBACK
+       bool
+       depends on MEMCG && BLK_CGROUP
+       default y
 
 menuconfig CGROUP_SCHED
-       bool "Group CPU scheduler"
+       bool "CPU controller"
        default n
        help
          This feature lets CPU scheduler recognize task groups and control CPU
@@ -1116,40 +1054,89 @@ config RT_GROUP_SCHED
 
 endif #CGROUP_SCHED
 
-config BLK_CGROUP
-       bool "Block IO controller"
-       depends on BLOCK
+config CGROUP_PIDS
+       bool "PIDs controller"
+       help
+         Provides enforcement of process number limits in the scope of a
+         cgroup. Any attempt to fork more processes than is allowed in the
+         cgroup will fail. PIDs are fundamentally a global resource because it
+         is fairly trivial to reach PID exhaustion before you reach even a
+         conservative kmemcg limit. As a result, it is possible to grind a
+         system to halt without being limited by other cgroup policies. The
+         PIDs cgroup subsystem is designed to stop this from happening.
+
+         It should be noted that organisational operations (such as attaching
+         to a cgroup hierarchy will *not* be blocked by the PIDs subsystem),
+         since the PIDs limit only affects a process's ability to fork, not to
+         attach to a cgroup.
+
+config CGROUP_FREEZER
+       bool "Freezer controller"
+       help
+         Provides a way to freeze and unfreeze all tasks in a
+         cgroup.
+
+config CGROUP_HUGETLB
+       bool "HugeTLB controller"
+       depends on HUGETLB_PAGE
+       select PAGE_COUNTER
        default n
-       ---help---
-       Generic block IO controller cgroup interface. This is the common
-       cgroup interface which should be used by various IO controlling
-       policies.
+       help
+         Provides a cgroup controller for HugeTLB pages.
+         When you enable this, you can put a per cgroup limit on HugeTLB usage.
+         The limit is enforced during page fault. Since HugeTLB doesn't
+         support page reclaim, enforcing the limit at page fault time implies
+         that, the application will get SIGBUS signal if it tries to access
+         HugeTLB pages beyond its limit. This requires the application to know
+         beforehand how much HugeTLB pages it would require for its use. The
+         control group is tracked in the third page lru pointer. This means
+         that we cannot use the controller with huge page less than 3 pages.
 
-       Currently, CFQ IO scheduler uses it to recognize task groups and
-       control disk bandwidth allocation (proportional time slice allocation)
-       to such task groups. It is also used by bio throttling logic in
-       block layer to implement upper limit in IO rates on a device.
+config CPUSETS
+       bool "Cpuset controller"
+       help
+         This option will let you create and manage CPUSETs which
+         allow dynamically partitioning a system into sets of CPUs and
+         Memory Nodes and assigning tasks to run only within those sets.
+         This is primarily useful on large SMP or NUMA systems.
 
-       This option only enables generic Block IO controller infrastructure.
-       One needs to also enable actual IO controlling logic/policy. For
-       enabling proportional weight division of disk bandwidth in CFQ, set
-       CONFIG_CFQ_GROUP_IOSCHED=y; for enabling throttling policy, set
-       CONFIG_BLK_DEV_THROTTLING=y.
+         Say N if unsure.
 
-       See Documentation/cgroups/blkio-controller.txt for more information.
+config PROC_PID_CPUSET
+       bool "Include legacy /proc/<pid>/cpuset file"
+       depends on CPUSETS
+       default y
 
-config DEBUG_BLK_CGROUP
-       bool "Enable Block IO controller debugging"
-       depends on BLK_CGROUP
+config CGROUP_DEVICE
+       bool "Device controller"
+       help
+         Provides a cgroup controller implementing whitelists for
+         devices which a process in the cgroup can mknod or open.
+
+config CGROUP_CPUACCT
+       bool "Simple CPU accounting controller"
+       help
+         Provides a simple controller for monitoring the
+         total CPU consumed by the tasks in a cgroup.
+
+config CGROUP_PERF
+       bool "Perf controller"
+       depends on PERF_EVENTS
+       help
+         This option extends the perf per-cpu mode to restrict monitoring
+         to threads which belong to the cgroup specified and run on the
+         designated cpu.
+
+         Say N if unsure.
+
+config CGROUP_DEBUG
+       bool "Example controller"
        default n
-       ---help---
-       Enable some debugging help. Currently it exports additional stat
-       files in a cgroup which can be useful for debugging.
+       help
+         This option enables a simple controller that exports
+         debugging information about the cgroups framework.
 
-config CGROUP_WRITEBACK
-       bool
-       depends on MEMCG && BLK_CGROUP
-       default y
+         Say N.
 
 endif # CGROUPS
 
index fe95970b1f7995fc819bad7d81d90721905a5512..c03a640ef6da265db01b93c2970ab6b2da7abd67 100644 (file)
@@ -211,6 +211,7 @@ static unsigned long have_free_callback __read_mostly;
 /* Ditto for the can_fork callback. */
 static unsigned long have_canfork_callback __read_mostly;
 
+static struct file_system_type cgroup2_fs_type;
 static struct cftype cgroup_dfl_base_files[];
 static struct cftype cgroup_legacy_base_files[];
 
@@ -1623,10 +1624,6 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts)
                        all_ss = true;
                        continue;
                }
-               if (!strcmp(token, "__DEVEL__sane_behavior")) {
-                       opts->flags |= CGRP_ROOT_SANE_BEHAVIOR;
-                       continue;
-               }
                if (!strcmp(token, "noprefix")) {
                        opts->flags |= CGRP_ROOT_NOPREFIX;
                        continue;
@@ -1693,15 +1690,6 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts)
                        return -ENOENT;
        }
 
-       if (opts->flags & CGRP_ROOT_SANE_BEHAVIOR) {
-               pr_warn("sane_behavior: this is still under development and its behaviors will change, proceed at your own risk\n");
-               if (nr_opts != 1) {
-                       pr_err("sane_behavior: no other mount options allowed\n");
-                       return -EINVAL;
-               }
-               return 0;
-       }
-
        /*
         * If the 'all' option was specified select all the subsystems,
         * otherwise if 'none', 'name=' and a subsystem name options were
@@ -1981,6 +1969,7 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
                         int flags, const char *unused_dev_name,
                         void *data)
 {
+       bool is_v2 = fs_type == &cgroup2_fs_type;
        struct super_block *pinned_sb = NULL;
        struct cgroup_subsys *ss;
        struct cgroup_root *root;
@@ -1997,6 +1986,17 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
        if (!use_task_css_set_links)
                cgroup_enable_task_cg_lists();
 
+       if (is_v2) {
+               if (data) {
+                       pr_err("cgroup2: unknown option \"%s\"\n", (char *)data);
+                       return ERR_PTR(-EINVAL);
+               }
+               cgrp_dfl_root_visible = true;
+               root = &cgrp_dfl_root;
+               cgroup_get(&root->cgrp);
+               goto out_mount;
+       }
+
        mutex_lock(&cgroup_mutex);
 
        /* First find the desired set of subsystems */
@@ -2004,15 +2004,6 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
        if (ret)
                goto out_unlock;
 
-       /* look for a matching existing root */
-       if (opts.flags & CGRP_ROOT_SANE_BEHAVIOR) {
-               cgrp_dfl_root_visible = true;
-               root = &cgrp_dfl_root;
-               cgroup_get(&root->cgrp);
-               ret = 0;
-               goto out_unlock;
-       }
-
        /*
         * Destruction of cgroup root is asynchronous, so subsystems may
         * still be dying after the previous unmount.  Let's drain the
@@ -2123,9 +2114,10 @@ out_free:
 
        if (ret)
                return ERR_PTR(ret);
-
+out_mount:
        dentry = kernfs_mount(fs_type, flags, root->kf_root,
-                               CGROUP_SUPER_MAGIC, &new_sb);
+                             is_v2 ? CGROUP2_SUPER_MAGIC : CGROUP_SUPER_MAGIC,
+                             &new_sb);
        if (IS_ERR(dentry) || !new_sb)
                cgroup_put(&root->cgrp);
 
@@ -2168,6 +2160,12 @@ static struct file_system_type cgroup_fs_type = {
        .kill_sb = cgroup_kill_sb,
 };
 
+static struct file_system_type cgroup2_fs_type = {
+       .name = "cgroup2",
+       .mount = cgroup_mount,
+       .kill_sb = cgroup_kill_sb,
+};
+
 /**
  * task_cgroup_path - cgroup path of a task in the first cgroup hierarchy
  * @task: target task
@@ -4039,7 +4037,7 @@ int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from)
                goto out_err;
 
        /*
-        * Migrate tasks one-by-one until @form is empty.  This fails iff
+        * Migrate tasks one-by-one until @from is empty.  This fails iff
         * ->can_attach() fails.
         */
        do {
@@ -5171,7 +5169,7 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss, bool early)
 {
        struct cgroup_subsys_state *css;
 
-       printk(KERN_INFO "Initializing cgroup subsys %s\n", ss->name);
+       pr_debug("Initializing cgroup subsys %s\n", ss->name);
 
        mutex_lock(&cgroup_mutex);
 
@@ -5329,6 +5327,7 @@ int __init cgroup_init(void)
 
        WARN_ON(sysfs_create_mount_point(fs_kobj, "cgroup"));
        WARN_ON(register_filesystem(&cgroup_fs_type));
+       WARN_ON(register_filesystem(&cgroup2_fs_type));
        WARN_ON(!proc_create("cgroups", 0, NULL, &proc_cgroupstats_operations));
 
        return 0;
@@ -5472,19 +5471,6 @@ static const struct file_operations proc_cgroupstats_operations = {
        .release = single_release,
 };
 
-static void **subsys_canfork_priv_p(void *ss_priv[CGROUP_CANFORK_COUNT], int i)
-{
-       if (CGROUP_CANFORK_START <= i && i < CGROUP_CANFORK_END)
-               return &ss_priv[i - CGROUP_CANFORK_START];
-       return NULL;
-}
-
-static void *subsys_canfork_priv(void *ss_priv[CGROUP_CANFORK_COUNT], int i)
-{
-       void **private = subsys_canfork_priv_p(ss_priv, i);
-       return private ? *private : NULL;
-}
-
 /**
  * cgroup_fork - initialize cgroup related fields during copy_process()
  * @child: pointer to task_struct of forking parent process.
@@ -5507,14 +5493,13 @@ void cgroup_fork(struct task_struct *child)
  * returns an error, the fork aborts with that error code. This allows for
  * a cgroup subsystem to conditionally allow or deny new forks.
  */
-int cgroup_can_fork(struct task_struct *child,
-                   void *ss_priv[CGROUP_CANFORK_COUNT])
+int cgroup_can_fork(struct task_struct *child)
 {
        struct cgroup_subsys *ss;
        int i, j, ret;
 
        for_each_subsys_which(ss, i, &have_canfork_callback) {
-               ret = ss->can_fork(child, subsys_canfork_priv_p(ss_priv, i));
+               ret = ss->can_fork(child);
                if (ret)
                        goto out_revert;
        }
@@ -5526,7 +5511,7 @@ out_revert:
                if (j >= i)
                        break;
                if (ss->cancel_fork)
-                       ss->cancel_fork(child, subsys_canfork_priv(ss_priv, j));
+                       ss->cancel_fork(child);
        }
 
        return ret;
@@ -5539,15 +5524,14 @@ out_revert:
  * This calls the cancel_fork() callbacks if a fork failed *after*
  * cgroup_can_fork() succeded.
  */
-void cgroup_cancel_fork(struct task_struct *child,
-                       void *ss_priv[CGROUP_CANFORK_COUNT])
+void cgroup_cancel_fork(struct task_struct *child)
 {
        struct cgroup_subsys *ss;
        int i;
 
        for_each_subsys(ss, i)
                if (ss->cancel_fork)
-                       ss->cancel_fork(child, subsys_canfork_priv(ss_priv, i));
+                       ss->cancel_fork(child);
 }
 
 /**
@@ -5560,8 +5544,7 @@ void cgroup_cancel_fork(struct task_struct *child,
  * cgroup_task_iter_start() - to guarantee that the new task ends up on its
  * list.
  */
-void cgroup_post_fork(struct task_struct *child,
-                     void *old_ss_priv[CGROUP_CANFORK_COUNT])
+void cgroup_post_fork(struct task_struct *child)
 {
        struct cgroup_subsys *ss;
        int i;
@@ -5605,7 +5588,7 @@ void cgroup_post_fork(struct task_struct *child,
         * and addition to css_set.
         */
        for_each_subsys_which(ss, i, &have_fork_callback)
-               ss->fork(child, subsys_canfork_priv(old_ss_priv, i));
+               ss->fork(child);
 }
 
 /**
index 2d3df82c54f2dd84484e0b4d739551cb69861e4e..1b72d56edce5e2d9253c2c03f203e81aa76bd16c 100644 (file)
@@ -200,7 +200,7 @@ static void freezer_attach(struct cgroup_taskset *tset)
  * to do anything as freezer_attach() will put @task into the appropriate
  * state.
  */
-static void freezer_fork(struct task_struct *task, void *private)
+static void freezer_fork(struct task_struct *task)
 {
        struct freezer *freezer;
 
index b50d5a167fda7d2ae6902efd55e551efed780007..303097b374294cf4eb59d4d1a28e4a4a69e4d480 100644 (file)
@@ -134,7 +134,7 @@ static void pids_charge(struct pids_cgroup *pids, int num)
  *
  * This function follows the set limit. It will fail if the charge would cause
  * the new value to exceed the hierarchical limit. Returns 0 if the charge
- * succeded, otherwise -EAGAIN.
+ * succeeded, otherwise -EAGAIN.
  */
 static int pids_try_charge(struct pids_cgroup *pids, int num)
 {
@@ -209,7 +209,7 @@ static void pids_cancel_attach(struct cgroup_taskset *tset)
  * task_css_check(true) in pids_can_fork() and pids_cancel_fork() relies
  * on threadgroup_change_begin() held by the copy_process().
  */
-static int pids_can_fork(struct task_struct *task, void **priv_p)
+static int pids_can_fork(struct task_struct *task)
 {
        struct cgroup_subsys_state *css;
        struct pids_cgroup *pids;
@@ -219,7 +219,7 @@ static int pids_can_fork(struct task_struct *task, void **priv_p)
        return pids_try_charge(pids, 1);
 }
 
-static void pids_cancel_fork(struct task_struct *task, void *priv)
+static void pids_cancel_fork(struct task_struct *task)
 {
        struct cgroup_subsys_state *css;
        struct pids_cgroup *pids;
index 02a8ea5c99632907b2ae887015c59bd4ad35da9d..3e945fcd81796f954a7e1c81ae95e78bd1a91dba 100644 (file)
@@ -51,6 +51,7 @@
 #include <linux/stat.h>
 #include <linux/string.h>
 #include <linux/time.h>
+#include <linux/time64.h>
 #include <linux/backing-dev.h>
 #include <linux/sort.h>
 
@@ -68,7 +69,7 @@ struct static_key cpusets_enabled_key __read_mostly = STATIC_KEY_INIT_FALSE;
 struct fmeter {
        int cnt;                /* unprocessed events count */
        int val;                /* most recent output value */
-       time_t time;            /* clock (secs) when val computed */
+       time64_t time;          /* clock (secs) when val computed */
        spinlock_t lock;        /* guards read or write of above */
 };
 
@@ -1374,7 +1375,7 @@ out:
  */
 
 #define FM_COEF 933            /* coefficient for half-life of 10 secs */
-#define FM_MAXTICKS ((time_t)99) /* useless computing more ticks than this */
+#define FM_MAXTICKS ((u32)99)   /* useless computing more ticks than this */
 #define FM_MAXCNT 1000000      /* limit cnt to avoid overflow */
 #define FM_SCALE 1000          /* faux fixed point scale */
 
@@ -1390,8 +1391,11 @@ static void fmeter_init(struct fmeter *fmp)
 /* Internal meter update - process cnt events and update value */
 static void fmeter_update(struct fmeter *fmp)
 {
-       time_t now = get_seconds();
-       time_t ticks = now - fmp->time;
+       time64_t now;
+       u32 ticks;
+
+       now = ktime_get_seconds();
+       ticks = now - fmp->time;
 
        if (ticks == 0)
                return;
index 291b08cc817bc8dd84320d03d4cf7b9517902ff9..6774e6b2e96d6faa95f805e7521f98ba61e2e253 100644 (file)
@@ -1250,7 +1250,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 {
        int retval;
        struct task_struct *p;
-       void *cgrp_ss_priv[CGROUP_CANFORK_COUNT] = {};
 
        if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))
                return ERR_PTR(-EINVAL);
@@ -1527,7 +1526,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
         * between here and cgroup_post_fork() if an organisation operation is in
         * progress.
         */
-       retval = cgroup_can_fork(p, cgrp_ss_priv);
+       retval = cgroup_can_fork(p);
        if (retval)
                goto bad_fork_free_pid;
 
@@ -1609,7 +1608,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
        write_unlock_irq(&tasklist_lock);
 
        proc_fork_connector(p);
-       cgroup_post_fork(p, cgrp_ss_priv);
+       cgroup_post_fork(p);
        threadgroup_change_end(current);
        perf_event_fork(p);
 
@@ -1619,7 +1618,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
        return p;
 
 bad_fork_cancel_cgroup:
-       cgroup_cancel_fork(p, cgrp_ss_priv);
+       cgroup_cancel_fork(p);
 bad_fork_free_pid:
        if (pid != &init_struct_pid)
                free_pid(pid);
index b2dd4d999900a26edd9cd26fb952b84b98ee411f..27946975eff004f210d563e73218f1fe6d0b9a9e 100644 (file)
@@ -280,13 +280,7 @@ static ssize_t pm_wakeup_irq_show(struct kobject *kobj,
        return pm_wakeup_irq ? sprintf(buf, "%u\n", pm_wakeup_irq) : -ENODATA;
 }
 
-static ssize_t pm_wakeup_irq_store(struct kobject *kobj,
-                                       struct kobj_attribute *attr,
-                                       const char *buf, size_t n)
-{
-       return -EINVAL;
-}
-power_attr(pm_wakeup_irq);
+power_attr_ro(pm_wakeup_irq);
 
 #else /* !CONFIG_PM_SLEEP_DEBUG */
 static inline void pm_print_times_init(void) {}
@@ -564,14 +558,7 @@ static ssize_t pm_trace_dev_match_show(struct kobject *kobj,
        return show_trace_dev_match(buf, PAGE_SIZE);
 }
 
-static ssize_t
-pm_trace_dev_match_store(struct kobject *kobj, struct kobj_attribute *attr,
-                        const char *buf, size_t n)
-{
-       return -EINVAL;
-}
-
-power_attr(pm_trace_dev_match);
+power_attr_ro(pm_trace_dev_match);
 
 #endif /* CONFIG_PM_TRACE */
 
index caadb566e82bb51a5348d6ba67a73bda8c99f37d..efe1b3b17c88d0eb793fa84ceec00e5b31604af4 100644 (file)
@@ -77,6 +77,15 @@ static struct kobj_attribute _name##_attr = {        \
        .store  = _name##_store,                \
 }
 
+#define power_attr_ro(_name) \
+static struct kobj_attribute _name##_attr = {  \
+       .attr   = {                             \
+               .name = __stringify(_name),     \
+               .mode = S_IRUGO,                \
+       },                                      \
+       .show   = _name##_show,                 \
+}
+
 /* Preferred image size in bytes (default 500 MB) */
 extern unsigned long image_size;
 /* Size of memory reserved for drivers (default SPARE_PAGES x PAGE_SIZE) */
index 77d97a6fc71515ce83f80e62edfdf726a09a8fc6..44253adb3c36dc28fb84cf9fdda4609f59dc388c 100644 (file)
@@ -8342,7 +8342,7 @@ static void cpu_cgroup_css_offline(struct cgroup_subsys_state *css)
        sched_offline_group(tg);
 }
 
-static void cpu_cgroup_fork(struct task_struct *task, void *private)
+static void cpu_cgroup_fork(struct task_struct *task)
 {
        sched_move_task(task);
 }
index 4228fd3682c3d45894f0f3bbc13a715331a24e7c..45dd798bcd37e7bd529e61932e51a30366590626 100644 (file)
@@ -316,7 +316,7 @@ static bool kprobe_prog_is_valid_access(int off, int size, enum bpf_access_type
        return true;
 }
 
-static struct bpf_verifier_ops kprobe_prog_ops = {
+static const struct bpf_verifier_ops kprobe_prog_ops = {
        .get_func_proto  = kprobe_prog_func_proto,
        .is_valid_access = kprobe_prog_is_valid_access,
 };
index 3f743b147247034e6a794f7cf47176a2c6a44ece..eca592f977b260689dc48911f867375b20ad5c8b 100644 (file)
@@ -62,8 +62,6 @@
 #define FTRACE_HASH_DEFAULT_BITS 10
 #define FTRACE_HASH_MAX_BITS 12
 
-#define FL_GLOBAL_CONTROL_MASK (FTRACE_OPS_FL_CONTROL)
-
 #ifdef CONFIG_DYNAMIC_FTRACE
 #define INIT_OPS_HASH(opsname) \
        .func_hash              = &opsname.local_hash,                  \
@@ -113,14 +111,9 @@ static int ftrace_disabled __read_mostly;
 
 static DEFINE_MUTEX(ftrace_lock);
 
-static struct ftrace_ops *ftrace_control_list __read_mostly = &ftrace_list_end;
 static struct ftrace_ops *ftrace_ops_list __read_mostly = &ftrace_list_end;
 ftrace_func_t ftrace_trace_function __read_mostly = ftrace_stub;
 static struct ftrace_ops global_ops;
-static struct ftrace_ops control_ops;
-
-static void ftrace_ops_recurs_func(unsigned long ip, unsigned long parent_ip,
-                                  struct ftrace_ops *op, struct pt_regs *regs);
 
 #if ARCH_SUPPORTS_FTRACE_OPS
 static void ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,
@@ -203,7 +196,7 @@ void clear_ftrace_function(void)
        ftrace_trace_function = ftrace_stub;
 }
 
-static void control_ops_disable_all(struct ftrace_ops *ops)
+static void per_cpu_ops_disable_all(struct ftrace_ops *ops)
 {
        int cpu;
 
@@ -211,16 +204,19 @@ static void control_ops_disable_all(struct ftrace_ops *ops)
                *per_cpu_ptr(ops->disabled, cpu) = 1;
 }
 
-static int control_ops_alloc(struct ftrace_ops *ops)
+static int per_cpu_ops_alloc(struct ftrace_ops *ops)
 {
        int __percpu *disabled;
 
+       if (WARN_ON_ONCE(!(ops->flags & FTRACE_OPS_FL_PER_CPU)))
+               return -EINVAL;
+
        disabled = alloc_percpu(int);
        if (!disabled)
                return -ENOMEM;
 
        ops->disabled = disabled;
-       control_ops_disable_all(ops);
+       per_cpu_ops_disable_all(ops);
        return 0;
 }
 
@@ -256,10 +252,11 @@ static inline void update_function_graph_func(void) { }
 static ftrace_func_t ftrace_ops_get_list_func(struct ftrace_ops *ops)
 {
        /*
-        * If this is a dynamic ops or we force list func,
+        * If this is a dynamic, RCU, or per CPU ops, or we force list func,
         * then it needs to call the list anyway.
         */
-       if (ops->flags & FTRACE_OPS_FL_DYNAMIC || FTRACE_FORCE_LIST_FUNC)
+       if (ops->flags & (FTRACE_OPS_FL_DYNAMIC | FTRACE_OPS_FL_PER_CPU |
+                         FTRACE_OPS_FL_RCU) || FTRACE_FORCE_LIST_FUNC)
                return ftrace_ops_list_func;
 
        return ftrace_ops_get_func(ops);
@@ -383,26 +380,6 @@ static int remove_ftrace_ops(struct ftrace_ops **list, struct ftrace_ops *ops)
        return 0;
 }
 
-static void add_ftrace_list_ops(struct ftrace_ops **list,
-                               struct ftrace_ops *main_ops,
-                               struct ftrace_ops *ops)
-{
-       int first = *list == &ftrace_list_end;
-       add_ftrace_ops(list, ops);
-       if (first)
-               add_ftrace_ops(&ftrace_ops_list, main_ops);
-}
-
-static int remove_ftrace_list_ops(struct ftrace_ops **list,
-                                 struct ftrace_ops *main_ops,
-                                 struct ftrace_ops *ops)
-{
-       int ret = remove_ftrace_ops(list, ops);
-       if (!ret && *list == &ftrace_list_end)
-               ret = remove_ftrace_ops(&ftrace_ops_list, main_ops);
-       return ret;
-}
-
 static void ftrace_update_trampoline(struct ftrace_ops *ops);
 
 static int __register_ftrace_function(struct ftrace_ops *ops)
@@ -430,14 +407,12 @@ static int __register_ftrace_function(struct ftrace_ops *ops)
        if (!core_kernel_data((unsigned long)ops))
                ops->flags |= FTRACE_OPS_FL_DYNAMIC;
 
-       if (ops->flags & FTRACE_OPS_FL_CONTROL) {
-               if (control_ops_alloc(ops))
+       if (ops->flags & FTRACE_OPS_FL_PER_CPU) {
+               if (per_cpu_ops_alloc(ops))
                        return -ENOMEM;
-               add_ftrace_list_ops(&ftrace_control_list, &control_ops, ops);
-               /* The control_ops needs the trampoline update */
-               ops = &control_ops;
-       } else
-               add_ftrace_ops(&ftrace_ops_list, ops);
+       }
+
+       add_ftrace_ops(&ftrace_ops_list, ops);
 
        /* Always save the function, and reset at unregistering */
        ops->saved_func = ops->func;
@@ -460,11 +435,7 @@ static int __unregister_ftrace_function(struct ftrace_ops *ops)
        if (WARN_ON(!(ops->flags & FTRACE_OPS_FL_ENABLED)))
                return -EBUSY;
 
-       if (ops->flags & FTRACE_OPS_FL_CONTROL) {
-               ret = remove_ftrace_list_ops(&ftrace_control_list,
-                                            &control_ops, ops);
-       } else
-               ret = remove_ftrace_ops(&ftrace_ops_list, ops);
+       ret = remove_ftrace_ops(&ftrace_ops_list, ops);
 
        if (ret < 0)
                return ret;
@@ -1687,6 +1658,9 @@ static void __ftrace_hash_rec_update(struct ftrace_ops *ops,
                int in_hash = 0;
                int match = 0;
 
+               if (rec->flags & FTRACE_FL_DISABLED)
+                       continue;
+
                if (all) {
                        /*
                         * Only the filter_hash affects all records.
@@ -1940,7 +1914,7 @@ static int ftrace_hash_ipmodify_update(struct ftrace_ops *ops,
        return __ftrace_hash_update_ipmodify(ops, old_hash, new_hash);
 }
 
-static void print_ip_ins(const char *fmt, unsigned char *p)
+static void print_ip_ins(const char *fmt, const unsigned char *p)
 {
        int i;
 
@@ -1952,6 +1926,31 @@ static void print_ip_ins(const char *fmt, unsigned char *p)
 
 static struct ftrace_ops *
 ftrace_find_tramp_ops_any(struct dyn_ftrace *rec);
+static struct ftrace_ops *
+ftrace_find_tramp_ops_next(struct dyn_ftrace *rec, struct ftrace_ops *ops);
+
+enum ftrace_bug_type ftrace_bug_type;
+const void *ftrace_expected;
+
+static void print_bug_type(void)
+{
+       switch (ftrace_bug_type) {
+       case FTRACE_BUG_UNKNOWN:
+               break;
+       case FTRACE_BUG_INIT:
+               pr_info("Initializing ftrace call sites\n");
+               break;
+       case FTRACE_BUG_NOP:
+               pr_info("Setting ftrace call site to NOP\n");
+               break;
+       case FTRACE_BUG_CALL:
+               pr_info("Setting ftrace call site to call ftrace function\n");
+               break;
+       case FTRACE_BUG_UPDATE:
+               pr_info("Updating ftrace call site to call a different ftrace function\n");
+               break;
+       }
+}
 
 /**
  * ftrace_bug - report and shutdown function tracer
@@ -1979,8 +1978,12 @@ void ftrace_bug(int failed, struct dyn_ftrace *rec)
                FTRACE_WARN_ON_ONCE(1);
                pr_info("ftrace failed to modify ");
                print_ip_sym(ip);
-               print_ip_ins(" actual: ", (unsigned char *)ip);
+               print_ip_ins(" actual:   ", (unsigned char *)ip);
                pr_cont("\n");
+               if (ftrace_expected) {
+                       print_ip_ins(" expected: ", ftrace_expected);
+                       pr_cont("\n");
+               }
                break;
        case -EPERM:
                FTRACE_WARN_ON_ONCE(1);
@@ -1992,6 +1995,7 @@ void ftrace_bug(int failed, struct dyn_ftrace *rec)
                pr_info("ftrace faulted on unknown error ");
                print_ip_sym(ip);
        }
+       print_bug_type();
        if (rec) {
                struct ftrace_ops *ops = NULL;
 
@@ -2000,15 +2004,19 @@ void ftrace_bug(int failed, struct dyn_ftrace *rec)
                        rec->flags & FTRACE_FL_REGS ? " R" : "  ");
                if (rec->flags & FTRACE_FL_TRAMP_EN) {
                        ops = ftrace_find_tramp_ops_any(rec);
-                       if (ops)
-                               pr_cont("\ttramp: %pS",
-                                       (void *)ops->trampoline);
-                       else
+                       if (ops) {
+                               do {
+                                       pr_cont("\ttramp: %pS (%pS)",
+                                               (void *)ops->trampoline,
+                                               (void *)ops->func);
+                                       ops = ftrace_find_tramp_ops_next(rec, ops);
+                               } while (ops);
+                       } else
                                pr_cont("\ttramp: ERROR!");
 
                }
                ip = ftrace_get_addr_curr(rec);
-               pr_cont(" expected tramp: %lx\n", ip);
+               pr_cont("\n expected tramp: %lx\n", ip);
        }
 }
 
@@ -2016,6 +2024,11 @@ static int ftrace_check_record(struct dyn_ftrace *rec, int enable, int update)
 {
        unsigned long flag = 0UL;
 
+       ftrace_bug_type = FTRACE_BUG_UNKNOWN;
+
+       if (rec->flags & FTRACE_FL_DISABLED)
+               return FTRACE_UPDATE_IGNORE;
+
        /*
         * If we are updating calls:
         *
@@ -2077,9 +2090,12 @@ static int ftrace_check_record(struct dyn_ftrace *rec, int enable, int update)
                 *   from the save regs, to a non-save regs function or
                 *   vice versa, or from a trampoline call.
                 */
-               if (flag & FTRACE_FL_ENABLED)
+               if (flag & FTRACE_FL_ENABLED) {
+                       ftrace_bug_type = FTRACE_BUG_CALL;
                        return FTRACE_UPDATE_MAKE_CALL;
+               }
 
+               ftrace_bug_type = FTRACE_BUG_UPDATE;
                return FTRACE_UPDATE_MODIFY_CALL;
        }
 
@@ -2096,6 +2112,7 @@ static int ftrace_check_record(struct dyn_ftrace *rec, int enable, int update)
                                        FTRACE_FL_REGS_EN);
        }
 
+       ftrace_bug_type = FTRACE_BUG_NOP;
        return FTRACE_UPDATE_MAKE_NOP;
 }
 
@@ -2144,6 +2161,24 @@ ftrace_find_tramp_ops_any(struct dyn_ftrace *rec)
        return NULL;
 }
 
+static struct ftrace_ops *
+ftrace_find_tramp_ops_next(struct dyn_ftrace *rec,
+                          struct ftrace_ops *op)
+{
+       unsigned long ip = rec->ip;
+
+       while_for_each_ftrace_op(op) {
+
+               if (!op->trampoline)
+                       continue;
+
+               if (hash_contains_ip(ip, op->func_hash))
+                       return op;
+       } 
+
+       return NULL;
+}
+
 static struct ftrace_ops *
 ftrace_find_tramp_ops_curr(struct dyn_ftrace *rec)
 {
@@ -2307,17 +2342,22 @@ __ftrace_replace_code(struct dyn_ftrace *rec, int enable)
 
        ret = ftrace_update_record(rec, enable);
 
+       ftrace_bug_type = FTRACE_BUG_UNKNOWN;
+
        switch (ret) {
        case FTRACE_UPDATE_IGNORE:
                return 0;
 
        case FTRACE_UPDATE_MAKE_CALL:
+               ftrace_bug_type = FTRACE_BUG_CALL;
                return ftrace_make_call(rec, ftrace_addr);
 
        case FTRACE_UPDATE_MAKE_NOP:
+               ftrace_bug_type = FTRACE_BUG_NOP;
                return ftrace_make_nop(NULL, rec, ftrace_old_addr);
 
        case FTRACE_UPDATE_MODIFY_CALL:
+               ftrace_bug_type = FTRACE_BUG_UPDATE;
                return ftrace_modify_call(rec, ftrace_old_addr, ftrace_addr);
        }
 
@@ -2425,6 +2465,7 @@ ftrace_code_disable(struct module *mod, struct dyn_ftrace *rec)
 
        ret = ftrace_make_nop(mod, rec, MCOUNT_ADDR);
        if (ret) {
+               ftrace_bug_type = FTRACE_BUG_INIT;
                ftrace_bug(ret, rec);
                return 0;
        }
@@ -2566,7 +2607,7 @@ void __weak arch_ftrace_trampoline_free(struct ftrace_ops *ops)
 {
 }
 
-static void control_ops_free(struct ftrace_ops *ops)
+static void per_cpu_ops_free(struct ftrace_ops *ops)
 {
        free_percpu(ops->disabled);
 }
@@ -2667,13 +2708,13 @@ static int ftrace_shutdown(struct ftrace_ops *ops, int command)
 
        if (!command || !ftrace_enabled) {
                /*
-                * If these are control ops, they still need their
+                * If these are per_cpu ops, they still need their
                 * per_cpu field freed. Since, function tracing is
                 * not currently active, we can just free them
                 * without synchronizing all CPUs.
                 */
-               if (ops->flags & FTRACE_OPS_FL_CONTROL)
-                       control_ops_free(ops);
+               if (ops->flags & FTRACE_OPS_FL_PER_CPU)
+                       per_cpu_ops_free(ops);
                return 0;
        }
 
@@ -2714,7 +2755,7 @@ static int ftrace_shutdown(struct ftrace_ops *ops, int command)
        /*
         * Dynamic ops may be freed, we must make sure that all
         * callers are done before leaving this function.
-        * The same goes for freeing the per_cpu data of the control
+        * The same goes for freeing the per_cpu data of the per_cpu
         * ops.
         *
         * Again, normal synchronize_sched() is not good enough.
@@ -2725,13 +2766,13 @@ static int ftrace_shutdown(struct ftrace_ops *ops, int command)
         * infrastructure to do the synchronization, thus we must do it
         * ourselves.
         */
-       if (ops->flags & (FTRACE_OPS_FL_DYNAMIC | FTRACE_OPS_FL_CONTROL)) {
+       if (ops->flags & (FTRACE_OPS_FL_DYNAMIC | FTRACE_OPS_FL_PER_CPU)) {
                schedule_on_each_cpu(ftrace_sync);
 
                arch_ftrace_trampoline_free(ops);
 
-               if (ops->flags & FTRACE_OPS_FL_CONTROL)
-                       control_ops_free(ops);
+               if (ops->flags & FTRACE_OPS_FL_PER_CPU)
+                       per_cpu_ops_free(ops);
        }
 
        return 0;
@@ -2798,9 +2839,9 @@ ops_references_rec(struct ftrace_ops *ops, struct dyn_ftrace *rec)
        if (!(ops->flags & FTRACE_OPS_FL_ENABLED))
                return 0;
 
-       /* If ops traces all mods, we already accounted for it */
+       /* If ops traces all then it includes this function */
        if (ops_traces_mod(ops))
-               return 0;
+               return 1;
 
        /* The function must be in the filter */
        if (!ftrace_hash_empty(ops->func_hash->filter_hash) &&
@@ -2814,64 +2855,41 @@ ops_references_rec(struct ftrace_ops *ops, struct dyn_ftrace *rec)
        return 1;
 }
 
-static int referenced_filters(struct dyn_ftrace *rec)
-{
-       struct ftrace_ops *ops;
-       int cnt = 0;
-
-       for (ops = ftrace_ops_list; ops != &ftrace_list_end; ops = ops->next) {
-               if (ops_references_rec(ops, rec))
-                   cnt++;
-       }
-
-       return cnt;
-}
-
 static int ftrace_update_code(struct module *mod, struct ftrace_page *new_pgs)
 {
        struct ftrace_page *pg;
        struct dyn_ftrace *p;
        cycle_t start, stop;
        unsigned long update_cnt = 0;
-       unsigned long ref = 0;
-       bool test = false;
+       unsigned long rec_flags = 0;
        int i;
 
+       start = ftrace_now(raw_smp_processor_id());
+
        /*
-        * When adding a module, we need to check if tracers are
-        * currently enabled and if they are set to trace all functions.
-        * If they are, we need to enable the module functions as well
-        * as update the reference counts for those function records.
+        * When a module is loaded, this function is called to convert
+        * the calls to mcount in its text to nops, and also to create
+        * an entry in the ftrace data. Now, if ftrace is activated
+        * after this call, but before the module sets its text to
+        * read-only, the modification of enabling ftrace can fail if
+        * the read-only is done while ftrace is converting the calls.
+        * To prevent this, the module's records are set as disabled
+        * and will be enabled after the call to set the module's text
+        * to read-only.
         */
-       if (mod) {
-               struct ftrace_ops *ops;
-
-               for (ops = ftrace_ops_list;
-                    ops != &ftrace_list_end; ops = ops->next) {
-                       if (ops->flags & FTRACE_OPS_FL_ENABLED) {
-                               if (ops_traces_mod(ops))
-                                       ref++;
-                               else
-                                       test = true;
-                       }
-               }
-       }
-
-       start = ftrace_now(raw_smp_processor_id());
+       if (mod)
+               rec_flags |= FTRACE_FL_DISABLED;
 
        for (pg = new_pgs; pg; pg = pg->next) {
 
                for (i = 0; i < pg->index; i++) {
-                       int cnt = ref;
 
                        /* If something went wrong, bail without enabling anything */
                        if (unlikely(ftrace_disabled))
                                return -1;
 
                        p = &pg->records[i];
-                       if (test)
-                               cnt += referenced_filters(p);
-                       p->flags = cnt;
+                       p->flags = rec_flags;
 
                        /*
                         * Do the initial record conversion from mcount jump
@@ -2881,21 +2899,6 @@ static int ftrace_update_code(struct module *mod, struct ftrace_page *new_pgs)
                                break;
 
                        update_cnt++;
-
-                       /*
-                        * If the tracing is enabled, go ahead and enable the record.
-                        *
-                        * The reason not to enable the record immediatelly is the
-                        * inherent check of ftrace_make_nop/ftrace_make_call for
-                        * correct previous instructions.  Making first the NOP
-                        * conversion puts the module to the correct state, thus
-                        * passing the ftrace_make_call check.
-                        */
-                       if (ftrace_start_up && cnt) {
-                               int failed = __ftrace_replace_code(p, 1);
-                               if (failed)
-                                       ftrace_bug(failed, p);
-                       }
                }
        }
 
@@ -3258,7 +3261,7 @@ static int t_show(struct seq_file *m, void *v)
 
        seq_printf(m, "%ps", (void *)rec->ip);
        if (iter->flags & FTRACE_ITER_ENABLED) {
-               struct ftrace_ops *ops = NULL;
+               struct ftrace_ops *ops;
 
                seq_printf(m, " (%ld)%s%s",
                           ftrace_rec_count(rec),
@@ -3266,14 +3269,19 @@ static int t_show(struct seq_file *m, void *v)
                           rec->flags & FTRACE_FL_IPMODIFY ? " I" : "  ");
                if (rec->flags & FTRACE_FL_TRAMP_EN) {
                        ops = ftrace_find_tramp_ops_any(rec);
-                       if (ops)
-                               seq_printf(m, "\ttramp: %pS",
-                                          (void *)ops->trampoline);
-                       else
+                       if (ops) {
+                               do {
+                                       seq_printf(m, "\ttramp: %pS (%pS)",
+                                                  (void *)ops->trampoline,
+                                                  (void *)ops->func);
+                                       add_trampoline_func(m, ops, rec);
+                                       ops = ftrace_find_tramp_ops_next(rec, ops);
+                               } while (ops);
+                       } else
                                seq_puts(m, "\ttramp: ERROR!");
-
+               } else {
+                       add_trampoline_func(m, NULL, rec);
                }
-               add_trampoline_func(m, ops, rec);
        }       
 
        seq_putc(m, '\n');
@@ -4898,6 +4906,19 @@ static int ftrace_process_locs(struct module *mod,
 
 #define next_to_ftrace_page(p) container_of(p, struct ftrace_page, next)
 
+static int referenced_filters(struct dyn_ftrace *rec)
+{
+       struct ftrace_ops *ops;
+       int cnt = 0;
+
+       for (ops = ftrace_ops_list; ops != &ftrace_list_end; ops = ops->next) {
+               if (ops_references_rec(ops, rec))
+                   cnt++;
+       }
+
+       return cnt;
+}
+
 void ftrace_release_mod(struct module *mod)
 {
        struct dyn_ftrace *rec;
@@ -4940,41 +4961,112 @@ void ftrace_release_mod(struct module *mod)
        mutex_unlock(&ftrace_lock);
 }
 
-static void ftrace_init_module(struct module *mod,
-                              unsigned long *start, unsigned long *end)
+static void ftrace_module_enable(struct module *mod)
 {
-       if (ftrace_disabled || start == end)
-               return;
-       ftrace_process_locs(mod, start, end);
+       struct dyn_ftrace *rec;
+       struct ftrace_page *pg;
+
+       mutex_lock(&ftrace_lock);
+
+       if (ftrace_disabled)
+               goto out_unlock;
+
+       /*
+        * If the tracing is enabled, go ahead and enable the record.
+        *
+        * The reason not to enable the record immediatelly is the
+        * inherent check of ftrace_make_nop/ftrace_make_call for
+        * correct previous instructions.  Making first the NOP
+        * conversion puts the module to the correct state, thus
+        * passing the ftrace_make_call check.
+        *
+        * We also delay this to after the module code already set the
+        * text to read-only, as we now need to set it back to read-write
+        * so that we can modify the text.
+        */
+       if (ftrace_start_up)
+               ftrace_arch_code_modify_prepare();
+
+       do_for_each_ftrace_rec(pg, rec) {
+               int cnt;
+               /*
+                * do_for_each_ftrace_rec() is a double loop.
+                * module text shares the pg. If a record is
+                * not part of this module, then skip this pg,
+                * which the "break" will do.
+                */
+               if (!within_module_core(rec->ip, mod))
+                       break;
+
+               cnt = 0;
+
+               /*
+                * When adding a module, we need to check if tracers are
+                * currently enabled and if they are, and can trace this record,
+                * we need to enable the module functions as well as update the
+                * reference counts for those function records.
+                */
+               if (ftrace_start_up)
+                       cnt += referenced_filters(rec);
+
+               /* This clears FTRACE_FL_DISABLED */
+               rec->flags = cnt;
+
+               if (ftrace_start_up && cnt) {
+                       int failed = __ftrace_replace_code(rec, 1);
+                       if (failed) {
+                               ftrace_bug(failed, rec);
+                               goto out_loop;
+                       }
+               }
+
+       } while_for_each_ftrace_rec();
+
+ out_loop:
+       if (ftrace_start_up)
+               ftrace_arch_code_modify_post_process();
+
+ out_unlock:
+       mutex_unlock(&ftrace_lock);
 }
 
 void ftrace_module_init(struct module *mod)
 {
-       ftrace_init_module(mod, mod->ftrace_callsites,
-                          mod->ftrace_callsites +
-                          mod->num_ftrace_callsites);
+       if (ftrace_disabled || !mod->num_ftrace_callsites)
+               return;
+
+       ftrace_process_locs(mod, mod->ftrace_callsites,
+                           mod->ftrace_callsites + mod->num_ftrace_callsites);
 }
 
-static int ftrace_module_notify_exit(struct notifier_block *self,
-                                    unsigned long val, void *data)
+static int ftrace_module_notify(struct notifier_block *self,
+                               unsigned long val, void *data)
 {
        struct module *mod = data;
 
-       if (val == MODULE_STATE_GOING)
+       switch (val) {
+       case MODULE_STATE_COMING:
+               ftrace_module_enable(mod);
+               break;
+       case MODULE_STATE_GOING:
                ftrace_release_mod(mod);
+               break;
+       default:
+               break;
+       }
 
        return 0;
 }
 #else
-static int ftrace_module_notify_exit(struct notifier_block *self,
-                                    unsigned long val, void *data)
+static int ftrace_module_notify(struct notifier_block *self,
+                               unsigned long val, void *data)
 {
        return 0;
 }
 #endif /* CONFIG_MODULES */
 
-struct notifier_block ftrace_module_exit_nb = {
-       .notifier_call = ftrace_module_notify_exit,
+struct notifier_block ftrace_module_nb = {
+       .notifier_call = ftrace_module_notify,
        .priority = INT_MIN,    /* Run after anything that can remove kprobes */
 };
 
@@ -5006,7 +5098,7 @@ void __init ftrace_init(void)
                                  __start_mcount_loc,
                                  __stop_mcount_loc);
 
-       ret = register_module_notifier(&ftrace_module_exit_nb);
+       ret = register_module_notifier(&ftrace_module_nb);
        if (ret)
                pr_warning("Failed to register trace ftrace module exit notifier\n");
 
@@ -5116,44 +5208,6 @@ void ftrace_reset_array_ops(struct trace_array *tr)
        tr->ops->func = ftrace_stub;
 }
 
-static void
-ftrace_ops_control_func(unsigned long ip, unsigned long parent_ip,
-                       struct ftrace_ops *op, struct pt_regs *regs)
-{
-       if (unlikely(trace_recursion_test(TRACE_CONTROL_BIT)))
-               return;
-
-       /*
-        * Some of the ops may be dynamically allocated,
-        * they must be freed after a synchronize_sched().
-        */
-       preempt_disable_notrace();
-       trace_recursion_set(TRACE_CONTROL_BIT);
-
-       /*
-        * Control funcs (perf) uses RCU. Only trace if
-        * RCU is currently active.
-        */
-       if (!rcu_is_watching())
-               goto out;
-
-       do_for_each_ftrace_op(op, ftrace_control_list) {
-               if (!(op->flags & FTRACE_OPS_FL_STUB) &&
-                   !ftrace_function_local_disabled(op) &&
-                   ftrace_ops_test(op, ip, regs))
-                       op->func(ip, parent_ip, op, regs);
-       } while_for_each_ftrace_op(op);
- out:
-       trace_recursion_clear(TRACE_CONTROL_BIT);
-       preempt_enable_notrace();
-}
-
-static struct ftrace_ops control_ops = {
-       .func   = ftrace_ops_control_func,
-       .flags  = FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_INITIALIZED,
-       INIT_OPS_HASH(control_ops)
-};
-
 static inline void
 __ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,
                       struct ftrace_ops *ignored, struct pt_regs *regs)
@@ -5170,8 +5224,22 @@ __ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,
         * they must be freed after a synchronize_sched().
         */
        preempt_disable_notrace();
+
        do_for_each_ftrace_op(op, ftrace_ops_list) {
-               if (ftrace_ops_test(op, ip, regs)) {
+               /*
+                * Check the following for each ops before calling their func:
+                *  if RCU flag is set, then rcu_is_watching() must be true
+                *  if PER_CPU is set, then ftrace_function_local_disable()
+                *                          must be false
+                *  Otherwise test if the ip matches the ops filter
+                *
+                * If any of the above fails then the op->func() is not executed.
+                */
+               if ((!(op->flags & FTRACE_OPS_FL_RCU) || rcu_is_watching()) &&
+                   (!(op->flags & FTRACE_OPS_FL_PER_CPU) ||
+                    !ftrace_function_local_disabled(op)) &&
+                   ftrace_ops_test(op, ip, regs)) {
+                   
                        if (FTRACE_WARN_ON(!op->func)) {
                                pr_warn("op=%p %pS\n", op, op);
                                goto out;
@@ -5195,7 +5263,7 @@ out:
  * being NULL, or CONFIG_DYNAMIC_FTRACE_WITH_REGS.
  * Note, CONFIG_DYNAMIC_FTRACE_WITH_REGS expects a full regs to be saved.
  * An architecture can pass partial regs with ftrace_ops and still
- * set the ARCH_SUPPORT_FTARCE_OPS.
+ * set the ARCH_SUPPORTS_FTRACE_OPS.
  */
 #if ARCH_SUPPORTS_FTRACE_OPS
 static void ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,
@@ -5212,20 +5280,29 @@ static void ftrace_ops_no_ops(unsigned long ip, unsigned long parent_ip)
 
 /*
  * If there's only one function registered but it does not support
- * recursion, this function will be called by the mcount trampoline.
- * This function will handle recursion protection.
+ * recursion, needs RCU protection and/or requires per cpu handling, then
+ * this function will be called by the mcount trampoline.
  */
-static void ftrace_ops_recurs_func(unsigned long ip, unsigned long parent_ip,
+static void ftrace_ops_assist_func(unsigned long ip, unsigned long parent_ip,
                                   struct ftrace_ops *op, struct pt_regs *regs)
 {
        int bit;
 
+       if ((op->flags & FTRACE_OPS_FL_RCU) && !rcu_is_watching())
+               return;
+
        bit = trace_test_and_set_recursion(TRACE_LIST_START, TRACE_LIST_MAX);
        if (bit < 0)
                return;
 
-       op->func(ip, parent_ip, op, regs);
+       preempt_disable_notrace();
 
+       if (!(op->flags & FTRACE_OPS_FL_PER_CPU) ||
+           !ftrace_function_local_disabled(op)) {
+               op->func(ip, parent_ip, op, regs);
+       }
+
+       preempt_enable_notrace();
        trace_clear_recursion(bit);
 }
 
@@ -5243,12 +5320,12 @@ static void ftrace_ops_recurs_func(unsigned long ip, unsigned long parent_ip,
 ftrace_func_t ftrace_ops_get_func(struct ftrace_ops *ops)
 {
        /*
-        * If the func handles its own recursion, call it directly.
-        * Otherwise call the recursion protected function that
-        * will call the ftrace ops function.
+        * If the function does not handle recursion, needs to be RCU safe,
+        * or does per cpu logic, then we need to call the assist handler.
         */
-       if (!(ops->flags & FTRACE_OPS_FL_RECURSION_SAFE))
-               return ftrace_ops_recurs_func;
+       if (!(ops->flags & FTRACE_OPS_FL_RECURSION_SAFE) ||
+           ops->flags & (FTRACE_OPS_FL_RCU | FTRACE_OPS_FL_PER_CPU))
+               return ftrace_ops_assist_func;
 
        return ops->func;
 }
index 9c6045a27ba356252546971fb26dbae30149c89c..95181e36891a2b63f38083ec7b81439d589fdcfe 100644 (file)
@@ -1001,17 +1001,13 @@ static int rb_head_page_replace(struct buffer_page *old,
 
 /*
  * rb_tail_page_update - move the tail page forward
- *
- * Returns 1 if moved tail page, 0 if someone else did.
  */
-static int rb_tail_page_update(struct ring_buffer_per_cpu *cpu_buffer,
+static void rb_tail_page_update(struct ring_buffer_per_cpu *cpu_buffer,
                               struct buffer_page *tail_page,
                               struct buffer_page *next_page)
 {
-       struct buffer_page *old_tail;
        unsigned long old_entries;
        unsigned long old_write;
-       int ret = 0;
 
        /*
         * The tail page now needs to be moved forward.
@@ -1036,7 +1032,7 @@ static int rb_tail_page_update(struct ring_buffer_per_cpu *cpu_buffer,
         * it is, then it is up to us to update the tail
         * pointer.
         */
-       if (tail_page == cpu_buffer->tail_page) {
+       if (tail_page == READ_ONCE(cpu_buffer->tail_page)) {
                /* Zero the write counter */
                unsigned long val = old_write & ~RB_WRITE_MASK;
                unsigned long eval = old_entries & ~RB_WRITE_MASK;
@@ -1061,14 +1057,9 @@ static int rb_tail_page_update(struct ring_buffer_per_cpu *cpu_buffer,
                 */
                local_set(&next_page->page->commit, 0);
 
-               old_tail = cmpxchg(&cpu_buffer->tail_page,
-                                  tail_page, next_page);
-
-               if (old_tail == tail_page)
-                       ret = 1;
+               /* Again, either we update tail_page or an interrupt does */
+               (void)cmpxchg(&cpu_buffer->tail_page, tail_page, next_page);
        }
-
-       return ret;
 }
 
 static int rb_check_bpage(struct ring_buffer_per_cpu *cpu_buffer,
@@ -2036,12 +2027,15 @@ rb_handle_head_page(struct ring_buffer_per_cpu *cpu_buffer,
         * the tail page would have moved.
         */
        if (ret == RB_PAGE_NORMAL) {
+               struct buffer_page *buffer_tail_page;
+
+               buffer_tail_page = READ_ONCE(cpu_buffer->tail_page);
                /*
                 * If the tail had moved passed next, then we need
                 * to reset the pointer.
                 */
-               if (cpu_buffer->tail_page != tail_page &&
-                   cpu_buffer->tail_page != next_page)
+               if (buffer_tail_page != tail_page &&
+                   buffer_tail_page != next_page)
                        rb_head_page_set_normal(cpu_buffer, new_head,
                                                next_page,
                                                RB_PAGE_HEAD);
@@ -2135,6 +2129,8 @@ rb_reset_tail(struct ring_buffer_per_cpu *cpu_buffer,
        local_sub(length, &tail_page->write);
 }
 
+static inline void rb_end_commit(struct ring_buffer_per_cpu *cpu_buffer);
+
 /*
  * This is the slow path, force gcc not to inline it.
  */
@@ -2147,7 +2143,6 @@ rb_move_tail(struct ring_buffer_per_cpu *cpu_buffer,
        struct ring_buffer *buffer = cpu_buffer->buffer;
        struct buffer_page *next_page;
        int ret;
-       u64 ts;
 
        next_page = tail_page;
 
@@ -2221,20 +2216,17 @@ rb_move_tail(struct ring_buffer_per_cpu *cpu_buffer,
                }
        }
 
-       ret = rb_tail_page_update(cpu_buffer, tail_page, next_page);
-       if (ret) {
-               /*
-                * Nested commits always have zero deltas, so
-                * just reread the time stamp
-                */
-               ts = rb_time_stamp(buffer);
-               next_page->page->time_stamp = ts;
-       }
+       rb_tail_page_update(cpu_buffer, tail_page, next_page);
 
  out_again:
 
        rb_reset_tail(cpu_buffer, tail, info);
 
+       /* Commit what we have for now. */
+       rb_end_commit(cpu_buffer);
+       /* rb_end_commit() decs committing */
+       local_inc(&cpu_buffer->committing);
+
        /* fail and let the caller try again */
        return ERR_PTR(-EAGAIN);
 
@@ -2362,7 +2354,7 @@ rb_try_to_discard(struct ring_buffer_per_cpu *cpu_buffer,
        addr = (unsigned long)event;
        addr &= PAGE_MASK;
 
-       bpage = cpu_buffer->tail_page;
+       bpage = READ_ONCE(cpu_buffer->tail_page);
 
        if (bpage->page == (void *)addr && rb_page_write(bpage) == old_index) {
                unsigned long write_mask =
@@ -2410,7 +2402,7 @@ rb_set_commit_to_write(struct ring_buffer_per_cpu *cpu_buffer)
  again:
        max_count = cpu_buffer->nr_pages * 100;
 
-       while (cpu_buffer->commit_page != cpu_buffer->tail_page) {
+       while (cpu_buffer->commit_page != READ_ONCE(cpu_buffer->tail_page)) {
                if (RB_WARN_ON(cpu_buffer, !(--max_count)))
                        return;
                if (RB_WARN_ON(cpu_buffer,
@@ -2419,8 +2411,10 @@ rb_set_commit_to_write(struct ring_buffer_per_cpu *cpu_buffer)
                local_set(&cpu_buffer->commit_page->page->commit,
                          rb_page_write(cpu_buffer->commit_page));
                rb_inc_page(cpu_buffer, &cpu_buffer->commit_page);
-               cpu_buffer->write_stamp =
-                       cpu_buffer->commit_page->page->time_stamp;
+               /* Only update the write stamp if the page has an event */
+               if (rb_page_write(cpu_buffer->commit_page))
+                       cpu_buffer->write_stamp =
+                               cpu_buffer->commit_page->page->time_stamp;
                /* add barrier to keep gcc from optimizing too much */
                barrier();
        }
@@ -2443,7 +2437,7 @@ rb_set_commit_to_write(struct ring_buffer_per_cpu *cpu_buffer)
         * and pushed the tail page forward, we will be left with
         * a dangling commit that will never go forward.
         */
-       if (unlikely(cpu_buffer->commit_page != cpu_buffer->tail_page))
+       if (unlikely(cpu_buffer->commit_page != READ_ONCE(cpu_buffer->tail_page)))
                goto again;
 }
 
@@ -2699,7 +2693,8 @@ __rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer,
        if (unlikely(info->add_timestamp))
                info->length += RB_LEN_TIME_EXTEND;
 
-       tail_page = info->tail_page = cpu_buffer->tail_page;
+       /* Don't let the compiler play games with cpu_buffer->tail_page */
+       tail_page = info->tail_page = READ_ONCE(cpu_buffer->tail_page);
        write = local_add_return(info->length, &tail_page->write);
 
        /* set write to only the index of the write */
index 919d9d07686f5bcaad65699f400748a4b4db8a5e..8414fa40bf275cde2b93c58ef349b6fb9ec1d90d 100644 (file)
@@ -363,8 +363,8 @@ struct trace_option_dentry {
  * @name: the name chosen to select it on the available_tracers file
  * @init: called when one switches to this tracer (echo name > current_tracer)
  * @reset: called when one switches to another tracer
- * @start: called when tracing is unpaused (echo 1 > tracing_enabled)
- * @stop: called when tracing is paused (echo 0 > tracing_enabled)
+ * @start: called when tracing is unpaused (echo 1 > tracing_on)
+ * @stop: called when tracing is paused (echo 0 > tracing_on)
  * @update_thresh: called when tracing_thresh is updated
  * @open: called when the trace file is opened
  * @pipe_open: called when the trace_pipe file is opened
@@ -467,8 +467,6 @@ enum {
        TRACE_INTERNAL_IRQ_BIT,
        TRACE_INTERNAL_SIRQ_BIT,
 
-       TRACE_CONTROL_BIT,
-
        TRACE_BRANCH_BIT,
 /*
  * Abuse of the trace_recursion.
index cc9f7a9319bea63104ef05c97634c43286a5268c..00df25fd86ef458b4ee23d645efda32426af2568 100644 (file)
@@ -334,7 +334,7 @@ static int perf_ftrace_function_register(struct perf_event *event)
 {
        struct ftrace_ops *ops = &event->ftrace_ops;
 
-       ops->flags |= FTRACE_OPS_FL_CONTROL;
+       ops->flags |= FTRACE_OPS_FL_PER_CPU | FTRACE_OPS_FL_RCU;
        ops->func = perf_ftrace_function_call;
        return register_ftrace_function(ops);
 }
index 4b5e8ed68d77a9b711fefae80b6999b9d6eaf579..b38f617b618185d907670ca77774b3332bdb63db 100644 (file)
@@ -538,11 +538,12 @@ static int register_trigger(char *glob, struct event_trigger_ops *ops,
        list_add_rcu(&data->list, &file->triggers);
        ret++;
 
+       update_cond_flag(file);
        if (trace_event_trigger_enable_disable(file, 1) < 0) {
                list_del_rcu(&data->list);
+               update_cond_flag(file);
                ret--;
        }
-       update_cond_flag(file);
 out:
        return ret;
 }
@@ -570,8 +571,8 @@ static void unregister_trigger(char *glob, struct event_trigger_ops *ops,
                if (data->cmd_ops->trigger_type == test->cmd_ops->trigger_type) {
                        unregistered = true;
                        list_del_rcu(&data->list);
-                       update_cond_flag(file);
                        trace_event_trigger_enable_disable(file, 0);
+                       update_cond_flag(file);
                        break;
                }
        }
@@ -1314,11 +1315,12 @@ static int event_enable_register_trigger(char *glob,
        list_add_rcu(&data->list, &file->triggers);
        ret++;
 
+       update_cond_flag(file);
        if (trace_event_trigger_enable_disable(file, 1) < 0) {
                list_del_rcu(&data->list);
+               update_cond_flag(file);
                ret--;
        }
-       update_cond_flag(file);
 out:
        return ret;
 }
@@ -1339,8 +1341,8 @@ static void event_enable_unregister_trigger(char *glob,
                    (enable_data->file == test_enable_data->file)) {
                        unregistered = true;
                        list_del_rcu(&data->list);
-                       update_cond_flag(file);
                        trace_event_trigger_enable_disable(file, 0);
+                       update_cond_flag(file);
                        break;
                }
        }
index 5c94e1012a91f9ea65b20ca130f3f4aa4fb337f5..cb18469e1f490066fe36dcc6e3f8127ddc6a98da 100644 (file)
@@ -306,10 +306,12 @@ int seq_buf_to_user(struct seq_buf *s, char __user *ubuf, int cnt)
        if (!cnt)
                return 0;
 
-       if (s->len <= s->readpos)
+       len = seq_buf_used(s);
+
+       if (len <= s->readpos)
                return -EBUSY;
 
-       len = seq_buf_used(s) - s->readpos;
+       len -= s->readpos;
        if (cnt > len)
                cnt = len;
        ret = copy_to_user(ubuf, s->buffer + s->readpos, cnt);
index fc10620967c79d7b8fbbcc0f82fd9804b1562f13..14cb1db4c52b75ee16d1346e89e8bd6047d3db9f 100644 (file)
@@ -4813,7 +4813,7 @@ static void mem_cgroup_clear_mc(void)
 static int mem_cgroup_can_attach(struct cgroup_taskset *tset)
 {
        struct cgroup_subsys_state *css;
-       struct mem_cgroup *memcg;
+       struct mem_cgroup *memcg = NULL; /* unneeded init to make gcc happy */
        struct mem_cgroup *from;
        struct task_struct *leader, *p;
        struct mm_struct *mm;
index 10ad4ac1fa0ba8ebd04e793595fab47d326194ce..1b8a5caa221eb6a2554a95fdfb2a53ea7f17d9c3 100644 (file)
@@ -7,6 +7,7 @@
  * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
  * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
  * Copyright 2007-2010, Intel Corporation
+ * Copyright(c) 2015 Intel Deutschland GmbH
  *
  * 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
@@ -61,16 +62,25 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
 {
        struct ieee80211_local *local = sta->local;
        struct tid_ampdu_rx *tid_rx;
+       struct ieee80211_ampdu_params params = {
+               .sta = &sta->sta,
+               .action = IEEE80211_AMPDU_RX_STOP,
+               .tid = tid,
+               .amsdu = false,
+               .timeout = 0,
+               .ssn = 0,
+       };
 
        lockdep_assert_held(&sta->ampdu_mlme.mtx);
 
        tid_rx = rcu_dereference_protected(sta->ampdu_mlme.tid_rx[tid],
                                        lockdep_is_held(&sta->ampdu_mlme.mtx));
 
-       if (!tid_rx)
+       if (!test_bit(tid, sta->ampdu_mlme.agg_session_valid))
                return;
 
        RCU_INIT_POINTER(sta->ampdu_mlme.tid_rx[tid], NULL);
+       __clear_bit(tid, sta->ampdu_mlme.agg_session_valid);
 
        ht_dbg(sta->sdata,
               "Rx BA session stop requested for %pM tid %u %s reason: %d\n",
@@ -78,8 +88,7 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
               initiator == WLAN_BACK_RECIPIENT ? "recipient" : "inititator",
               (int)reason);
 
-       if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP,
-                            &sta->sta, tid, NULL, 0, false))
+       if (drv_ampdu_action(local, sta->sdata, &params))
                sdata_info(sta->sdata,
                           "HW problem - can not stop rx aggregation for %pM tid %d\n",
                           sta->sta.addr, tid);
@@ -89,6 +98,13 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
                ieee80211_send_delba(sta->sdata, sta->sta.addr,
                                     tid, WLAN_BACK_RECIPIENT, reason);
 
+       /*
+        * return here in case tid_rx is not assigned - which will happen if
+        * IEEE80211_HW_SUPPORTS_REORDERING_BUFFER is set.
+        */
+       if (!tid_rx)
+               return;
+
        del_timer_sync(&tid_rx->session_timer);
 
        /* make sure ieee80211_sta_reorder_release() doesn't re-arm the timer */
@@ -237,6 +253,15 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta,
 {
        struct ieee80211_local *local = sta->sdata->local;
        struct tid_ampdu_rx *tid_agg_rx;
+       struct ieee80211_ampdu_params params = {
+               .sta = &sta->sta,
+               .action = IEEE80211_AMPDU_RX_START,
+               .tid = tid,
+               .amsdu = false,
+               .timeout = timeout,
+               .ssn = start_seq_num,
+       };
+
        int i, ret = -EOPNOTSUPP;
        u16 status = WLAN_STATUS_REQUEST_DECLINED;
 
@@ -275,11 +300,12 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta,
        /* make sure the size doesn't exceed the maximum supported by the hw */
        if (buf_size > local->hw.max_rx_aggregation_subframes)
                buf_size = local->hw.max_rx_aggregation_subframes;
+       params.buf_size = buf_size;
 
        /* examine state machine */
        mutex_lock(&sta->ampdu_mlme.mtx);
 
-       if (sta->ampdu_mlme.tid_rx[tid]) {
+       if (test_bit(tid, sta->ampdu_mlme.agg_session_valid)) {
                ht_dbg_ratelimited(sta->sdata,
                                   "unexpected AddBA Req from %pM on tid %u\n",
                                   sta->sta.addr, tid);
@@ -290,6 +316,16 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta,
                                                false);
        }
 
+       if (ieee80211_hw_check(&local->hw, SUPPORTS_REORDERING_BUFFER)) {
+               ret = drv_ampdu_action(local, sta->sdata, &params);
+               ht_dbg(sta->sdata,
+                      "Rx A-MPDU request on %pM tid %d result %d\n",
+                      sta->sta.addr, tid, ret);
+               if (!ret)
+                       status = WLAN_STATUS_SUCCESS;
+               goto end;
+       }
+
        /* prepare A-MPDU MLME for Rx aggregation */
        tid_agg_rx = kmalloc(sizeof(struct tid_ampdu_rx), GFP_KERNEL);
        if (!tid_agg_rx)
@@ -322,8 +358,7 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta,
        for (i = 0; i < buf_size; i++)
                __skb_queue_head_init(&tid_agg_rx->reorder_buf[i]);
 
-       ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START,
-                              &sta->sta, tid, &start_seq_num, 0, false);
+       ret = drv_ampdu_action(local, sta->sdata, &params);
        ht_dbg(sta->sdata, "Rx A-MPDU request on %pM tid %d result %d\n",
               sta->sta.addr, tid, ret);
        if (ret) {
@@ -341,6 +376,7 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta,
        tid_agg_rx->timeout = timeout;
        tid_agg_rx->stored_mpdu_num = 0;
        tid_agg_rx->auto_seq = auto_seq;
+       tid_agg_rx->reorder_buf_filtered = 0;
        status = WLAN_STATUS_SUCCESS;
 
        /* activate it for RX */
@@ -352,6 +388,8 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta,
        }
 
 end:
+       if (status == WLAN_STATUS_SUCCESS)
+               __set_bit(tid, sta->ampdu_mlme.agg_session_valid);
        mutex_unlock(&sta->ampdu_mlme.mtx);
 
 end_no_lock:
index ff757181b0a85c820e1acc53a088e95c78b87bff..4932e9f243a2cb9e156e7e24ac1c098fc9a4b19c 100644 (file)
@@ -7,6 +7,7 @@
  * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
  * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
  * Copyright 2007-2010, Intel Corporation
+ * Copyright(c) 2015 Intel Deutschland GmbH
  *
  * 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
@@ -295,7 +296,14 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
 {
        struct ieee80211_local *local = sta->local;
        struct tid_ampdu_tx *tid_tx;
-       enum ieee80211_ampdu_mlme_action action;
+       struct ieee80211_ampdu_params params = {
+               .sta = &sta->sta,
+               .tid = tid,
+               .buf_size = 0,
+               .amsdu = false,
+               .timeout = 0,
+               .ssn = 0,
+       };
        int ret;
 
        lockdep_assert_held(&sta->ampdu_mlme.mtx);
@@ -304,10 +312,10 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
        case AGG_STOP_DECLINED:
        case AGG_STOP_LOCAL_REQUEST:
        case AGG_STOP_PEER_REQUEST:
-               action = IEEE80211_AMPDU_TX_STOP_CONT;
+               params.action = IEEE80211_AMPDU_TX_STOP_CONT;
                break;
        case AGG_STOP_DESTROY_STA:
-               action = IEEE80211_AMPDU_TX_STOP_FLUSH;
+               params.action = IEEE80211_AMPDU_TX_STOP_FLUSH;
                break;
        default:
                WARN_ON_ONCE(1);
@@ -330,9 +338,8 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
                spin_unlock_bh(&sta->lock);
                if (reason != AGG_STOP_DESTROY_STA)
                        return -EALREADY;
-               ret = drv_ampdu_action(local, sta->sdata,
-                                      IEEE80211_AMPDU_TX_STOP_FLUSH_CONT,
-                                      &sta->sta, tid, NULL, 0, false);
+               params.action = IEEE80211_AMPDU_TX_STOP_FLUSH_CONT;
+               ret = drv_ampdu_action(local, sta->sdata, &params);
                WARN_ON_ONCE(ret);
                return 0;
        }
@@ -381,8 +388,7 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
                                        WLAN_BACK_INITIATOR;
        tid_tx->tx_stop = reason == AGG_STOP_LOCAL_REQUEST;
 
-       ret = drv_ampdu_action(local, sta->sdata, action,
-                              &sta->sta, tid, NULL, 0, false);
+       ret = drv_ampdu_action(local, sta->sdata, &params);
 
        /* HW shall not deny going back to legacy */
        if (WARN_ON(ret)) {
@@ -445,7 +451,14 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
        struct tid_ampdu_tx *tid_tx;
        struct ieee80211_local *local = sta->local;
        struct ieee80211_sub_if_data *sdata = sta->sdata;
-       u16 start_seq_num;
+       struct ieee80211_ampdu_params params = {
+               .sta = &sta->sta,
+               .action = IEEE80211_AMPDU_TX_START,
+               .tid = tid,
+               .buf_size = 0,
+               .amsdu = false,
+               .timeout = 0,
+       };
        int ret;
 
        tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
@@ -467,10 +480,8 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
         */
        synchronize_net();
 
-       start_seq_num = sta->tid_seq[tid] >> 4;
-
-       ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START,
-                              &sta->sta, tid, &start_seq_num, 0, false);
+       params.ssn = sta->tid_seq[tid] >> 4;
+       ret = drv_ampdu_action(local, sdata, &params);
        if (ret) {
                ht_dbg(sdata,
                       "BA request denied - HW unavailable for %pM tid %d\n",
@@ -499,7 +510,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
 
        /* send AddBA request */
        ieee80211_send_addba_request(sdata, sta->sta.addr, tid,
-                                    tid_tx->dialog_token, start_seq_num,
+                                    tid_tx->dialog_token, params.ssn,
                                     IEEE80211_MAX_AMPDU_BUF,
                                     tid_tx->timeout);
 }
@@ -684,18 +695,24 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local,
                                         struct sta_info *sta, u16 tid)
 {
        struct tid_ampdu_tx *tid_tx;
+       struct ieee80211_ampdu_params params = {
+               .sta = &sta->sta,
+               .action = IEEE80211_AMPDU_TX_OPERATIONAL,
+               .tid = tid,
+               .timeout = 0,
+               .ssn = 0,
+       };
 
        lockdep_assert_held(&sta->ampdu_mlme.mtx);
 
        tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
+       params.buf_size = tid_tx->buf_size;
+       params.amsdu = tid_tx->amsdu;
 
        ht_dbg(sta->sdata, "Aggregation is on for %pM tid %d\n",
               sta->sta.addr, tid);
 
-       drv_ampdu_action(local, sta->sdata,
-                        IEEE80211_AMPDU_TX_OPERATIONAL,
-                        &sta->sta, tid, NULL, tid_tx->buf_size,
-                        tid_tx->amsdu);
+       drv_ampdu_action(local, sta->sdata, &params);
 
        /*
         * synchronize with TX path, while splicing the TX path
index 166a29fe6c35f63a5357a01ceeb140f19346f9bd..fe1704c4e8fb825a455afeb53f34fd50b62dd33e 100644 (file)
@@ -339,8 +339,9 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
 
        switch (key->conf.cipher) {
        case WLAN_CIPHER_SUITE_TKIP:
-               iv32 = key->u.tkip.tx.iv32;
-               iv16 = key->u.tkip.tx.iv16;
+               pn64 = atomic64_read(&key->conf.tx_pn);
+               iv32 = TKIP_PN_TO_IV32(pn64);
+               iv16 = TKIP_PN_TO_IV16(pn64);
 
                if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE &&
                    !(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
@@ -1131,6 +1132,34 @@ static int sta_apply_parameters(struct ieee80211_local *local,
                sta->sta.max_sp = params->max_sp;
        }
 
+       /* The sender might not have sent the last bit, consider it to be 0 */
+       if (params->ext_capab_len >= 8) {
+               u8 val = (params->ext_capab[7] &
+                         WLAN_EXT_CAPA8_MAX_MSDU_IN_AMSDU_LSB) >> 7;
+
+               /* we did get all the bits, take the MSB as well */
+               if (params->ext_capab_len >= 9) {
+                       u8 val_msb = params->ext_capab[8] &
+                               WLAN_EXT_CAPA9_MAX_MSDU_IN_AMSDU_MSB;
+                       val_msb <<= 1;
+                       val |= val_msb;
+               }
+
+               switch (val) {
+               case 1:
+                       sta->sta.max_amsdu_subframes = 32;
+                       break;
+               case 2:
+                       sta->sta.max_amsdu_subframes = 16;
+                       break;
+               case 3:
+                       sta->sta.max_amsdu_subframes = 8;
+                       break;
+               default:
+                       sta->sta.max_amsdu_subframes = 0;
+               }
+       }
+
        /*
         * cfg80211 validates this (1-2007) and allows setting the AID
         * only when creating a new station entry
@@ -1160,6 +1189,7 @@ static int sta_apply_parameters(struct ieee80211_local *local,
                ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
                                                  params->ht_capa, sta);
 
+       /* VHT can override some HT caps such as the A-MSDU max length */
        if (params->vht_capa)
                ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
                                                    params->vht_capa, sta);
index 1d1b9b7bdefe74ac851ca6d01554d663fae39541..283981108ca80cb5bb7182b28e626a1a14c09fb1 100644 (file)
@@ -231,7 +231,7 @@ ieee80211_get_max_required_bw(struct ieee80211_sub_if_data *sdata)
                    !(sta->sdata->bss && sta->sdata->bss == sdata->bss))
                        continue;
 
-               if (!sta->uploaded)
+               if (!sta->uploaded || !test_sta_flag(sta, WLAN_STA_ASSOC))
                        continue;
 
                max_bw = max(max_bw, ieee80211_get_sta_bw(&sta->sta));
index abbdff03ce92307551eb52b780e9a76e1873c203..e433d0c97e86118394cd39c663f3531fd1145a75 100644 (file)
@@ -126,6 +126,7 @@ static const char *hw_flag_names[NUM_IEEE80211_HW_FLAGS + 1] = {
        FLAG(SUPPORTS_AMSDU_IN_AMPDU),
        FLAG(BEACON_TX_STATUS),
        FLAG(NEEDS_UNIQUE_STA_ADDR),
+       FLAG(SUPPORTS_REORDERING_BUFFER),
 
        /* keep last for the build bug below */
        (void *)0x1
index 7961e7d0b61e1ee48700e9a7ef2db8feec84814f..a2ef95f16f116ae905049c595742bcee3e78c6c7 100644 (file)
@@ -132,9 +132,10 @@ static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf,
                len = scnprintf(buf, sizeof(buf), "\n");
                break;
        case WLAN_CIPHER_SUITE_TKIP:
+               pn = atomic64_read(&key->conf.tx_pn);
                len = scnprintf(buf, sizeof(buf), "%08x %04x\n",
-                               key->u.tkip.tx.iv32,
-                               key->u.tkip.tx.iv16);
+                               TKIP_PN_TO_IV32(pn),
+                               TKIP_PN_TO_IV16(pn));
                break;
        case WLAN_CIPHER_SUITE_CCMP:
        case WLAN_CIPHER_SUITE_CCMP_256:
index ca1fe5576103767c3a98b52e037c0034b949887f..c258f1041d330885d08869e302a5ec255b470b4b 100644 (file)
@@ -284,9 +284,7 @@ int drv_switch_vif_chanctx(struct ieee80211_local *local,
 
 int drv_ampdu_action(struct ieee80211_local *local,
                     struct ieee80211_sub_if_data *sdata,
-                    enum ieee80211_ampdu_mlme_action action,
-                    struct ieee80211_sta *sta, u16 tid,
-                    u16 *ssn, u8 buf_size, bool amsdu)
+                    struct ieee80211_ampdu_params *params)
 {
        int ret = -EOPNOTSUPP;
 
@@ -296,12 +294,10 @@ int drv_ampdu_action(struct ieee80211_local *local,
        if (!check_sdata_in_driver(sdata))
                return -EIO;
 
-       trace_drv_ampdu_action(local, sdata, action, sta, tid,
-                              ssn, buf_size, amsdu);
+       trace_drv_ampdu_action(local, sdata, params);
 
        if (local->ops->ampdu_action)
-               ret = local->ops->ampdu_action(&local->hw, &sdata->vif, action,
-                                              sta, tid, ssn, buf_size, amsdu);
+               ret = local->ops->ampdu_action(&local->hw, &sdata->vif, params);
 
        trace_drv_return_int(local, ret);
 
index 154ce4b13406d5a31bac8797f8069184ca9cd6f5..18b0d65baff000156c8015f76b9ce527a938e95a 100644 (file)
@@ -585,9 +585,7 @@ static inline int drv_tx_last_beacon(struct ieee80211_local *local)
 
 int drv_ampdu_action(struct ieee80211_local *local,
                     struct ieee80211_sub_if_data *sdata,
-                    enum ieee80211_ampdu_mlme_action action,
-                    struct ieee80211_sta *sta, u16 tid,
-                    u16 *ssn, u8 buf_size, bool amsdu);
+                    struct ieee80211_ampdu_params *params);
 
 static inline int drv_get_survey(struct ieee80211_local *local, int idx,
                                struct survey_info *survey)
index 7a76ce639d58d6071681551e916f0125cf376212..f4a52877356349abed96d0a77d6ae75f301181e4 100644 (file)
@@ -230,6 +230,11 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
        /* set Rx highest rate */
        ht_cap.mcs.rx_highest = ht_cap_ie->mcs.rx_highest;
 
+       if (ht_cap.cap & IEEE80211_HT_CAP_MAX_AMSDU)
+               sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_HT_7935;
+       else
+               sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_HT_3839;
+
  apply:
        changed = memcmp(&sta->sta.ht_cap, &ht_cap, sizeof(ht_cap));
 
index f7fc0e00497fd73f858833e2cb54ec3058b177fe..9b983788ee5180eff22407bc27a43791fe0503d2 100644 (file)
@@ -7,6 +7,7 @@
  * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
  * Copyright 2009, Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
+ * Copyright(c) 2016 Intel Deutschland GmbH
  *
  * 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
@@ -1050,9 +1051,8 @@ static void ieee80211_update_sta_info(struct ieee80211_sub_if_data *sdata,
                struct cfg80211_chan_def chandef;
                enum ieee80211_sta_rx_bandwidth bw = sta->sta.bandwidth;
 
-               ieee80211_ht_oper_to_chandef(channel,
-                                            elems->ht_operation,
-                                            &chandef);
+               cfg80211_chandef_create(&chandef, channel, NL80211_CHAN_NO_HT);
+               ieee80211_chandef_ht_oper(elems->ht_operation, &chandef);
 
                memcpy(&htcap_ie, elems->ht_cap_elem, sizeof(htcap_ie));
                rates_updated |= ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
@@ -1066,9 +1066,8 @@ static void ieee80211_update_sta_info(struct ieee80211_sub_if_data *sdata,
                        struct ieee80211_vht_cap cap_ie;
                        struct ieee80211_sta_vht_cap cap = sta->sta.vht_cap;
 
-                       ieee80211_vht_oper_to_chandef(channel,
-                                                     elems->vht_operation,
-                                                     &chandef);
+                       ieee80211_chandef_vht_oper(elems->vht_operation,
+                                                  &chandef);
                        memcpy(&cap_ie, elems->vht_cap_elem, sizeof(cap_ie));
                        ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
                                                            &cap_ie, sta);
@@ -1485,14 +1484,21 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
 
                sdata_info(sdata, "Trigger new scan to find an IBSS to join\n");
 
-               num = ieee80211_ibss_setup_scan_channels(local->hw.wiphy,
-                                                        &ifibss->chandef,
-                                                        channels,
-                                                        ARRAY_SIZE(channels));
                scan_width = cfg80211_chandef_to_scan_width(&ifibss->chandef);
-               ieee80211_request_ibss_scan(sdata, ifibss->ssid,
-                                           ifibss->ssid_len, channels, num,
-                                           scan_width);
+
+               if (ifibss->fixed_channel) {
+                       num = ieee80211_ibss_setup_scan_channels(local->hw.wiphy,
+                                                                &ifibss->chandef,
+                                                                channels,
+                                                                ARRAY_SIZE(channels));
+                       ieee80211_request_ibss_scan(sdata, ifibss->ssid,
+                                                   ifibss->ssid_len, channels,
+                                                   num, scan_width);
+               } else {
+                       ieee80211_request_ibss_scan(sdata, ifibss->ssid,
+                                                   ifibss->ssid_len, NULL,
+                                                   0, scan_width);
+               }
        } else {
                int interval = IEEE80211_SCAN_INTERVAL;
 
index b84f6aa32c0831ce200f286af2ecd947ef0fefde..1630975c89f159c613668692290450a7d60ed9ab 100644 (file)
@@ -716,7 +716,6 @@ struct ieee80211_if_mesh {
  *     back to wireless media and to the local net stack.
  * @IEEE80211_SDATA_DISCONNECT_RESUME: Disconnect after resume.
  * @IEEE80211_SDATA_IN_DRIVER: indicates interface was added to driver
- * @IEEE80211_SDATA_MU_MIMO_OWNER: indicates interface owns MU-MIMO capability
  */
 enum ieee80211_sub_if_data_flags {
        IEEE80211_SDATA_ALLMULTI                = BIT(0),
@@ -724,7 +723,6 @@ enum ieee80211_sub_if_data_flags {
        IEEE80211_SDATA_DONT_BRIDGE_PACKETS     = BIT(3),
        IEEE80211_SDATA_DISCONNECT_RESUME       = BIT(4),
        IEEE80211_SDATA_IN_DRIVER               = BIT(5),
-       IEEE80211_SDATA_MU_MIMO_OWNER           = BIT(6),
 };
 
 /**
@@ -804,6 +802,7 @@ enum txq_info_flags {
 struct txq_info {
        struct sk_buff_head queue;
        unsigned long flags;
+       unsigned long byte_cnt;
 
        /* keep last! */
        struct ieee80211_txq txq;
@@ -1466,7 +1465,13 @@ ieee80211_have_rx_timestamp(struct ieee80211_rx_status *status)
 {
        WARN_ON_ONCE(status->flag & RX_FLAG_MACTIME_START &&
                     status->flag & RX_FLAG_MACTIME_END);
-       return status->flag & (RX_FLAG_MACTIME_START | RX_FLAG_MACTIME_END);
+       if (status->flag & (RX_FLAG_MACTIME_START | RX_FLAG_MACTIME_END))
+               return true;
+       /* can't handle HT/VHT preamble yet */
+       if (status->flag & RX_FLAG_MACTIME_PLCP_START &&
+           !(status->flag & (RX_FLAG_HT | RX_FLAG_VHT)))
+               return true;
+       return false;
 }
 
 u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
@@ -1714,6 +1719,8 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
 enum ieee80211_sta_rx_bandwidth ieee80211_sta_cap_rx_bw(struct sta_info *sta);
 enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta);
 void ieee80211_sta_set_rx_nss(struct sta_info *sta);
+void ieee80211_process_mu_groups(struct ieee80211_sub_if_data *sdata,
+                                struct ieee80211_mgmt *mgmt);
 u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
                                   struct sta_info *sta, u8 opmode,
                                  enum ieee80211_band band);
@@ -1829,20 +1836,6 @@ static inline void ieee802_11_parse_elems(const u8 *start, size_t len,
        ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0);
 }
 
-static inline bool ieee80211_rx_reorder_ready(struct sk_buff_head *frames)
-{
-       struct sk_buff *tail = skb_peek_tail(frames);
-       struct ieee80211_rx_status *status;
-
-       if (!tail)
-               return false;
-
-       status = IEEE80211_SKB_RXCB(tail);
-       if (status->flag & RX_FLAG_AMSDU_MORE)
-               return false;
-
-       return true;
-}
 
 extern const int ieee802_1d_to_ac[8];
 
@@ -1986,12 +1979,10 @@ int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata,
 u8 *ieee80211_add_wmm_info_ie(u8 *buf, u8 qosinfo);
 
 /* channel management */
-void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan,
-                                 const struct ieee80211_ht_operation *ht_oper,
-                                 struct cfg80211_chan_def *chandef);
-void ieee80211_vht_oper_to_chandef(struct ieee80211_channel *control_chan,
-                                  const struct ieee80211_vht_operation *oper,
-                                  struct cfg80211_chan_def *chandef);
+bool ieee80211_chandef_ht_oper(const struct ieee80211_ht_operation *ht_oper,
+                              struct cfg80211_chan_def *chandef);
+bool ieee80211_chandef_vht_oper(const struct ieee80211_vht_operation *oper,
+                               struct cfg80211_chan_def *chandef);
 u32 ieee80211_chandef_downgrade(struct cfg80211_chan_def *c);
 
 int __must_check
index c9e325d2e120c0f9c230dbace71c3c405b9216a3..453b4e7417804105cb136e2ec7f4c57a39392db3 100644 (file)
@@ -977,7 +977,11 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
        if (sdata->vif.txq) {
                struct txq_info *txqi = to_txq_info(sdata->vif.txq);
 
+               spin_lock_bh(&txqi->queue.lock);
                ieee80211_purge_tx_queue(&local->hw, &txqi->queue);
+               txqi->byte_cnt = 0;
+               spin_unlock_bh(&txqi->queue.lock);
+
                atomic_set(&sdata->txqs_len[txqi->txq.ac], 0);
        }
 
@@ -1271,6 +1275,16 @@ static void ieee80211_iface_work(struct work_struct *work)
                                }
                        }
                        mutex_unlock(&local->sta_mtx);
+               } else if (ieee80211_is_action(mgmt->frame_control) &&
+                          mgmt->u.action.category == WLAN_CATEGORY_VHT) {
+                       switch (mgmt->u.action.u.vht_group_notif.action_code) {
+                       case WLAN_VHT_ACTION_GROUPID_MGMT:
+                               ieee80211_process_mu_groups(sdata, mgmt);
+                               break;
+                       default:
+                               WARN_ON(1);
+                               break;
+                       }
                } else if (ieee80211_is_data_qos(mgmt->frame_control)) {
                        struct ieee80211_hdr *hdr = (void *)mgmt;
                        /*
index 5e5bc599da4c8cc42639f6cbec7de47ea24925bc..3df7b0392d30c70fcfa988a7f1233e17111868a1 100644 (file)
@@ -932,50 +932,6 @@ void ieee80211_gtk_rekey_notify(struct ieee80211_vif *vif, const u8 *bssid,
 }
 EXPORT_SYMBOL_GPL(ieee80211_gtk_rekey_notify);
 
-void ieee80211_get_key_tx_seq(struct ieee80211_key_conf *keyconf,
-                             struct ieee80211_key_seq *seq)
-{
-       struct ieee80211_key *key;
-       u64 pn64;
-
-       if (WARN_ON(!(keyconf->flags & IEEE80211_KEY_FLAG_GENERATE_IV)))
-               return;
-
-       key = container_of(keyconf, struct ieee80211_key, conf);
-
-       switch (key->conf.cipher) {
-       case WLAN_CIPHER_SUITE_TKIP:
-               seq->tkip.iv32 = key->u.tkip.tx.iv32;
-               seq->tkip.iv16 = key->u.tkip.tx.iv16;
-               break;
-       case WLAN_CIPHER_SUITE_CCMP:
-       case WLAN_CIPHER_SUITE_CCMP_256:
-       case WLAN_CIPHER_SUITE_AES_CMAC:
-       case WLAN_CIPHER_SUITE_BIP_CMAC_256:
-               BUILD_BUG_ON(offsetof(typeof(*seq), ccmp) !=
-                            offsetof(typeof(*seq), aes_cmac));
-       case WLAN_CIPHER_SUITE_BIP_GMAC_128:
-       case WLAN_CIPHER_SUITE_BIP_GMAC_256:
-               BUILD_BUG_ON(offsetof(typeof(*seq), ccmp) !=
-                            offsetof(typeof(*seq), aes_gmac));
-       case WLAN_CIPHER_SUITE_GCMP:
-       case WLAN_CIPHER_SUITE_GCMP_256:
-               BUILD_BUG_ON(offsetof(typeof(*seq), ccmp) !=
-                            offsetof(typeof(*seq), gcmp));
-               pn64 = atomic64_read(&key->conf.tx_pn);
-               seq->ccmp.pn[5] = pn64;
-               seq->ccmp.pn[4] = pn64 >> 8;
-               seq->ccmp.pn[3] = pn64 >> 16;
-               seq->ccmp.pn[2] = pn64 >> 24;
-               seq->ccmp.pn[1] = pn64 >> 32;
-               seq->ccmp.pn[0] = pn64 >> 40;
-               break;
-       default:
-               WARN_ON(1);
-       }
-}
-EXPORT_SYMBOL(ieee80211_get_key_tx_seq);
-
 void ieee80211_get_key_rx_seq(struct ieee80211_key_conf *keyconf,
                              int tid, struct ieee80211_key_seq *seq)
 {
@@ -1029,48 +985,6 @@ void ieee80211_get_key_rx_seq(struct ieee80211_key_conf *keyconf,
 }
 EXPORT_SYMBOL(ieee80211_get_key_rx_seq);
 
-void ieee80211_set_key_tx_seq(struct ieee80211_key_conf *keyconf,
-                             struct ieee80211_key_seq *seq)
-{
-       struct ieee80211_key *key;
-       u64 pn64;
-
-       key = container_of(keyconf, struct ieee80211_key, conf);
-
-       switch (key->conf.cipher) {
-       case WLAN_CIPHER_SUITE_TKIP:
-               key->u.tkip.tx.iv32 = seq->tkip.iv32;
-               key->u.tkip.tx.iv16 = seq->tkip.iv16;
-               break;
-       case WLAN_CIPHER_SUITE_CCMP:
-       case WLAN_CIPHER_SUITE_CCMP_256:
-       case WLAN_CIPHER_SUITE_AES_CMAC:
-       case WLAN_CIPHER_SUITE_BIP_CMAC_256:
-               BUILD_BUG_ON(offsetof(typeof(*seq), ccmp) !=
-                            offsetof(typeof(*seq), aes_cmac));
-       case WLAN_CIPHER_SUITE_BIP_GMAC_128:
-       case WLAN_CIPHER_SUITE_BIP_GMAC_256:
-               BUILD_BUG_ON(offsetof(typeof(*seq), ccmp) !=
-                            offsetof(typeof(*seq), aes_gmac));
-       case WLAN_CIPHER_SUITE_GCMP:
-       case WLAN_CIPHER_SUITE_GCMP_256:
-               BUILD_BUG_ON(offsetof(typeof(*seq), ccmp) !=
-                            offsetof(typeof(*seq), gcmp));
-               pn64 = (u64)seq->ccmp.pn[5] |
-                      ((u64)seq->ccmp.pn[4] << 8) |
-                      ((u64)seq->ccmp.pn[3] << 16) |
-                      ((u64)seq->ccmp.pn[2] << 24) |
-                      ((u64)seq->ccmp.pn[1] << 32) |
-                      ((u64)seq->ccmp.pn[0] << 40);
-               atomic64_set(&key->conf.tx_pn, pn64);
-               break;
-       default:
-               WARN_ON(1);
-               break;
-       }
-}
-EXPORT_SYMBOL_GPL(ieee80211_set_key_tx_seq);
-
 void ieee80211_set_key_rx_seq(struct ieee80211_key_conf *keyconf,
                              int tid, struct ieee80211_key_seq *seq)
 {
index 9951ef06323e743d2c33156d15e5a21478584cd9..4aa20cef08595955702cd0aa5746d2dde1e56647 100644 (file)
@@ -44,13 +44,17 @@ enum ieee80211_internal_tkip_state {
 };
 
 struct tkip_ctx {
-       u32 iv32;       /* current iv32 */
-       u16 iv16;       /* current iv16 */
        u16 p1k[5];     /* p1k cache */
        u32 p1k_iv32;   /* iv32 for which p1k computed */
        enum ieee80211_internal_tkip_state state;
 };
 
+struct tkip_ctx_rx {
+       struct tkip_ctx ctx;
+       u32 iv32;       /* current iv32 */
+       u16 iv16;       /* current iv16 */
+};
+
 struct ieee80211_key {
        struct ieee80211_local *local;
        struct ieee80211_sub_if_data *sdata;
@@ -71,7 +75,7 @@ struct ieee80211_key {
                        struct tkip_ctx tx;
 
                        /* last received RSC */
-                       struct tkip_ctx rx[IEEE80211_NUM_TIDS];
+                       struct tkip_ctx_rx rx[IEEE80211_NUM_TIDS];
 
                        /* number of mic failures */
                        u32 mic_failures;
index fa28500f28fd9fd8d452602b0407741589f12e36..9a8e7b57c86efbb6f9304c4075bfda34be028871 100644 (file)
@@ -91,11 +91,10 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
        if (sdata->vif.bss_conf.basic_rates != basic_rates)
                return false;
 
-       ieee80211_ht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan,
-                                    ie->ht_operation, &sta_chan_def);
-
-       ieee80211_vht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan,
-                                     ie->vht_operation, &sta_chan_def);
+       cfg80211_chandef_create(&sta_chan_def, sdata->vif.bss_conf.chandef.chan,
+                               NL80211_CHAN_NO_HT);
+       ieee80211_chandef_ht_oper(ie->ht_operation, &sta_chan_def);
+       ieee80211_chandef_vht_oper(ie->vht_operation, &sta_chan_def);
 
        if (!cfg80211_chandef_compatible(&sdata->vif.bss_conf.chandef,
                                         &sta_chan_def))
index a1596344c3ba1c5fe590767f3c0483310d63121a..d941f3a73a4f9f9a8632c9869a3a1c95d303e80d 100644 (file)
@@ -137,8 +137,6 @@ struct mesh_path {
  * @copy_node: function to copy nodes of the table
  * @size_order: determines size of the table, there will be 2^size_order hash
  *     buckets
- * @mean_chain_len: maximum average length for the hash buckets' list, if it is
- *     reached, the table will grow
  * @known_gates: list of known mesh gates and their mpaths by the station. The
  * gate's mpath may or may not be resolved and active.
  *
@@ -154,7 +152,6 @@ struct mesh_table {
        void (*free_node) (struct hlist_node *p, bool free_leafs);
        int (*copy_node) (struct hlist_node *p, struct mesh_table *newtbl);
        int size_order;
-       int mean_chain_len;
        struct hlist_head *known_gates;
        spinlock_t gates_lock;
 
index dadf8dc6f1cfdceb762cabcf057e2e485ad853e8..2ba7aa56b11c0ec121d7851665c989e1a2b3b2d1 100644 (file)
@@ -55,16 +55,21 @@ int mpp_paths_generation;
 static DEFINE_RWLOCK(pathtbl_resize_lock);
 
 
+static inline struct mesh_table *resize_dereference_paths(
+       struct mesh_table __rcu *table)
+{
+       return rcu_dereference_protected(table,
+                                       lockdep_is_held(&pathtbl_resize_lock));
+}
+
 static inline struct mesh_table *resize_dereference_mesh_paths(void)
 {
-       return rcu_dereference_protected(mesh_paths,
-               lockdep_is_held(&pathtbl_resize_lock));
+       return resize_dereference_paths(mesh_paths);
 }
 
 static inline struct mesh_table *resize_dereference_mpp_paths(void)
 {
-       return rcu_dereference_protected(mpp_paths,
-               lockdep_is_held(&pathtbl_resize_lock));
+       return resize_dereference_paths(mpp_paths);
 }
 
 /*
@@ -160,11 +165,10 @@ static int mesh_table_grow(struct mesh_table *oldtbl,
        int i;
 
        if (atomic_read(&oldtbl->entries)
-                       < oldtbl->mean_chain_len * (oldtbl->hash_mask + 1))
+                       < MEAN_CHAIN_LEN * (oldtbl->hash_mask + 1))
                return -EAGAIN;
 
        newtbl->free_node = oldtbl->free_node;
-       newtbl->mean_chain_len = oldtbl->mean_chain_len;
        newtbl->copy_node = oldtbl->copy_node;
        newtbl->known_gates = oldtbl->known_gates;
        atomic_set(&newtbl->entries, atomic_read(&oldtbl->entries));
@@ -585,7 +589,7 @@ struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata,
 
        hlist_add_head_rcu(&new_node->list, bucket);
        if (atomic_inc_return(&tbl->entries) >=
-           tbl->mean_chain_len * (tbl->hash_mask + 1))
+           MEAN_CHAIN_LEN * (tbl->hash_mask + 1))
                grow = 1;
 
        mesh_paths_generation++;
@@ -714,7 +718,7 @@ int mpp_path_add(struct ieee80211_sub_if_data *sdata,
 
        hlist_add_head_rcu(&new_node->list, bucket);
        if (atomic_inc_return(&tbl->entries) >=
-           tbl->mean_chain_len * (tbl->hash_mask + 1))
+           MEAN_CHAIN_LEN * (tbl->hash_mask + 1))
                grow = 1;
 
        spin_unlock(&tbl->hashwlock[hash_idx]);
@@ -835,6 +839,29 @@ void mesh_path_flush_by_nexthop(struct sta_info *sta)
        rcu_read_unlock();
 }
 
+static void mpp_flush_by_proxy(struct ieee80211_sub_if_data *sdata,
+                              const u8 *proxy)
+{
+       struct mesh_table *tbl;
+       struct mesh_path *mpp;
+       struct mpath_node *node;
+       int i;
+
+       rcu_read_lock();
+       read_lock_bh(&pathtbl_resize_lock);
+       tbl = resize_dereference_mpp_paths();
+       for_each_mesh_entry(tbl, node, i) {
+               mpp = node->mpath;
+               if (ether_addr_equal(mpp->mpp, proxy)) {
+                       spin_lock(&tbl->hashwlock[i]);
+                       __mesh_path_del(tbl, node);
+                       spin_unlock(&tbl->hashwlock[i]);
+               }
+       }
+       read_unlock_bh(&pathtbl_resize_lock);
+       rcu_read_unlock();
+}
+
 static void table_flush_by_iface(struct mesh_table *tbl,
                                 struct ieee80211_sub_if_data *sdata)
 {
@@ -876,14 +903,17 @@ void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata)
 }
 
 /**
- * mesh_path_del - delete a mesh path from the table
+ * table_path_del - delete a path from the mesh or mpp table
  *
- * @addr: dst address (ETH_ALEN length)
+ * @tbl: mesh or mpp path table
  * @sdata: local subif
+ * @addr: dst address (ETH_ALEN length)
  *
  * Returns: 0 if successful
  */
-int mesh_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr)
+static int table_path_del(struct mesh_table __rcu *rcu_tbl,
+                         struct ieee80211_sub_if_data *sdata,
+                         const u8 *addr)
 {
        struct mesh_table *tbl;
        struct mesh_path *mpath;
@@ -892,8 +922,7 @@ int mesh_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr)
        int hash_idx;
        int err = 0;
 
-       read_lock_bh(&pathtbl_resize_lock);
-       tbl = resize_dereference_mesh_paths();
+       tbl = resize_dereference_paths(rcu_tbl);
        hash_idx = mesh_table_hash(addr, sdata, tbl);
        bucket = &tbl->hash_buckets[hash_idx];
 
@@ -909,9 +938,50 @@ int mesh_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr)
 
        err = -ENXIO;
 enddel:
-       mesh_paths_generation++;
        spin_unlock(&tbl->hashwlock[hash_idx]);
+       return err;
+}
+
+/**
+ * mesh_path_del - delete a mesh path from the table
+ *
+ * @addr: dst address (ETH_ALEN length)
+ * @sdata: local subif
+ *
+ * Returns: 0 if successful
+ */
+int mesh_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr)
+{
+       int err = 0;
+
+       /* flush relevant mpp entries first */
+       mpp_flush_by_proxy(sdata, addr);
+
+       read_lock_bh(&pathtbl_resize_lock);
+       err = table_path_del(mesh_paths, sdata, addr);
+       mesh_paths_generation++;
        read_unlock_bh(&pathtbl_resize_lock);
+
+       return err;
+}
+
+/**
+ * mpp_path_del - delete a mesh proxy path from the table
+ *
+ * @addr: addr address (ETH_ALEN length)
+ * @sdata: local subif
+ *
+ * Returns: 0 if successful
+ */
+static int mpp_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr)
+{
+       int err = 0;
+
+       read_lock_bh(&pathtbl_resize_lock);
+       err = table_path_del(mpp_paths, sdata, addr);
+       mpp_paths_generation++;
+       read_unlock_bh(&pathtbl_resize_lock);
+
        return err;
 }
 
@@ -1076,7 +1146,6 @@ int mesh_pathtbl_init(void)
                return -ENOMEM;
        tbl_path->free_node = &mesh_path_node_free;
        tbl_path->copy_node = &mesh_path_node_copy;
-       tbl_path->mean_chain_len = MEAN_CHAIN_LEN;
        tbl_path->known_gates = kzalloc(sizeof(struct hlist_head), GFP_ATOMIC);
        if (!tbl_path->known_gates) {
                ret = -ENOMEM;
@@ -1092,7 +1161,6 @@ int mesh_pathtbl_init(void)
        }
        tbl_mpp->free_node = &mesh_path_node_free;
        tbl_mpp->copy_node = &mesh_path_node_copy;
-       tbl_mpp->mean_chain_len = MEAN_CHAIN_LEN;
        tbl_mpp->known_gates = kzalloc(sizeof(struct hlist_head), GFP_ATOMIC);
        if (!tbl_mpp->known_gates) {
                ret = -ENOMEM;
@@ -1131,6 +1199,17 @@ void mesh_path_expire(struct ieee80211_sub_if_data *sdata)
                     time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE))
                        mesh_path_del(mpath->sdata, mpath->dst);
        }
+
+       tbl = rcu_dereference(mpp_paths);
+       for_each_mesh_entry(tbl, node, i) {
+               if (node->mpath->sdata != sdata)
+                       continue;
+               mpath = node->mpath;
+               if ((!(mpath->flags & MESH_PATH_FIXED)) &&
+                   time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE))
+                       mpp_path_del(mpath->sdata, mpath->dst);
+       }
+
        rcu_read_unlock();
 }
 
index bd3d55eb21d4f8fb5d4cf7a0da75a506ecdf00eb..a07e93c21c9ede90bd94328f1e4aaa51476d58bd 100644 (file)
@@ -976,6 +976,10 @@ mesh_plink_get_event(struct ieee80211_sub_if_data *sdata,
                        mpl_dbg(sdata, "Mesh plink error: no more free plinks\n");
                        goto out;
                }
+
+               /* new matching peer */
+               event = OPN_ACPT;
+               goto out;
        } else {
                if (!test_sta_flag(sta, WLAN_STA_AUTH)) {
                        mpl_dbg(sdata, "Mesh plink: Action frame from non-authed peer\n");
@@ -985,12 +989,6 @@ mesh_plink_get_event(struct ieee80211_sub_if_data *sdata,
                        goto out;
        }
 
-       /* new matching peer */
-       if (!sta) {
-               event = OPN_ACPT;
-               goto out;
-       }
-
        switch (ftype) {
        case WLAN_SP_MESH_PEERING_OPEN:
                if (!matches_local)
index 1c342e2592c4ab8af62871a4e44da0f3029140b0..f41625bcd87905d679e6b09dc8b11113e9b07550 100644 (file)
@@ -6,7 +6,7 @@
  * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
  * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
- * Copyright (C) 2015 Intel Deutschland GmbH
+ * Copyright (C) 2015 - 2016 Intel Deutschland GmbH
  *
  * 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
@@ -196,16 +196,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
 
        /* check 40 MHz support, if we have it */
        if (sta_ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
-               switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
-               case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
-                       chandef->width = NL80211_CHAN_WIDTH_40;
-                       chandef->center_freq1 += 10;
-                       break;
-               case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
-                       chandef->width = NL80211_CHAN_WIDTH_40;
-                       chandef->center_freq1 -= 10;
-                       break;
-               }
+               ieee80211_chandef_ht_oper(ht_oper, chandef);
        } else {
                /* 40 MHz (and 80 MHz) must be supported for VHT */
                ret = IEEE80211_STA_DISABLE_VHT;
@@ -219,35 +210,11 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
                goto out;
        }
 
-       vht_chandef.chan = channel;
-       vht_chandef.center_freq1 =
-               ieee80211_channel_to_frequency(vht_oper->center_freq_seg1_idx,
-                                              channel->band);
-       vht_chandef.center_freq2 = 0;
-
-       switch (vht_oper->chan_width) {
-       case IEEE80211_VHT_CHANWIDTH_USE_HT:
-               vht_chandef.width = chandef->width;
-               vht_chandef.center_freq1 = chandef->center_freq1;
-               break;
-       case IEEE80211_VHT_CHANWIDTH_80MHZ:
-               vht_chandef.width = NL80211_CHAN_WIDTH_80;
-               break;
-       case IEEE80211_VHT_CHANWIDTH_160MHZ:
-               vht_chandef.width = NL80211_CHAN_WIDTH_160;
-               break;
-       case IEEE80211_VHT_CHANWIDTH_80P80MHZ:
-               vht_chandef.width = NL80211_CHAN_WIDTH_80P80;
-               vht_chandef.center_freq2 =
-                       ieee80211_channel_to_frequency(
-                               vht_oper->center_freq_seg2_idx,
-                               channel->band);
-               break;
-       default:
+       vht_chandef = *chandef;
+       if (!ieee80211_chandef_vht_oper(vht_oper, &vht_chandef)) {
                if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
                        sdata_info(sdata,
-                                  "AP VHT operation IE has invalid channel width (%d), disable VHT\n",
-                                  vht_oper->chan_width);
+                                  "AP VHT information is invalid, disable VHT\n");
                ret = IEEE80211_STA_DISABLE_VHT;
                goto out;
        }
@@ -592,7 +559,7 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
                struct ieee80211_sub_if_data *other;
 
                list_for_each_entry_rcu(other, &local->interfaces, list) {
-                       if (other->flags & IEEE80211_SDATA_MU_MIMO_OWNER) {
+                       if (other->vif.mu_mimo_owner) {
                                disable_mu_mimo = true;
                                break;
                        }
@@ -600,7 +567,7 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
                if (disable_mu_mimo)
                        cap &= ~IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
                else
-                       sdata->flags |= IEEE80211_SDATA_MU_MIMO_OWNER;
+                       sdata->vif.mu_mimo_owner = true;
        }
 
        mask = IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK;
@@ -1638,8 +1605,7 @@ void ieee80211_dynamic_ps_timer(unsigned long data)
 
 void ieee80211_dfs_cac_timer_work(struct work_struct *work)
 {
-       struct delayed_work *delayed_work =
-               container_of(work, struct delayed_work, work);
+       struct delayed_work *delayed_work = to_delayed_work(work);
        struct ieee80211_sub_if_data *sdata =
                container_of(delayed_work, struct ieee80211_sub_if_data,
                             dfs_cac_timer_work);
@@ -2079,7 +2045,14 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
        memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask));
        memset(&ifmgd->vht_capa, 0, sizeof(ifmgd->vht_capa));
        memset(&ifmgd->vht_capa_mask, 0, sizeof(ifmgd->vht_capa_mask));
-       sdata->flags &= ~IEEE80211_SDATA_MU_MIMO_OWNER;
+
+       /* reset MU-MIMO ownership and group data */
+       memset(sdata->vif.bss_conf.mu_group.membership, 0,
+              sizeof(sdata->vif.bss_conf.mu_group.membership));
+       memset(sdata->vif.bss_conf.mu_group.position, 0,
+              sizeof(sdata->vif.bss_conf.mu_group.position));
+       changed |= BSS_CHANGED_MU_GROUPS;
+       sdata->vif.mu_mimo_owner = false;
 
        sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL;
 
@@ -2536,7 +2509,8 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
                eth_zero_addr(sdata->u.mgd.bssid);
                ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
                sdata->u.mgd.flags = 0;
-               sdata->flags &= ~IEEE80211_SDATA_MU_MIMO_OWNER;
+               sdata->vif.mu_mimo_owner = false;
+
                mutex_lock(&sdata->local->mtx);
                ieee80211_vif_release_channel(sdata);
                mutex_unlock(&sdata->local->mtx);
@@ -3571,6 +3545,9 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
                                elems.ht_cap_elem, elems.ht_operation,
                                elems.vht_operation, bssid, &changed)) {
                mutex_unlock(&local->sta_mtx);
+               sdata_info(sdata,
+                          "failed to follow AP %pM bandwidth change, disconnect\n",
+                          bssid);
                ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
                                       WLAN_REASON_DEAUTH_LEAVING,
                                       true, deauth_buf);
@@ -3946,11 +3923,9 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
                         * We actually lost the connection ... or did we?
                         * Let's make sure!
                         */
-                       wiphy_debug(local->hw.wiphy,
-                                   "%s: No probe response from AP %pM"
-                                   " after %dms, disconnecting.\n",
-                                   sdata->name,
-                                   bssid, probe_wait_ms);
+                       mlme_dbg(sdata,
+                                "No probe response from AP %pM after %dms, disconnecting.\n",
+                                bssid, probe_wait_ms);
 
                        ieee80211_sta_connection_lost(sdata, bssid,
                                WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, false);
@@ -4538,6 +4513,9 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
        if (ifmgd->associated) {
                u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
 
+               sdata_info(sdata,
+                          "disconnect from AP %pM for new auth to %pM\n",
+                          ifmgd->associated->bssid, req->bss->bssid);
                ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
                                       WLAN_REASON_UNSPECIFIED,
                                       false, frame_buf);
@@ -4606,6 +4584,9 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
        if (ifmgd->associated) {
                u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
 
+               sdata_info(sdata,
+                          "disconnect from AP %pM for new assoc to %pM\n",
+                          ifmgd->associated->bssid, req->bss->bssid);
                ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
                                       WLAN_REASON_UNSPECIFIED,
                                       false, frame_buf);
index bc081850ac0e5538241bd1cab37b65aeefd2c244..91279576f4a716d00cfd810e5d6db18306520c1c 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
  * Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
+ * Copyright(c) 2015 - 2016 Intel Deutschland GmbH
  *
  * 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
@@ -18,6 +19,7 @@
 #include <linux/etherdevice.h>
 #include <linux/rcupdate.h>
 #include <linux/export.h>
+#include <linux/bitops.h>
 #include <net/mac80211.h>
 #include <net/ieee80211_radiotap.h>
 #include <asm/unaligned.h>
@@ -122,7 +124,8 @@ static inline bool should_drop_frame(struct sk_buff *skb, int present_fcs_len,
        hdr = (void *)(skb->data + rtap_vendor_space);
 
        if (status->flag & (RX_FLAG_FAILED_FCS_CRC |
-                           RX_FLAG_FAILED_PLCP_CRC))
+                           RX_FLAG_FAILED_PLCP_CRC |
+                           RX_FLAG_ONLY_MONITOR))
                return true;
 
        if (unlikely(skb->len < 16 + present_fcs_len + rtap_vendor_space))
@@ -507,7 +510,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
                return NULL;
        }
 
-       if (!local->monitors) {
+       if (!local->monitors || (status->flag & RX_FLAG_SKIP_MONITOR)) {
                if (should_drop_frame(origskb, present_fcs_len,
                                      rtap_vendor_space)) {
                        dev_kfree_skb(origskb);
@@ -797,6 +800,26 @@ static ieee80211_rx_result ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
        return RX_CONTINUE;
 }
 
+static inline bool ieee80211_rx_reorder_ready(struct tid_ampdu_rx *tid_agg_rx,
+                                             int index)
+{
+       struct sk_buff_head *frames = &tid_agg_rx->reorder_buf[index];
+       struct sk_buff *tail = skb_peek_tail(frames);
+       struct ieee80211_rx_status *status;
+
+       if (tid_agg_rx->reorder_buf_filtered & BIT_ULL(index))
+               return true;
+
+       if (!tail)
+               return false;
+
+       status = IEEE80211_SKB_RXCB(tail);
+       if (status->flag & RX_FLAG_AMSDU_MORE)
+               return false;
+
+       return true;
+}
+
 static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata,
                                            struct tid_ampdu_rx *tid_agg_rx,
                                            int index,
@@ -811,7 +834,7 @@ static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata,
        if (skb_queue_empty(skb_list))
                goto no_frame;
 
-       if (!ieee80211_rx_reorder_ready(skb_list)) {
+       if (!ieee80211_rx_reorder_ready(tid_agg_rx, index)) {
                __skb_queue_purge(skb_list);
                goto no_frame;
        }
@@ -825,6 +848,7 @@ static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata,
        }
 
 no_frame:
+       tid_agg_rx->reorder_buf_filtered &= ~BIT_ULL(index);
        tid_agg_rx->head_seq_num = ieee80211_sn_inc(tid_agg_rx->head_seq_num);
 }
 
@@ -865,7 +889,7 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata,
 
        /* release the buffer until next missing frame */
        index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size;
-       if (!ieee80211_rx_reorder_ready(&tid_agg_rx->reorder_buf[index]) &&
+       if (!ieee80211_rx_reorder_ready(tid_agg_rx, index) &&
            tid_agg_rx->stored_mpdu_num) {
                /*
                 * No buffers ready to be released, but check whether any
@@ -874,8 +898,7 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata,
                int skipped = 1;
                for (j = (index + 1) % tid_agg_rx->buf_size; j != index;
                     j = (j + 1) % tid_agg_rx->buf_size) {
-                       if (!ieee80211_rx_reorder_ready(
-                                       &tid_agg_rx->reorder_buf[j])) {
+                       if (!ieee80211_rx_reorder_ready(tid_agg_rx, j)) {
                                skipped++;
                                continue;
                        }
@@ -902,8 +925,7 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata,
                                 skipped) & IEEE80211_SN_MASK;
                        skipped = 0;
                }
-       } else while (ieee80211_rx_reorder_ready(
-                               &tid_agg_rx->reorder_buf[index])) {
+       } else while (ieee80211_rx_reorder_ready(tid_agg_rx, index)) {
                ieee80211_release_reorder_frame(sdata, tid_agg_rx, index,
                                                frames);
                index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size;
@@ -914,8 +936,7 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata,
 
                for (; j != (index - 1) % tid_agg_rx->buf_size;
                     j = (j + 1) % tid_agg_rx->buf_size) {
-                       if (ieee80211_rx_reorder_ready(
-                                       &tid_agg_rx->reorder_buf[j]))
+                       if (ieee80211_rx_reorder_ready(tid_agg_rx, j))
                                break;
                }
 
@@ -986,7 +1007,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata
        index = mpdu_seq_num % tid_agg_rx->buf_size;
 
        /* check if we already stored this frame */
-       if (ieee80211_rx_reorder_ready(&tid_agg_rx->reorder_buf[index])) {
+       if (ieee80211_rx_reorder_ready(tid_agg_rx, index)) {
                dev_kfree_skb(skb);
                goto out;
        }
@@ -1099,6 +1120,9 @@ ieee80211_rx_h_check_dup(struct ieee80211_rx_data *rx)
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
        struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
 
+       if (status->flag & RX_FLAG_DUP_VALIDATED)
+               return RX_CONTINUE;
+
        /*
         * Drop duplicate 802.11 retransmissions
         * (IEEE 802.11-2012: 9.3.2.10 "Duplicate detection and recovery")
@@ -2199,9 +2223,6 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
        skb->dev = dev;
        __skb_queue_head_init(&frame_list);
 
-       if (skb_linearize(skb))
-               return RX_DROP_UNUSABLE;
-
        ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr,
                                 rx->sdata->vif.type,
                                 rx->local->hw.extra_tx_headroom, true);
@@ -2231,7 +2252,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
        struct ieee80211_local *local = rx->local;
        struct ieee80211_sub_if_data *sdata = rx->sdata;
        struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
-       u16 q, hdrlen;
+       u16 ac, q, hdrlen;
 
        hdr = (struct ieee80211_hdr *) skb->data;
        hdrlen = ieee80211_hdrlen(hdr->frame_control);
@@ -2290,6 +2311,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
                        spin_lock_bh(&mppath->state_lock);
                        if (!ether_addr_equal(mppath->mpp, mpp_addr))
                                memcpy(mppath->mpp, mpp_addr, ETH_ALEN);
+                       mppath->exp_time = jiffies;
                        spin_unlock_bh(&mppath->state_lock);
                }
                rcu_read_unlock();
@@ -2300,7 +2322,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
            ether_addr_equal(sdata->vif.addr, hdr->addr3))
                return RX_CONTINUE;
 
-       q = ieee80211_select_queue_80211(sdata, skb, hdr);
+       ac = ieee80211_select_queue_80211(sdata, skb, hdr);
+       q = sdata->vif.hw_queue[ac];
        if (ieee80211_queue_stopped(&local->hw, q)) {
                IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_congestion);
                return RX_DROP_MONITOR;
@@ -2738,6 +2761,11 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
                                                    opmode, status->band);
                        goto handled;
                }
+               case WLAN_VHT_ACTION_GROUPID_MGMT: {
+                       if (len < IEEE80211_MIN_ACTION_SIZE + 25)
+                               goto invalid;
+                       goto queue;
+               }
                default:
                        break;
                }
@@ -3275,6 +3303,85 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid)
        ieee80211_rx_handlers(&rx, &frames);
 }
 
+void ieee80211_mark_rx_ba_filtered_frames(struct ieee80211_sta *pubsta, u8 tid,
+                                         u16 ssn, u64 filtered,
+                                         u16 received_mpdus)
+{
+       struct sta_info *sta;
+       struct tid_ampdu_rx *tid_agg_rx;
+       struct sk_buff_head frames;
+       struct ieee80211_rx_data rx = {
+               /* This is OK -- must be QoS data frame */
+               .security_idx = tid,
+               .seqno_idx = tid,
+       };
+       int i, diff;
+
+       if (WARN_ON(!pubsta || tid >= IEEE80211_NUM_TIDS))
+               return;
+
+       __skb_queue_head_init(&frames);
+
+       sta = container_of(pubsta, struct sta_info, sta);
+
+       rx.sta = sta;
+       rx.sdata = sta->sdata;
+       rx.local = sta->local;
+
+       rcu_read_lock();
+       tid_agg_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]);
+       if (!tid_agg_rx)
+               goto out;
+
+       spin_lock_bh(&tid_agg_rx->reorder_lock);
+
+       if (received_mpdus >= IEEE80211_SN_MODULO >> 1) {
+               int release;
+
+               /* release all frames in the reorder buffer */
+               release = (tid_agg_rx->head_seq_num + tid_agg_rx->buf_size) %
+                          IEEE80211_SN_MODULO;
+               ieee80211_release_reorder_frames(sta->sdata, tid_agg_rx,
+                                                release, &frames);
+               /* update ssn to match received ssn */
+               tid_agg_rx->head_seq_num = ssn;
+       } else {
+               ieee80211_release_reorder_frames(sta->sdata, tid_agg_rx, ssn,
+                                                &frames);
+       }
+
+       /* handle the case that received ssn is behind the mac ssn.
+        * it can be tid_agg_rx->buf_size behind and still be valid */
+       diff = (tid_agg_rx->head_seq_num - ssn) & IEEE80211_SN_MASK;
+       if (diff >= tid_agg_rx->buf_size) {
+               tid_agg_rx->reorder_buf_filtered = 0;
+               goto release;
+       }
+       filtered = filtered >> diff;
+       ssn += diff;
+
+       /* update bitmap */
+       for (i = 0; i < tid_agg_rx->buf_size; i++) {
+               int index = (ssn + i) % tid_agg_rx->buf_size;
+
+               tid_agg_rx->reorder_buf_filtered &= ~BIT_ULL(index);
+               if (filtered & BIT_ULL(i))
+                       tid_agg_rx->reorder_buf_filtered |= BIT_ULL(index);
+       }
+
+       /* now process also frames that the filter marking released */
+       ieee80211_sta_reorder_release(sta->sdata, tid_agg_rx, &frames);
+
+release:
+       spin_unlock_bh(&tid_agg_rx->reorder_lock);
+
+       ieee80211_rx_handlers(&rx, &frames);
+
+ out:
+       rcu_read_unlock();
+}
+EXPORT_SYMBOL(ieee80211_mark_rx_ba_filtered_frames);
+
 /* main receive path */
 
 static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx)
index 4402ad5b27d1530bf4cc9a0d674c6538f73cb568..87b7e7a7df6cc22a8aced080e86c765308ca9a0b 100644 (file)
@@ -116,6 +116,7 @@ static void __cleanup_single_sta(struct sta_info *sta)
 
                        ieee80211_purge_tx_queue(&local->hw, &txqi->queue);
                        atomic_sub(n, &sdata->txqs_len[txqi->txq.ac]);
+                       txqi->byte_cnt = 0;
                }
        }
 
@@ -498,11 +499,17 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
 {
        struct ieee80211_local *local = sta->local;
        struct ieee80211_sub_if_data *sdata = sta->sdata;
-       struct station_info sinfo;
+       struct station_info *sinfo;
        int err = 0;
 
        lockdep_assert_held(&local->sta_mtx);
 
+       sinfo = kzalloc(sizeof(struct station_info), GFP_KERNEL);
+       if (!sinfo) {
+               err = -ENOMEM;
+               goto out_err;
+       }
+
        /* check if STA exists already */
        if (sta_info_get_bss(sdata, sta->sta.addr)) {
                err = -EEXIST;
@@ -530,14 +537,12 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
        /* accept BA sessions now */
        clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
 
-       ieee80211_recalc_min_chandef(sdata);
        ieee80211_sta_debugfs_add(sta);
        rate_control_add_sta_debugfs(sta);
 
-       memset(&sinfo, 0, sizeof(sinfo));
-       sinfo.filled = 0;
-       sinfo.generation = local->sta_generation;
-       cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL);
+       sinfo->generation = local->sta_generation;
+       cfg80211_new_sta(sdata->dev, sta->sta.addr, sinfo, GFP_KERNEL);
+       kfree(sinfo);
 
        sta_dbg(sdata, "Inserted STA %pM\n", sta->sta.addr);
 
@@ -557,6 +562,7 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
        __cleanup_single_sta(sta);
  out_err:
        mutex_unlock(&local->sta_mtx);
+       kfree(sinfo);
        rcu_read_lock();
        return err;
 }
@@ -898,7 +904,7 @@ static void __sta_info_destroy_part2(struct sta_info *sta)
 {
        struct ieee80211_local *local = sta->local;
        struct ieee80211_sub_if_data *sdata = sta->sdata;
-       struct station_info sinfo = {};
+       struct station_info *sinfo;
        int ret;
 
        /*
@@ -936,12 +942,14 @@ static void __sta_info_destroy_part2(struct sta_info *sta)
 
        sta_dbg(sdata, "Removed STA %pM\n", sta->sta.addr);
 
-       sta_set_sinfo(sta, &sinfo);
-       cfg80211_del_sta_sinfo(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL);
+       sinfo = kzalloc(sizeof(*sinfo), GFP_KERNEL);
+       if (sinfo)
+               sta_set_sinfo(sta, sinfo);
+       cfg80211_del_sta_sinfo(sdata->dev, sta->sta.addr, sinfo, GFP_KERNEL);
+       kfree(sinfo);
 
        rate_control_remove_sta_debugfs(sta);
        ieee80211_sta_debugfs_remove(sta);
-       ieee80211_recalc_min_chandef(sdata);
 
        cleanup_single_sta(sta);
 }
@@ -1808,14 +1816,17 @@ int sta_info_move_state(struct sta_info *sta,
                        clear_bit(WLAN_STA_AUTH, &sta->_flags);
                break;
        case IEEE80211_STA_AUTH:
-               if (sta->sta_state == IEEE80211_STA_NONE)
+               if (sta->sta_state == IEEE80211_STA_NONE) {
                        set_bit(WLAN_STA_AUTH, &sta->_flags);
-               else if (sta->sta_state == IEEE80211_STA_ASSOC)
+               } else if (sta->sta_state == IEEE80211_STA_ASSOC) {
                        clear_bit(WLAN_STA_ASSOC, &sta->_flags);
+                       ieee80211_recalc_min_chandef(sta->sdata);
+               }
                break;
        case IEEE80211_STA_ASSOC:
                if (sta->sta_state == IEEE80211_STA_AUTH) {
                        set_bit(WLAN_STA_ASSOC, &sta->_flags);
+                       ieee80211_recalc_min_chandef(sta->sdata);
                } else if (sta->sta_state == IEEE80211_STA_AUTHORIZED) {
                        if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
                            (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
index d6051629ed155859819a591960183c0062c230d9..053f5c4fa495ba02cd99c5ddb201ce0ad0f7aeff 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright 2002-2005, Devicescape Software, Inc.
  * Copyright 2013-2014  Intel Mobile Communications GmbH
+ * Copyright(c) 2015 Intel Deutschland GmbH
  *
  * 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
@@ -167,6 +168,8 @@ struct tid_ampdu_tx {
  *
  * @reorder_buf: buffer to reorder incoming aggregated MPDUs. An MPDU may be an
  *     A-MSDU with individually reported subframes.
+ * @reorder_buf_filtered: bitmap indicating where there are filtered frames in
+ *     the reorder buffer that should be ignored when releasing frames
  * @reorder_time: jiffies when skb was added
  * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value)
  * @reorder_timer: releases expired frames from the reorder buffer.
@@ -194,6 +197,7 @@ struct tid_ampdu_tx {
 struct tid_ampdu_rx {
        struct rcu_head rcu_head;
        spinlock_t reorder_lock;
+       u64 reorder_buf_filtered;
        struct sk_buff_head *reorder_buf;
        unsigned long *reorder_time;
        struct timer_list session_timer;
@@ -212,20 +216,21 @@ struct tid_ampdu_rx {
 /**
  * struct sta_ampdu_mlme - STA aggregation information.
  *
+ * @mtx: mutex to protect all TX data (except non-NULL assignments
+ *     to tid_tx[idx], which are protected by the sta spinlock)
+ *     tid_start_tx is also protected by sta->lock.
  * @tid_rx: aggregation info for Rx per TID -- RCU protected
- * @tid_tx: aggregation info for Tx per TID
- * @tid_start_tx: sessions where start was requested
- * @addba_req_num: number of times addBA request has been sent.
- * @last_addba_req_time: timestamp of the last addBA request.
- * @dialog_token_allocator: dialog token enumerator for each new session;
- * @work: work struct for starting/stopping aggregation
  * @tid_rx_timer_expired: bitmap indicating on which TIDs the
  *     RX timer expired until the work for it runs
  * @tid_rx_stop_requested:  bitmap indicating which BA sessions per TID the
  *     driver requested to close until the work for it runs
- * @mtx: mutex to protect all TX data (except non-NULL assignments
- *     to tid_tx[idx], which are protected by the sta spinlock)
- *     tid_start_tx is also protected by sta->lock.
+ * @agg_session_valid: bitmap indicating which TID has a rx BA session open on
+ * @work: work struct for starting/stopping aggregation
+ * @tid_tx: aggregation info for Tx per TID
+ * @tid_start_tx: sessions where start was requested
+ * @last_addba_req_time: timestamp of the last addBA request.
+ * @addba_req_num: number of times addBA request has been sent.
+ * @dialog_token_allocator: dialog token enumerator for each new session;
  */
 struct sta_ampdu_mlme {
        struct mutex mtx;
@@ -233,6 +238,7 @@ struct sta_ampdu_mlme {
        struct tid_ampdu_rx __rcu *tid_rx[IEEE80211_NUM_TIDS];
        unsigned long tid_rx_timer_expired[BITS_TO_LONGS(IEEE80211_NUM_TIDS)];
        unsigned long tid_rx_stop_requested[BITS_TO_LONGS(IEEE80211_NUM_TIDS)];
+       unsigned long agg_session_valid[BITS_TO_LONGS(IEEE80211_NUM_TIDS)];
        /* tx */
        struct work_struct work;
        struct tid_ampdu_tx __rcu *tid_tx[IEEE80211_NUM_TIDS];
index 0ae207771a5837ff73d359fe4032be26ac4ca358..b3622823bad23b9a34a58b09fea1dd3e067bbcf2 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright 2002-2004, Instant802 Networks, Inc.
  * Copyright 2005, Devicescape Software, Inc.
+ * Copyright (C) 2016 Intel Deutschland GmbH
  *
  * 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
@@ -142,15 +143,14 @@ static void tkip_mixing_phase2(const u8 *tk, struct tkip_ctx *ctx,
 /* Add TKIP IV and Ext. IV at @pos. @iv0, @iv1, and @iv2 are the first octets
  * of the IV. Returns pointer to the octet following IVs (i.e., beginning of
  * the packet payload). */
-u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key)
+u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key_conf *keyconf, u64 pn)
 {
-       lockdep_assert_held(&key->u.tkip.txlock);
-
-       pos = write_tkip_iv(pos, key->u.tkip.tx.iv16);
-       *pos++ = (key->conf.keyidx << 6) | (1 << 5) /* Ext IV */;
-       put_unaligned_le32(key->u.tkip.tx.iv32, pos);
+       pos = write_tkip_iv(pos, TKIP_PN_TO_IV16(pn));
+       *pos++ = (keyconf->keyidx << 6) | (1 << 5) /* Ext IV */;
+       put_unaligned_le32(TKIP_PN_TO_IV32(pn), pos);
        return pos + 4;
 }
+EXPORT_SYMBOL_GPL(ieee80211_tkip_add_iv);
 
 static void ieee80211_compute_tkip_p1k(struct ieee80211_key *key, u32 iv32)
 {
@@ -250,6 +250,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm,
        u8 rc4key[16], keyid, *pos = payload;
        int res;
        const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY];
+       struct tkip_ctx_rx *rx_ctx = &key->u.tkip.rx[queue];
 
        if (payload_len < 12)
                return -1;
@@ -265,37 +266,36 @@ int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm,
        if ((keyid >> 6) != key->conf.keyidx)
                return TKIP_DECRYPT_INVALID_KEYIDX;
 
-       if (key->u.tkip.rx[queue].state != TKIP_STATE_NOT_INIT &&
-           (iv32 < key->u.tkip.rx[queue].iv32 ||
-            (iv32 == key->u.tkip.rx[queue].iv32 &&
-             iv16 <= key->u.tkip.rx[queue].iv16)))
+       if (rx_ctx->ctx.state != TKIP_STATE_NOT_INIT &&
+           (iv32 < rx_ctx->iv32 ||
+            (iv32 == rx_ctx->iv32 && iv16 <= rx_ctx->iv16)))
                return TKIP_DECRYPT_REPLAY;
 
        if (only_iv) {
                res = TKIP_DECRYPT_OK;
-               key->u.tkip.rx[queue].state = TKIP_STATE_PHASE1_HW_UPLOADED;
+               rx_ctx->ctx.state = TKIP_STATE_PHASE1_HW_UPLOADED;
                goto done;
        }
 
-       if (key->u.tkip.rx[queue].state == TKIP_STATE_NOT_INIT ||
-           key->u.tkip.rx[queue].iv32 != iv32) {
+       if (rx_ctx->ctx.state == TKIP_STATE_NOT_INIT ||
+           rx_ctx->iv32 != iv32) {
                /* IV16 wrapped around - perform TKIP phase 1 */
-               tkip_mixing_phase1(tk, &key->u.tkip.rx[queue], ta, iv32);
+               tkip_mixing_phase1(tk, &rx_ctx->ctx, ta, iv32);
        }
        if (key->local->ops->update_tkip_key &&
            key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE &&
-           key->u.tkip.rx[queue].state != TKIP_STATE_PHASE1_HW_UPLOADED) {
+           rx_ctx->ctx.state != TKIP_STATE_PHASE1_HW_UPLOADED) {
                struct ieee80211_sub_if_data *sdata = key->sdata;
 
                if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
                        sdata = container_of(key->sdata->bss,
                                        struct ieee80211_sub_if_data, u.ap);
                drv_update_tkip_key(key->local, sdata, &key->conf, key->sta,
-                               iv32, key->u.tkip.rx[queue].p1k);
-               key->u.tkip.rx[queue].state = TKIP_STATE_PHASE1_HW_UPLOADED;
+                               iv32, rx_ctx->ctx.p1k);
+               rx_ctx->ctx.state = TKIP_STATE_PHASE1_HW_UPLOADED;
        }
 
-       tkip_mixing_phase2(tk, &key->u.tkip.rx[queue], iv16, rc4key);
+       tkip_mixing_phase2(tk, &rx_ctx->ctx, iv16, rc4key);
 
        res = ieee80211_wep_decrypt_data(tfm, rc4key, 16, pos, payload_len - 12);
  done:
index e3ecb659b90af6002966d74acdb05b05e3a0be4d..a1bcbfbefe7c32ca5e0fe6d080818acebb624b9b 100644 (file)
@@ -13,8 +13,6 @@
 #include <linux/crypto.h>
 #include "key.h"
 
-u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key);
-
 int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm,
                                struct ieee80211_key *key,
                                struct sk_buff *skb,
index a6b4442776a0519251b1a7650007343a3541181e..2b0a17ee907abff27d2fef4c93e8d2a03eda4c17 100644 (file)
 #define KEY_PR_FMT     " cipher:0x%x, flags=%#x, keyidx=%d, hw_key_idx=%d"
 #define KEY_PR_ARG     __entry->cipher, __entry->flags, __entry->keyidx, __entry->hw_key_idx
 
-
+#define AMPDU_ACTION_ENTRY     __field(enum ieee80211_ampdu_mlme_action,               \
+                                       ieee80211_ampdu_mlme_action)                    \
+                               STA_ENTRY                                               \
+                               __field(u16, tid)                                       \
+                               __field(u16, ssn)                                       \
+                               __field(u8, buf_size)                                   \
+                               __field(bool, amsdu)                                    \
+                               __field(u16, timeout)
+#define AMPDU_ACTION_ASSIGN    STA_NAMED_ASSIGN(params->sta);                          \
+                               __entry->tid = params->tid;                             \
+                               __entry->ssn = params->ssn;                             \
+                               __entry->buf_size = params->buf_size;                   \
+                               __entry->amsdu = params->amsdu;                         \
+                               __entry->timeout = params->timeout;
+#define AMPDU_ACTION_PR_FMT    STA_PR_FMT " tid %d, ssn %d, buf_size %u, amsdu %d, timeout %d"
+#define AMPDU_ACTION_PR_ARG    STA_PR_ARG, __entry->tid, __entry->ssn,                 \
+                               __entry->buf_size, __entry->amsdu, __entry->timeout
 
 /*
  * Tracing for driver callbacks.
@@ -970,38 +986,25 @@ DEFINE_EVENT(local_only_evt, drv_tx_last_beacon,
 TRACE_EVENT(drv_ampdu_action,
        TP_PROTO(struct ieee80211_local *local,
                 struct ieee80211_sub_if_data *sdata,
-                enum ieee80211_ampdu_mlme_action action,
-                struct ieee80211_sta *sta, u16 tid,
-                u16 *ssn, u8 buf_size, bool amsdu),
+                struct ieee80211_ampdu_params *params),
 
-       TP_ARGS(local, sdata, action, sta, tid, ssn, buf_size, amsdu),
+       TP_ARGS(local, sdata, params),
 
        TP_STRUCT__entry(
                LOCAL_ENTRY
-               STA_ENTRY
-               __field(u32, action)
-               __field(u16, tid)
-               __field(u16, ssn)
-               __field(u8, buf_size)
-               __field(bool, amsdu)
                VIF_ENTRY
+               AMPDU_ACTION_ENTRY
        ),
 
        TP_fast_assign(
                LOCAL_ASSIGN;
                VIF_ASSIGN;
-               STA_ASSIGN;
-               __entry->action = action;
-               __entry->tid = tid;
-               __entry->ssn = ssn ? *ssn : 0;
-               __entry->buf_size = buf_size;
-               __entry->amsdu = amsdu;
+               AMPDU_ACTION_ASSIGN;
        ),
 
        TP_printk(
-               LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " action:%d tid:%d buf:%d amsdu:%d",
-               LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action,
-               __entry->tid, __entry->buf_size, __entry->amsdu
+               LOCAL_PR_FMT VIF_PR_FMT AMPDU_ACTION_PR_FMT,
+               LOCAL_PR_ARG, VIF_PR_ARG, AMPDU_ACTION_PR_ARG
        )
 );
 
index 3311ce0f3d6c2f9c93c075458159935c631d144d..3a7475ff1a413c1dd7281af1c5483c64583aa9cd 100644 (file)
@@ -710,6 +710,10 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
 
        info->control.short_preamble = txrc.short_preamble;
 
+       /* don't ask rate control when rate already injected via radiotap */
+       if (info->control.flags & IEEE80211_TX_CTRL_RATE_INJECT)
+               return TX_CONTINUE;
+
        if (tx->sta)
                assoc = test_sta_flag(tx->sta, WLAN_STA_ASSOC);
 
@@ -1266,7 +1270,11 @@ static void ieee80211_drv_tx(struct ieee80211_local *local,
        if (atomic_read(&sdata->txqs_len[ac]) >= local->hw.txq_ac_max_pending)
                netif_stop_subqueue(sdata->dev, ac);
 
-       skb_queue_tail(&txqi->queue, skb);
+       spin_lock_bh(&txqi->queue.lock);
+       txqi->byte_cnt += skb->len;
+       __skb_queue_tail(&txqi->queue, skb);
+       spin_unlock_bh(&txqi->queue.lock);
+
        drv_wake_tx_queue(local, txqi);
 
        return;
@@ -1294,6 +1302,8 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
        if (!skb)
                goto out;
 
+       txqi->byte_cnt -= skb->len;
+
        atomic_dec(&sdata->txqs_len[ac]);
        if (__netif_subqueue_stopped(sdata->dev, ac))
                ieee80211_propagate_queue_wake(local, sdata->vif.hw_queue[ac]);
@@ -1665,15 +1675,24 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
        ieee80211_tx(sdata, sta, skb, false);
 }
 
-static bool ieee80211_parse_tx_radiotap(struct sk_buff *skb)
+static bool ieee80211_parse_tx_radiotap(struct ieee80211_local *local,
+                                       struct sk_buff *skb)
 {
        struct ieee80211_radiotap_iterator iterator;
        struct ieee80211_radiotap_header *rthdr =
                (struct ieee80211_radiotap_header *) skb->data;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_supported_band *sband =
+               local->hw.wiphy->bands[info->band];
        int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len,
                                                   NULL);
        u16 txflags;
+       u16 rate = 0;
+       bool rate_found = false;
+       u8 rate_retries = 0;
+       u16 rate_flags = 0;
+       u8 mcs_known, mcs_flags;
+       int i;
 
        info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
                       IEEE80211_TX_CTL_DONTFRAG;
@@ -1724,6 +1743,35 @@ static bool ieee80211_parse_tx_radiotap(struct sk_buff *skb)
                                info->flags |= IEEE80211_TX_CTL_NO_ACK;
                        break;
 
+               case IEEE80211_RADIOTAP_RATE:
+                       rate = *iterator.this_arg;
+                       rate_flags = 0;
+                       rate_found = true;
+                       break;
+
+               case IEEE80211_RADIOTAP_DATA_RETRIES:
+                       rate_retries = *iterator.this_arg;
+                       break;
+
+               case IEEE80211_RADIOTAP_MCS:
+                       mcs_known = iterator.this_arg[0];
+                       mcs_flags = iterator.this_arg[1];
+                       if (!(mcs_known & IEEE80211_RADIOTAP_MCS_HAVE_MCS))
+                               break;
+
+                       rate_found = true;
+                       rate = iterator.this_arg[2];
+                       rate_flags = IEEE80211_TX_RC_MCS;
+
+                       if (mcs_known & IEEE80211_RADIOTAP_MCS_HAVE_GI &&
+                           mcs_flags & IEEE80211_RADIOTAP_MCS_SGI)
+                               rate_flags |= IEEE80211_TX_RC_SHORT_GI;
+
+                       if (mcs_known & IEEE80211_RADIOTAP_MCS_HAVE_BW &&
+                           mcs_flags & IEEE80211_RADIOTAP_MCS_BW_40)
+                               rate_flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
+                       break;
+
                /*
                 * Please update the file
                 * Documentation/networking/mac80211-injection.txt
@@ -1738,6 +1786,32 @@ static bool ieee80211_parse_tx_radiotap(struct sk_buff *skb)
        if (ret != -ENOENT) /* ie, if we didn't simply run out of fields */
                return false;
 
+       if (rate_found) {
+               info->control.flags |= IEEE80211_TX_CTRL_RATE_INJECT;
+
+               for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
+                       info->control.rates[i].idx = -1;
+                       info->control.rates[i].flags = 0;
+                       info->control.rates[i].count = 0;
+               }
+
+               if (rate_flags & IEEE80211_TX_RC_MCS) {
+                       info->control.rates[0].idx = rate;
+               } else {
+                       for (i = 0; i < sband->n_bitrates; i++) {
+                               if (rate * 5 != sband->bitrates[i].bitrate)
+                                       continue;
+
+                               info->control.rates[0].idx = i;
+                               break;
+                       }
+               }
+
+               info->control.rates[0].flags = rate_flags;
+               info->control.rates[0].count = min_t(u8, rate_retries + 1,
+                                                    local->hw.max_rate_tries);
+       }
+
        /*
         * remove the radiotap header
         * iterator->_max_length was sanity-checked against
@@ -1818,10 +1892,6 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
        info->flags = IEEE80211_TX_CTL_REQ_TX_STATUS |
                      IEEE80211_TX_CTL_INJECTED;
 
-       /* process and remove the injection radiotap header */
-       if (!ieee80211_parse_tx_radiotap(skb))
-               goto fail;
-
        rcu_read_lock();
 
        /*
@@ -1883,6 +1953,11 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
                goto fail_rcu;
 
        info->band = chandef->chan->band;
+
+       /* process and remove the injection radiotap header */
+       if (!ieee80211_parse_tx_radiotap(local, skb))
+               goto fail_rcu;
+
        ieee80211_xmit(sdata, NULL, skb);
        rcu_read_unlock();
 
@@ -2099,8 +2174,11 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
                                        mpp_lookup = true;
                        }
 
-                       if (mpp_lookup)
+                       if (mpp_lookup) {
                                mppath = mpp_path_lookup(sdata, skb->data);
+                               if (mppath)
+                                       mppath->exp_time = jiffies;
+                       }
 
                        if (mppath && mpath)
                                mesh_path_del(mpath->sdata, mpath->dst);
index 3943d4bf289c29b436765d82dd0f241c8b7f5530..89f71799df841bdf5f107970e5617a77307257c8 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
  * Copyright 2007      Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
- * Copyright (C) 2015  Intel Deutschland GmbH
+ * Copyright (C) 2015-2016     Intel Deutschland GmbH
  *
  * 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
@@ -1928,6 +1928,9 @@ int ieee80211_reconfig(struct ieee80211_local *local)
                          BSS_CHANGED_IDLE |
                          BSS_CHANGED_TXPOWER;
 
+               if (sdata->vif.mu_mimo_owner)
+                       changed |= BSS_CHANGED_MU_GROUPS;
+
                switch (sdata->vif.type) {
                case NL80211_IFTYPE_STATION:
                        changed |= BSS_CHANGED_ASSOC |
@@ -2361,10 +2364,23 @@ u8 *ieee80211_ie_build_vht_oper(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
 
        switch (chandef->width) {
        case NL80211_CHAN_WIDTH_160:
-               vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_160MHZ;
+               /*
+                * Convert 160 MHz channel width to new style as interop
+                * workaround.
+                */
+               vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80MHZ;
+               vht_oper->center_freq_seg2_idx = vht_oper->center_freq_seg1_idx;
+               if (chandef->chan->center_freq < chandef->center_freq1)
+                       vht_oper->center_freq_seg1_idx -= 8;
+               else
+                       vht_oper->center_freq_seg1_idx += 8;
                break;
        case NL80211_CHAN_WIDTH_80P80:
-               vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80P80MHZ;
+               /*
+                * Convert 80+80 MHz channel width to new style as interop
+                * workaround.
+                */
+               vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80MHZ;
                break;
        case NL80211_CHAN_WIDTH_80:
                vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80MHZ;
@@ -2380,17 +2396,13 @@ u8 *ieee80211_ie_build_vht_oper(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
        return pos + sizeof(struct ieee80211_vht_operation);
 }
 
-void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan,
-                                 const struct ieee80211_ht_operation *ht_oper,
-                                 struct cfg80211_chan_def *chandef)
+bool ieee80211_chandef_ht_oper(const struct ieee80211_ht_operation *ht_oper,
+                              struct cfg80211_chan_def *chandef)
 {
        enum nl80211_channel_type channel_type;
 
-       if (!ht_oper) {
-               cfg80211_chandef_create(chandef, control_chan,
-                                       NL80211_CHAN_NO_HT);
-               return;
-       }
+       if (!ht_oper)
+               return false;
 
        switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
        case IEEE80211_HT_PARAM_CHA_SEC_NONE:
@@ -2404,42 +2416,66 @@ void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan,
                break;
        default:
                channel_type = NL80211_CHAN_NO_HT;
+               return false;
        }
 
-       cfg80211_chandef_create(chandef, control_chan, channel_type);
+       cfg80211_chandef_create(chandef, chandef->chan, channel_type);
+       return true;
 }
 
-void ieee80211_vht_oper_to_chandef(struct ieee80211_channel *control_chan,
-                                  const struct ieee80211_vht_operation *oper,
-                                  struct cfg80211_chan_def *chandef)
+bool ieee80211_chandef_vht_oper(const struct ieee80211_vht_operation *oper,
+                               struct cfg80211_chan_def *chandef)
 {
+       struct cfg80211_chan_def new = *chandef;
+       int cf1, cf2;
+
        if (!oper)
-               return;
+               return false;
 
-       chandef->chan = control_chan;
+       cf1 = ieee80211_channel_to_frequency(oper->center_freq_seg1_idx,
+                                            chandef->chan->band);
+       cf2 = ieee80211_channel_to_frequency(oper->center_freq_seg2_idx,
+                                            chandef->chan->band);
 
        switch (oper->chan_width) {
        case IEEE80211_VHT_CHANWIDTH_USE_HT:
                break;
        case IEEE80211_VHT_CHANWIDTH_80MHZ:
-               chandef->width = NL80211_CHAN_WIDTH_80;
+               new.width = NL80211_CHAN_WIDTH_80;
+               new.center_freq1 = cf1;
+               /* If needed, adjust based on the newer interop workaround. */
+               if (oper->center_freq_seg2_idx) {
+                       unsigned int diff;
+
+                       diff = abs(oper->center_freq_seg2_idx -
+                                  oper->center_freq_seg1_idx);
+                       if (diff == 8) {
+                               new.width = NL80211_CHAN_WIDTH_160;
+                               new.center_freq1 = cf2;
+                       } else if (diff > 8) {
+                               new.width = NL80211_CHAN_WIDTH_80P80;
+                               new.center_freq2 = cf2;
+                       }
+               }
                break;
        case IEEE80211_VHT_CHANWIDTH_160MHZ:
-               chandef->width = NL80211_CHAN_WIDTH_160;
+               new.width = NL80211_CHAN_WIDTH_160;
+               new.center_freq1 = cf1;
                break;
        case IEEE80211_VHT_CHANWIDTH_80P80MHZ:
-               chandef->width = NL80211_CHAN_WIDTH_80P80;
+               new.width = NL80211_CHAN_WIDTH_80P80;
+               new.center_freq1 = cf1;
+               new.center_freq2 = cf2;
                break;
        default:
-               break;
+               return false;
        }
 
-       chandef->center_freq1 =
-               ieee80211_channel_to_frequency(oper->center_freq_seg1_idx,
-                                              control_chan->band);
-       chandef->center_freq2 =
-               ieee80211_channel_to_frequency(oper->center_freq_seg2_idx,
-                                              control_chan->band);
+       if (!cfg80211_chandef_valid(&new))
+               return false;
+
+       *chandef = new;
+       return true;
 }
 
 int ieee80211_parse_bitrates(struct cfg80211_chan_def *chandef,
@@ -2662,6 +2698,18 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
                sband = local->hw.wiphy->bands[status->band];
                bitrate = sband->bitrates[status->rate_idx].bitrate;
                ri.legacy = DIV_ROUND_UP(bitrate, (1 << shift));
+
+               if (status->flag & RX_FLAG_MACTIME_PLCP_START) {
+                       /* TODO: handle HT/VHT preambles */
+                       if (status->band == IEEE80211_BAND_5GHZ) {
+                               ts += 20 << shift;
+                               mpdu_offset += 2;
+                       } else if (status->flag & RX_FLAG_SHORTPRE) {
+                               ts += 96;
+                       } else {
+                               ts += 192;
+                       }
+               }
        }
 
        rate = cfg80211_calculate_bitrate(&ri);
@@ -3347,3 +3395,17 @@ void ieee80211_init_tx_queue(struct ieee80211_sub_if_data *sdata,
                txqi->txq.ac = IEEE80211_AC_BE;
        }
 }
+
+void ieee80211_txq_get_depth(struct ieee80211_txq *txq,
+                            unsigned long *frame_cnt,
+                            unsigned long *byte_cnt)
+{
+       struct txq_info *txqi = to_txq_info(txq);
+
+       if (frame_cnt)
+               *frame_cnt = txqi->queue.qlen;
+
+       if (byte_cnt)
+               *byte_cnt = txqi->byte_cnt;
+}
+EXPORT_SYMBOL(ieee80211_txq_get_depth);
index c38b2f07a919e20dc22363fe80911f5f5a0b004f..89e04d55aa1832e522f8e8f9619bfabc8c81ee93 100644 (file)
@@ -1,6 +1,9 @@
 /*
  * VHT handling
  *
+ * Portions of this file
+ * Copyright(c) 2015 - 2016 Intel Deutschland GmbH
+ *
  * 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.
@@ -278,6 +281,23 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
        }
 
        sta->sta.bandwidth = ieee80211_sta_cur_vht_bw(sta);
+
+       /* If HT IE reported 3839 bytes only, stay with that size. */
+       if (sta->sta.max_amsdu_len == IEEE80211_MAX_MPDU_LEN_HT_3839)
+               return;
+
+       switch (vht_cap->cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK) {
+       case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454:
+               sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_11454;
+               break;
+       case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991:
+               sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_7991;
+               break;
+       case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895:
+       default:
+               sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_3895;
+               break;
+       }
 }
 
 enum ieee80211_sta_rx_bandwidth ieee80211_sta_cap_rx_bw(struct sta_info *sta)
@@ -425,6 +445,43 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
        return changed;
 }
 
+void ieee80211_process_mu_groups(struct ieee80211_sub_if_data *sdata,
+                                struct ieee80211_mgmt *mgmt)
+{
+       struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
+
+       if (!sdata->vif.mu_mimo_owner)
+               return;
+
+       if (!memcmp(mgmt->u.action.u.vht_group_notif.position,
+                   bss_conf->mu_group.position, WLAN_USER_POSITION_LEN) &&
+           !memcmp(mgmt->u.action.u.vht_group_notif.membership,
+                   bss_conf->mu_group.membership, WLAN_MEMBERSHIP_LEN))
+               return;
+
+       memcpy(bss_conf->mu_group.membership,
+              mgmt->u.action.u.vht_group_notif.membership,
+              WLAN_MEMBERSHIP_LEN);
+       memcpy(bss_conf->mu_group.position,
+              mgmt->u.action.u.vht_group_notif.position,
+              WLAN_USER_POSITION_LEN);
+
+       ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_MU_GROUPS);
+}
+
+void ieee80211_update_mu_groups(struct ieee80211_vif *vif,
+                               const u8 *membership, const u8 *position)
+{
+       struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+
+       if (WARN_ON_ONCE(!vif->mu_mimo_owner))
+               return;
+
+       memcpy(bss_conf->mu_group.membership, membership, WLAN_MEMBERSHIP_LEN);
+       memcpy(bss_conf->mu_group.position, position, WLAN_USER_POSITION_LEN);
+}
+EXPORT_SYMBOL_GPL(ieee80211_update_mu_groups);
+
 void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
                                 struct sta_info *sta, u8 opmode,
                                 enum ieee80211_band band)
index d824c38971ed53ff702669c9bce0f4a86495bdd0..18848258adde8bdf855829cbce15d388d84a3eef 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright 2002-2004, Instant802 Networks, Inc.
  * Copyright 2008, Jouni Malinen <j@w1.fi>
+ * Copyright (C) 2016 Intel Deutschland GmbH
  *
  * 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
@@ -183,7 +184,6 @@ mic_fail_no_key:
        return RX_DROP_UNUSABLE;
 }
 
-
 static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
 {
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
@@ -191,6 +191,7 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        unsigned int hdrlen;
        int len, tail;
+       u64 pn;
        u8 *pos;
 
        if (info->control.hw_key &&
@@ -222,12 +223,8 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
                return 0;
 
        /* Increase IV for the frame */
-       spin_lock(&key->u.tkip.txlock);
-       key->u.tkip.tx.iv16++;
-       if (key->u.tkip.tx.iv16 == 0)
-               key->u.tkip.tx.iv32++;
-       pos = ieee80211_tkip_add_iv(pos, key);
-       spin_unlock(&key->u.tkip.txlock);
+       pn = atomic64_inc_return(&key->conf.tx_pn);
+       pos = ieee80211_tkip_add_iv(pos, &key->conf, pn);
 
        /* hwaccel - with software IV */
        if (info->control.hw_key)
index 8e63662c6fb0fc236da90883ff34b79d05308fcc..d3f6b063467ba94d480230e2512ce2074d04125f 100644 (file)
@@ -185,7 +185,7 @@ static int genl_allocate_reserve_groups(int n_groups, int *first_id)
                        }
                }
 
-               if (id >= mc_groups_longs * BITS_PER_LONG) {
+               if (id + n_groups >= mc_groups_longs * BITS_PER_LONG) {
                        unsigned long new_longs = mc_groups_longs +
                                                  BITS_TO_LONGS(n_groups);
                        size_t nlen = new_longs * sizeof(unsigned long);
index 598d374f6a35f714db4753efa7ab28d6782419a9..868f1ad0415a4ea728989908ed49858b6dfccc01 100644 (file)
@@ -41,5 +41,4 @@ config RFKILL_GPIO
        default n
        help
          If you say yes here you get support of a generic gpio RFKILL
-         driver. The platform should fill in the appropriate fields in the
-         rfkill_gpio_platform_data structure and pass that to the driver.
+         driver.
index f53bf3b6558b094b6e1b379568620157b4ffae17..a8c05e18da5865e908e041a40c9f9bdafa83ed39 100644 (file)
@@ -57,6 +57,8 @@ struct rfkill {
 
        bool                    registered;
        bool                    persistent;
+       bool                    polling_paused;
+       bool                    suspended;
 
        const struct rfkill_ops *ops;
        void                    *data;
@@ -233,29 +235,6 @@ static void rfkill_event(struct rfkill *rfkill)
        rfkill_send_events(rfkill, RFKILL_OP_CHANGE);
 }
 
-static bool __rfkill_set_hw_state(struct rfkill *rfkill,
-                                 bool blocked, bool *change)
-{
-       unsigned long flags;
-       bool prev, any;
-
-       BUG_ON(!rfkill);
-
-       spin_lock_irqsave(&rfkill->lock, flags);
-       prev = !!(rfkill->state & RFKILL_BLOCK_HW);
-       if (blocked)
-               rfkill->state |= RFKILL_BLOCK_HW;
-       else
-               rfkill->state &= ~RFKILL_BLOCK_HW;
-       *change = prev != blocked;
-       any = !!(rfkill->state & RFKILL_BLOCK_ANY);
-       spin_unlock_irqrestore(&rfkill->lock, flags);
-
-       rfkill_led_trigger_event(rfkill);
-
-       return any;
-}
-
 /**
  * rfkill_set_block - wrapper for set_block method
  *
@@ -285,7 +264,7 @@ static void rfkill_set_block(struct rfkill *rfkill, bool blocked)
        spin_lock_irqsave(&rfkill->lock, flags);
        prev = rfkill->state & RFKILL_BLOCK_SW;
 
-       if (rfkill->state & RFKILL_BLOCK_SW)
+       if (prev)
                rfkill->state |= RFKILL_BLOCK_SW_PREV;
        else
                rfkill->state &= ~RFKILL_BLOCK_SW_PREV;
@@ -303,8 +282,8 @@ static void rfkill_set_block(struct rfkill *rfkill, bool blocked)
        spin_lock_irqsave(&rfkill->lock, flags);
        if (err) {
                /*
-                * Failed -- reset status to _prev, this may be different
-                * from what set set _PREV to earlier in this function
+                * Failed -- reset status to _PREV, which may be different
+                * from what we have set _PREV to earlier in this function
                 * if rfkill_set_sw_state was invoked.
                 */
                if (rfkill->state & RFKILL_BLOCK_SW_PREV)
@@ -323,6 +302,19 @@ static void rfkill_set_block(struct rfkill *rfkill, bool blocked)
                rfkill_event(rfkill);
 }
 
+static void rfkill_update_global_state(enum rfkill_type type, bool blocked)
+{
+       int i;
+
+       if (type != RFKILL_TYPE_ALL) {
+               rfkill_global_states[type].cur = blocked;
+               return;
+       }
+
+       for (i = 0; i < NUM_RFKILL_TYPES; i++)
+               rfkill_global_states[i].cur = blocked;
+}
+
 #ifdef CONFIG_RFKILL_INPUT
 static atomic_t rfkill_input_disabled = ATOMIC_INIT(0);
 
@@ -332,8 +324,7 @@ static atomic_t rfkill_input_disabled = ATOMIC_INIT(0);
  * @blocked: the new state
  *
  * This function sets the state of all switches of given type,
- * unless a specific switch is claimed by userspace (in which case,
- * that switch is left alone) or suspended.
+ * unless a specific switch is suspended.
  *
  * Caller must have acquired rfkill_global_mutex.
  */
@@ -341,15 +332,7 @@ static void __rfkill_switch_all(const enum rfkill_type type, bool blocked)
 {
        struct rfkill *rfkill;
 
-       if (type == RFKILL_TYPE_ALL) {
-               int i;
-
-               for (i = 0; i < NUM_RFKILL_TYPES; i++)
-                       rfkill_global_states[i].cur = blocked;
-       } else {
-               rfkill_global_states[type].cur = blocked;
-       }
-
+       rfkill_update_global_state(type, blocked);
        list_for_each_entry(rfkill, &rfkill_list, node) {
                if (rfkill->type != type && type != RFKILL_TYPE_ALL)
                        continue;
@@ -477,17 +460,28 @@ bool rfkill_get_global_sw_state(const enum rfkill_type type)
 }
 #endif
 
-
 bool rfkill_set_hw_state(struct rfkill *rfkill, bool blocked)
 {
-       bool ret, change;
+       unsigned long flags;
+       bool ret, prev;
+
+       BUG_ON(!rfkill);
 
-       ret = __rfkill_set_hw_state(rfkill, blocked, &change);
+       spin_lock_irqsave(&rfkill->lock, flags);
+       prev = !!(rfkill->state & RFKILL_BLOCK_HW);
+       if (blocked)
+               rfkill->state |= RFKILL_BLOCK_HW;
+       else
+               rfkill->state &= ~RFKILL_BLOCK_HW;
+       ret = !!(rfkill->state & RFKILL_BLOCK_ANY);
+       spin_unlock_irqrestore(&rfkill->lock, flags);
+
+       rfkill_led_trigger_event(rfkill);
 
        if (!rfkill->registered)
                return ret;
 
-       if (change)
+       if (prev != blocked)
                schedule_work(&rfkill->uevent_work);
 
        return ret;
@@ -582,6 +576,34 @@ void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw)
 }
 EXPORT_SYMBOL(rfkill_set_states);
 
+static const char * const rfkill_types[] = {
+       NULL, /* RFKILL_TYPE_ALL */
+       "wlan",
+       "bluetooth",
+       "ultrawideband",
+       "wimax",
+       "wwan",
+       "gps",
+       "fm",
+       "nfc",
+};
+
+enum rfkill_type rfkill_find_type(const char *name)
+{
+       int i;
+
+       BUILD_BUG_ON(ARRAY_SIZE(rfkill_types) != NUM_RFKILL_TYPES);
+
+       if (!name)
+               return RFKILL_TYPE_ALL;
+
+       for (i = 1; i < NUM_RFKILL_TYPES; i++)
+               if (!strcmp(name, rfkill_types[i]))
+                       return i;
+       return RFKILL_TYPE_ALL;
+}
+EXPORT_SYMBOL(rfkill_find_type);
+
 static ssize_t name_show(struct device *dev, struct device_attribute *attr,
                         char *buf)
 {
@@ -591,38 +613,12 @@ static ssize_t name_show(struct device *dev, struct device_attribute *attr,
 }
 static DEVICE_ATTR_RO(name);
 
-static const char *rfkill_get_type_str(enum rfkill_type type)
-{
-       BUILD_BUG_ON(NUM_RFKILL_TYPES != RFKILL_TYPE_NFC + 1);
-
-       switch (type) {
-       case RFKILL_TYPE_WLAN:
-               return "wlan";
-       case RFKILL_TYPE_BLUETOOTH:
-               return "bluetooth";
-       case RFKILL_TYPE_UWB:
-               return "ultrawideband";
-       case RFKILL_TYPE_WIMAX:
-               return "wimax";
-       case RFKILL_TYPE_WWAN:
-               return "wwan";
-       case RFKILL_TYPE_GPS:
-               return "gps";
-       case RFKILL_TYPE_FM:
-               return "fm";
-       case RFKILL_TYPE_NFC:
-               return "nfc";
-       default:
-               BUG();
-       }
-}
-
 static ssize_t type_show(struct device *dev, struct device_attribute *attr,
                         char *buf)
 {
        struct rfkill *rfkill = to_rfkill(dev);
 
-       return sprintf(buf, "%s\n", rfkill_get_type_str(rfkill->type));
+       return sprintf(buf, "%s\n", rfkill_types[rfkill->type]);
 }
 static DEVICE_ATTR_RO(type);
 
@@ -730,20 +726,12 @@ static ssize_t state_store(struct device *dev, struct device_attribute *attr,
 }
 static DEVICE_ATTR_RW(state);
 
-static ssize_t claim_show(struct device *dev, struct device_attribute *attr,
-                         char *buf)
-{
-       return sprintf(buf, "%d\n", 0);
-}
-static DEVICE_ATTR_RO(claim);
-
 static struct attribute *rfkill_dev_attrs[] = {
        &dev_attr_name.attr,
        &dev_attr_type.attr,
        &dev_attr_index.attr,
        &dev_attr_persistent.attr,
        &dev_attr_state.attr,
-       &dev_attr_claim.attr,
        &dev_attr_soft.attr,
        &dev_attr_hard.attr,
        NULL,
@@ -768,7 +756,7 @@ static int rfkill_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
        if (error)
                return error;
        error = add_uevent_var(env, "RFKILL_TYPE=%s",
-                              rfkill_get_type_str(rfkill->type));
+                              rfkill_types[rfkill->type]);
        if (error)
                return error;
        spin_lock_irqsave(&rfkill->lock, flags);
@@ -786,6 +774,7 @@ void rfkill_pause_polling(struct rfkill *rfkill)
        if (!rfkill->ops->poll)
                return;
 
+       rfkill->polling_paused = true;
        cancel_delayed_work_sync(&rfkill->poll_work);
 }
 EXPORT_SYMBOL(rfkill_pause_polling);
@@ -797,6 +786,11 @@ void rfkill_resume_polling(struct rfkill *rfkill)
        if (!rfkill->ops->poll)
                return;
 
+       rfkill->polling_paused = false;
+
+       if (rfkill->suspended)
+               return;
+
        queue_delayed_work(system_power_efficient_wq,
                           &rfkill->poll_work, 0);
 }
@@ -807,7 +801,8 @@ static int rfkill_suspend(struct device *dev)
 {
        struct rfkill *rfkill = to_rfkill(dev);
 
-       rfkill_pause_polling(rfkill);
+       rfkill->suspended = true;
+       cancel_delayed_work_sync(&rfkill->poll_work);
 
        return 0;
 }
@@ -817,12 +812,16 @@ static int rfkill_resume(struct device *dev)
        struct rfkill *rfkill = to_rfkill(dev);
        bool cur;
 
+       rfkill->suspended = false;
+
        if (!rfkill->persistent) {
                cur = !!(rfkill->state & RFKILL_BLOCK_SW);
                rfkill_set_block(rfkill, cur);
        }
 
-       rfkill_resume_polling(rfkill);
+       if (rfkill->ops->poll && !rfkill->polling_paused)
+               queue_delayed_work(system_power_efficient_wq,
+                                  &rfkill->poll_work, 0);
 
        return 0;
 }
@@ -1172,15 +1171,8 @@ static ssize_t rfkill_fop_write(struct file *file, const char __user *buf,
 
        mutex_lock(&rfkill_global_mutex);
 
-       if (ev.op == RFKILL_OP_CHANGE_ALL) {
-               if (ev.type == RFKILL_TYPE_ALL) {
-                       enum rfkill_type i;
-                       for (i = 0; i < NUM_RFKILL_TYPES; i++)
-                               rfkill_global_states[i].cur = ev.soft;
-               } else {
-                       rfkill_global_states[ev.type].cur = ev.soft;
-               }
-       }
+       if (ev.op == RFKILL_OP_CHANGE_ALL)
+               rfkill_update_global_state(ev.type, ev.soft);
 
        list_for_each_entry(rfkill, &rfkill_list, node) {
                if (rfkill->idx != ev.idx && ev.op != RFKILL_OP_CHANGE_ALL)
@@ -1269,10 +1261,8 @@ static struct miscdevice rfkill_miscdev = {
 static int __init rfkill_init(void)
 {
        int error;
-       int i;
 
-       for (i = 0; i < NUM_RFKILL_TYPES; i++)
-               rfkill_global_states[i].cur = !rfkill_default_state;
+       rfkill_update_global_state(RFKILL_TYPE_ALL, !rfkill_default_state);
 
        error = class_register(&rfkill_class);
        if (error)
index 4b1e3f35f06cf39ecb9bb3f6a88d802a67a37bc3..76c01cbd56e35b209bf5e2599298471263f14ded 100644 (file)
@@ -27,8 +27,6 @@
 #include <linux/acpi.h>
 #include <linux/gpio/consumer.h>
 
-#include <linux/rfkill-gpio.h>
-
 struct rfkill_gpio_data {
        const char              *name;
        enum rfkill_type        type;
@@ -81,7 +79,6 @@ static int rfkill_gpio_acpi_probe(struct device *dev,
        if (!id)
                return -ENODEV;
 
-       rfkill->name = dev_name(dev);
        rfkill->type = (unsigned)id->driver_data;
 
        return acpi_dev_add_driver_gpios(ACPI_COMPANION(dev),
@@ -90,24 +87,27 @@ static int rfkill_gpio_acpi_probe(struct device *dev,
 
 static int rfkill_gpio_probe(struct platform_device *pdev)
 {
-       struct rfkill_gpio_platform_data *pdata = pdev->dev.platform_data;
        struct rfkill_gpio_data *rfkill;
        struct gpio_desc *gpio;
+       const char *type_name;
        int ret;
 
        rfkill = devm_kzalloc(&pdev->dev, sizeof(*rfkill), GFP_KERNEL);
        if (!rfkill)
                return -ENOMEM;
 
+       device_property_read_string(&pdev->dev, "name", &rfkill->name);
+       device_property_read_string(&pdev->dev, "type", &type_name);
+
+       if (!rfkill->name)
+               rfkill->name = dev_name(&pdev->dev);
+
+       rfkill->type = rfkill_find_type(type_name);
+
        if (ACPI_HANDLE(&pdev->dev)) {
                ret = rfkill_gpio_acpi_probe(&pdev->dev, rfkill);
                if (ret)
                        return ret;
-       } else if (pdata) {
-               rfkill->name = pdata->name;
-               rfkill->type = pdata->type;
-       } else {
-               return -ENODEV;
        }
 
        rfkill->clk = devm_clk_get(&pdev->dev, NULL);
@@ -124,10 +124,8 @@ static int rfkill_gpio_probe(struct platform_device *pdev)
 
        rfkill->shutdown_gpio = gpio;
 
-       /* Make sure at-least one of the GPIO is defined and that
-        * a name is specified for this instance
-        */
-       if ((!rfkill->reset_gpio && !rfkill->shutdown_gpio) || !rfkill->name) {
+       /* Make sure at-least one GPIO is defined for this instance */
+       if (!rfkill->reset_gpio && !rfkill->shutdown_gpio) {
                dev_err(&pdev->dev, "invalid platform data\n");
                return -EINVAL;
        }
index da72ed32f14385c3e218cda196e5b4c3511c896e..6c606120abfed96fe7fe4cdb23beb204e5ea109a 100644 (file)
@@ -50,8 +50,8 @@ config CFG80211_DEVELOPER_WARNINGS
        default n
        help
          This option enables some additional warnings that help
-         cfg80211 developers and driver developers, but that can
-         trigger due to races with userspace.
+         cfg80211 developers and driver developers, but beware that
+         they can also trigger due to races with userspace.
 
          For example, when a driver reports that it was disconnected
          from the AP, but the user disconnects manually at the same
@@ -61,19 +61,6 @@ config CFG80211_DEVELOPER_WARNINGS
          on it (or mac80211).
 
 
-config CFG80211_REG_DEBUG
-       bool "cfg80211 regulatory debugging"
-       depends on CFG80211
-       default n
-       ---help---
-         You can enable this if you want to debug regulatory changes.
-         For more information on cfg80211 regulatory refer to the wireless
-         wiki:
-
-         http://wireless.kernel.org/en/developers/Regulatory
-
-         If unsure, say N.
-
 config CFG80211_CERTIFICATION_ONUS
        bool "cfg80211 certification onus"
        depends on CFG80211 && EXPERT
@@ -123,7 +110,7 @@ config CFG80211_REG_RELAX_NO_IR
         interface which associated to an AP which userspace assumes or confirms
         to be an authorized master, i.e., with radar detection support and DFS
         capabilities. However, note that in order to not create daisy chain
-        scenarios, this relaxation is not allowed in cases that the BSS client
+        scenarios, this relaxation is not allowed in cases where the BSS client
         is associated to P2P GO and in addition the P2P GO instantiated on
         a channel due to this relaxation should not allow connection from
         non P2P clients.
@@ -148,7 +135,7 @@ config CFG80211_DEBUGFS
        depends on CFG80211
        depends on DEBUG_FS
        ---help---
-         You can enable this if you want to debugfs entries for cfg80211.
+         You can enable this if you want debugfs entries for cfg80211.
 
          If unsure, say N.
 
@@ -159,7 +146,7 @@ config CFG80211_INTERNAL_REGDB
        ---help---
          This option generates an internal data structure representing
          the wireless regulatory rules described in net/wireless/db.txt
-         and includes code to query that database.  This is an alternative
+         and includes code to query that database. This is an alternative
          to using CRDA for defining regulatory rules for the kernel.
 
          Using this option requires some parsing of the db.txt at build time,
@@ -172,7 +159,7 @@ config CFG80211_INTERNAL_REGDB
 
          http://wireless.kernel.org/en/developers/Regulatory
 
-         Most distributions have a CRDA package.  So if unsure, say N.
+         Most distributions have a CRDA package. So if unsure, say N.
 
 config CFG80211_CRDA_SUPPORT
        bool "support CRDA" if CFG80211_INTERNAL_REGDB
index b0915515640efed1ff4795103c0572aba48c38f4..3a9c41bc849aa8f32fbc75eafe564b3a5385c4db 100644 (file)
@@ -352,6 +352,16 @@ struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv,
        WARN_ON(ops->add_station && !ops->del_station);
        WARN_ON(ops->add_mpath && !ops->del_mpath);
        WARN_ON(ops->join_mesh && !ops->leave_mesh);
+       WARN_ON(ops->start_p2p_device && !ops->stop_p2p_device);
+       WARN_ON(ops->start_ap && !ops->stop_ap);
+       WARN_ON(ops->join_ocb && !ops->leave_ocb);
+       WARN_ON(ops->suspend && !ops->resume);
+       WARN_ON(ops->sched_scan_start && !ops->sched_scan_stop);
+       WARN_ON(ops->remain_on_channel && !ops->cancel_remain_on_channel);
+       WARN_ON(ops->tdls_channel_switch && !ops->tdls_cancel_channel_switch);
+       WARN_ON(ops->add_tx_ts && !ops->del_tx_ts);
+       WARN_ON(ops->set_tx_power && !ops->get_tx_power);
+       WARN_ON(ops->set_antenna && !ops->get_antenna);
 
        alloc_size = sizeof(*rdev) + sizeof_priv;
 
index fb44fa3bf4efa750298163a15534572c43229b2e..ff328250bc442db6a9e8e5136496098d4270bf6f 100644 (file)
@@ -711,7 +711,7 @@ EXPORT_SYMBOL(cfg80211_rx_mgmt);
 
 void cfg80211_dfs_channels_update_work(struct work_struct *work)
 {
-       struct delayed_work *delayed_work;
+       struct delayed_work *delayed_work = to_delayed_work(work);
        struct cfg80211_registered_device *rdev;
        struct cfg80211_chan_def chandef;
        struct ieee80211_supported_band *sband;
@@ -721,7 +721,6 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work)
        unsigned long timeout, next_time = 0;
        int bandid, i;
 
-       delayed_work = container_of(work, struct delayed_work, work);
        rdev = container_of(delayed_work, struct cfg80211_registered_device,
                            dfs_update_channels_wk);
        wiphy = &rdev->wiphy;
index d4786f2802aa3c94f0a9bfcba846c98ec5b2b249..90890f183c0e51dfdade4a46c96ffe9080290ffe 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
- * Copyright 2015      Intel Deutschland GmbH
+ * Copyright 2015-2016 Intel Deutschland GmbH
  */
 
 #include <linux/if.h>
@@ -401,6 +401,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
        [NL80211_ATTR_NETNS_FD] = { .type = NLA_U32 },
        [NL80211_ATTR_SCHED_SCAN_DELAY] = { .type = NLA_U32 },
        [NL80211_ATTR_REG_INDOOR] = { .type = NLA_FLAG },
+       [NL80211_ATTR_PBSS] = { .type = NLA_FLAG },
 };
 
 /* policy for the key attributes */
@@ -3461,6 +3462,10 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
                        return PTR_ERR(params.acl);
        }
 
+       params.pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]);
+       if (params.pbss && !rdev->wiphy.bands[IEEE80211_BAND_60GHZ])
+               return -EOPNOTSUPP;
+
        wdev_lock(wdev);
        err = rdev_start_ap(rdev, dev, &params);
        if (!err) {
@@ -7281,9 +7286,11 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
        }
 
        if (nla_get_flag(info->attrs[NL80211_ATTR_USE_RRM])) {
-               if (!(rdev->wiphy.features &
-                     NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES) ||
-                   !(rdev->wiphy.features & NL80211_FEATURE_QUIET))
+               if (!((rdev->wiphy.features &
+                       NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES) &&
+                      (rdev->wiphy.features & NL80211_FEATURE_QUIET)) &&
+                   !wiphy_ext_feature_isset(&rdev->wiphy,
+                                            NL80211_EXT_FEATURE_RRM))
                        return -EINVAL;
                req.flags |= ASSOC_REQ_USE_RRM;
        }
@@ -7971,15 +7978,23 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
        }
 
        if (nla_get_flag(info->attrs[NL80211_ATTR_USE_RRM])) {
-               if (!(rdev->wiphy.features &
-                     NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES) ||
-                   !(rdev->wiphy.features & NL80211_FEATURE_QUIET)) {
+               if (!((rdev->wiphy.features &
+                       NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES) &&
+                      (rdev->wiphy.features & NL80211_FEATURE_QUIET)) &&
+                   !wiphy_ext_feature_isset(&rdev->wiphy,
+                                            NL80211_EXT_FEATURE_RRM)) {
                        kzfree(connkeys);
                        return -EINVAL;
                }
                connect.flags |= ASSOC_REQ_USE_RRM;
        }
 
+       connect.pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]);
+       if (connect.pbss && !rdev->wiphy.bands[IEEE80211_BAND_60GHZ]) {
+               kzfree(connkeys);
+               return -EOPNOTSUPP;
+       }
+
        wdev_lock(dev->ieee80211_ptr);
        err = cfg80211_connect(rdev, dev, &connect, connkeys, NULL);
        wdev_unlock(dev->ieee80211_ptr);
index 722da616438cd1e933fb4d5e60a2c4846f44d186..6582d155e2fce5417bc498a438ae9a19a3eca35f 100644 (file)
@@ -43,6 +43,7 @@ static const struct radiotap_align_size rtap_namespace_sizes[] = {
        [IEEE80211_RADIOTAP_DATA_RETRIES] = { .align = 1, .size = 1, },
        [IEEE80211_RADIOTAP_MCS] = { .align = 1, .size = 3, },
        [IEEE80211_RADIOTAP_AMPDU_STATUS] = { .align = 4, .size = 8, },
+       [IEEE80211_RADIOTAP_VHT] = { .align = 2, .size = 12, },
        /*
         * add more here as they are defined in radiotap.h
         */
index 3b0ce1c484a3dd33f2e2c81edeeadb79a48e2dcc..bc76b281ed3ae5704679025fabbc43e822da7e97 100644 (file)
 #include "regdb.h"
 #include "nl80211.h"
 
-#ifdef CONFIG_CFG80211_REG_DEBUG
-#define REG_DBG_PRINT(format, args...)                 \
-       printk(KERN_DEBUG pr_fmt(format), ##args)
-#else
-#define REG_DBG_PRINT(args...)
-#endif
-
 /*
  * Grace period we give before making sure all current interfaces reside on
  * channels allowed by the current regulatory domain.
@@ -178,12 +171,10 @@ enum nl80211_dfs_regions reg_get_dfs_region(struct wiphy *wiphy)
        if (wiphy_regd->dfs_region == regd->dfs_region)
                goto out;
 
-       REG_DBG_PRINT("%s: device specific dfs_region "
-                     "(%s) disagrees with cfg80211's "
-                     "central dfs_region (%s)\n",
-                     dev_name(&wiphy->dev),
-                     reg_dfs_region_str(wiphy_regd->dfs_region),
-                     reg_dfs_region_str(regd->dfs_region));
+       pr_debug("%s: device specific dfs_region (%s) disagrees with cfg80211's central dfs_region (%s)\n",
+                dev_name(&wiphy->dev),
+                reg_dfs_region_str(wiphy_regd->dfs_region),
+                reg_dfs_region_str(regd->dfs_region));
 
 out:
        return regd->dfs_region;
@@ -541,7 +532,7 @@ static DECLARE_DELAYED_WORK(crda_timeout, crda_timeout_work);
 
 static void crda_timeout_work(struct work_struct *work)
 {
-       REG_DBG_PRINT("Timeout while waiting for CRDA to reply, restoring regulatory settings\n");
+       pr_debug("Timeout while waiting for CRDA to reply, restoring regulatory settings\n");
        rtnl_lock();
        reg_crda_timeouts++;
        restore_regulatory_settings(true);
@@ -583,7 +574,7 @@ static int call_crda(const char *alpha2)
 
        if (!is_world_regdom((char *) alpha2))
                pr_debug("Calling CRDA for country: %c%c\n",
-                       alpha2[0], alpha2[1]);
+                        alpha2[0], alpha2[1]);
        else
                pr_debug("Calling CRDA to update world regulatory domain\n");
 
@@ -1130,42 +1121,6 @@ const char *reg_initiator_name(enum nl80211_reg_initiator initiator)
 }
 EXPORT_SYMBOL(reg_initiator_name);
 
-static void chan_reg_rule_print_dbg(const struct ieee80211_regdomain *regd,
-                                   struct ieee80211_channel *chan,
-                                   const struct ieee80211_reg_rule *reg_rule)
-{
-#ifdef CONFIG_CFG80211_REG_DEBUG
-       const struct ieee80211_power_rule *power_rule;
-       const struct ieee80211_freq_range *freq_range;
-       char max_antenna_gain[32], bw[32];
-
-       power_rule = &reg_rule->power_rule;
-       freq_range = &reg_rule->freq_range;
-
-       if (!power_rule->max_antenna_gain)
-               snprintf(max_antenna_gain, sizeof(max_antenna_gain), "N/A");
-       else
-               snprintf(max_antenna_gain, sizeof(max_antenna_gain), "%d mBi",
-                        power_rule->max_antenna_gain);
-
-       if (reg_rule->flags & NL80211_RRF_AUTO_BW)
-               snprintf(bw, sizeof(bw), "%d KHz, %d KHz AUTO",
-                        freq_range->max_bandwidth_khz,
-                        reg_get_max_bandwidth(regd, reg_rule));
-       else
-               snprintf(bw, sizeof(bw), "%d KHz",
-                        freq_range->max_bandwidth_khz);
-
-       REG_DBG_PRINT("Updating information on frequency %d MHz with regulatory rule:\n",
-                     chan->center_freq);
-
-       REG_DBG_PRINT("(%d KHz - %d KHz @ %s), (%s, %d mBm)\n",
-                     freq_range->start_freq_khz, freq_range->end_freq_khz,
-                     bw, max_antenna_gain,
-                     power_rule->max_eirp);
-#endif
-}
-
 static uint32_t reg_rule_to_chan_bw_flags(const struct ieee80211_regdomain *regd,
                                          const struct ieee80211_reg_rule *reg_rule,
                                          const struct ieee80211_channel *chan)
@@ -1240,20 +1195,19 @@ static void handle_channel(struct wiphy *wiphy,
                if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
                    request_wiphy && request_wiphy == wiphy &&
                    request_wiphy->regulatory_flags & REGULATORY_STRICT_REG) {
-                       REG_DBG_PRINT("Disabling freq %d MHz for good\n",
-                                     chan->center_freq);
+                       pr_debug("Disabling freq %d MHz for good\n",
+                                chan->center_freq);
                        chan->orig_flags |= IEEE80211_CHAN_DISABLED;
                        chan->flags = chan->orig_flags;
                } else {
-                       REG_DBG_PRINT("Disabling freq %d MHz\n",
-                                     chan->center_freq);
+                       pr_debug("Disabling freq %d MHz\n",
+                                chan->center_freq);
                        chan->flags |= IEEE80211_CHAN_DISABLED;
                }
                return;
        }
 
        regd = reg_get_regdomain(wiphy);
-       chan_reg_rule_print_dbg(regd, chan, reg_rule);
 
        power_rule = &reg_rule->power_rule;
        bw_flags = reg_rule_to_chan_bw_flags(regd, reg_rule, chan);
@@ -1391,18 +1345,15 @@ static bool ignore_reg_update(struct wiphy *wiphy,
                return true;
 
        if (!lr) {
-               REG_DBG_PRINT("Ignoring regulatory request set by %s "
-                             "since last_request is not set\n",
-                             reg_initiator_name(initiator));
+               pr_debug("Ignoring regulatory request set by %s since last_request is not set\n",
+                        reg_initiator_name(initiator));
                return true;
        }
 
        if (initiator == NL80211_REGDOM_SET_BY_CORE &&
            wiphy->regulatory_flags & REGULATORY_CUSTOM_REG) {
-               REG_DBG_PRINT("Ignoring regulatory request set by %s "
-                             "since the driver uses its own custom "
-                             "regulatory domain\n",
-                             reg_initiator_name(initiator));
+               pr_debug("Ignoring regulatory request set by %s since the driver uses its own custom regulatory domain\n",
+                        reg_initiator_name(initiator));
                return true;
        }
 
@@ -1413,10 +1364,8 @@ static bool ignore_reg_update(struct wiphy *wiphy,
        if (wiphy_strict_alpha2_regd(wiphy) && !wiphy->regd &&
            initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE &&
            !is_world_regdom(lr->alpha2)) {
-               REG_DBG_PRINT("Ignoring regulatory request set by %s "
-                             "since the driver requires its own regulatory "
-                             "domain to be set first\n",
-                             reg_initiator_name(initiator));
+               pr_debug("Ignoring regulatory request set by %s since the driver requires its own regulatory domain to be set first\n",
+                        reg_initiator_name(initiator));
                return true;
        }
 
@@ -1697,7 +1646,7 @@ static void reg_check_chans_work(struct work_struct *work)
 {
        struct cfg80211_registered_device *rdev;
 
-       REG_DBG_PRINT("Verifying active interfaces after reg change\n");
+       pr_debug("Verifying active interfaces after reg change\n");
        rtnl_lock();
 
        list_for_each_entry(rdev, &cfg80211_rdev_list, list)
@@ -1779,8 +1728,8 @@ static void handle_channel_custom(struct wiphy *wiphy,
        }
 
        if (IS_ERR(reg_rule)) {
-               REG_DBG_PRINT("Disabling freq %d MHz as custom regd has no rule that fits it\n",
-                             chan->center_freq);
+               pr_debug("Disabling freq %d MHz as custom regd has no rule that fits it\n",
+                        chan->center_freq);
                if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) {
                        chan->flags |= IEEE80211_CHAN_DISABLED;
                } else {
@@ -1790,8 +1739,6 @@ static void handle_channel_custom(struct wiphy *wiphy,
                return;
        }
 
-       chan_reg_rule_print_dbg(regd, chan, reg_rule);
-
        power_rule = &reg_rule->power_rule;
        bw_flags = reg_rule_to_chan_bw_flags(regd, reg_rule, chan);
 
@@ -2522,7 +2469,7 @@ static void restore_alpha2(char *alpha2, bool reset_user)
        if (is_user_regdom_saved()) {
                /* Unless we're asked to ignore it and reset it */
                if (reset_user) {
-                       REG_DBG_PRINT("Restoring regulatory settings including user preference\n");
+                       pr_debug("Restoring regulatory settings including user preference\n");
                        user_alpha2[0] = '9';
                        user_alpha2[1] = '7';
 
@@ -2532,24 +2479,24 @@ static void restore_alpha2(char *alpha2, bool reset_user)
                         * back as they were for a full restore.
                         */
                        if (!is_world_regdom(ieee80211_regdom)) {
-                               REG_DBG_PRINT("Keeping preference on module parameter ieee80211_regdom: %c%c\n",
-                                             ieee80211_regdom[0], ieee80211_regdom[1]);
+                               pr_debug("Keeping preference on module parameter ieee80211_regdom: %c%c\n",
+                                        ieee80211_regdom[0], ieee80211_regdom[1]);
                                alpha2[0] = ieee80211_regdom[0];
                                alpha2[1] = ieee80211_regdom[1];
                        }
                } else {
-                       REG_DBG_PRINT("Restoring regulatory settings while preserving user preference for: %c%c\n",
-                                     user_alpha2[0], user_alpha2[1]);
+                       pr_debug("Restoring regulatory settings while preserving user preference for: %c%c\n",
+                                user_alpha2[0], user_alpha2[1]);
                        alpha2[0] = user_alpha2[0];
                        alpha2[1] = user_alpha2[1];
                }
        } else if (!is_world_regdom(ieee80211_regdom)) {
-               REG_DBG_PRINT("Keeping preference on module parameter ieee80211_regdom: %c%c\n",
-                             ieee80211_regdom[0], ieee80211_regdom[1]);
+               pr_debug("Keeping preference on module parameter ieee80211_regdom: %c%c\n",
+                        ieee80211_regdom[0], ieee80211_regdom[1]);
                alpha2[0] = ieee80211_regdom[0];
                alpha2[1] = ieee80211_regdom[1];
        } else
-               REG_DBG_PRINT("Restoring regulatory settings\n");
+               pr_debug("Restoring regulatory settings\n");
 }
 
 static void restore_custom_reg_settings(struct wiphy *wiphy)
@@ -2661,14 +2608,14 @@ static void restore_regulatory_settings(bool reset_user)
        list_splice_tail_init(&tmp_reg_req_list, &reg_requests_list);
        spin_unlock(&reg_requests_lock);
 
-       REG_DBG_PRINT("Kicking the queue\n");
+       pr_debug("Kicking the queue\n");
 
        schedule_work(&reg_work);
 }
 
 void regulatory_hint_disconnect(void)
 {
-       REG_DBG_PRINT("All devices are disconnected, going to restore regulatory settings\n");
+       pr_debug("All devices are disconnected, going to restore regulatory settings\n");
        restore_regulatory_settings(false);
 }
 
@@ -2716,10 +2663,10 @@ int regulatory_hint_found_beacon(struct wiphy *wiphy,
        if (!reg_beacon)
                return -ENOMEM;
 
-       REG_DBG_PRINT("Found new beacon on frequency: %d MHz (Ch %d) on %s\n",
-                     beacon_chan->center_freq,
-                     ieee80211_frequency_to_channel(beacon_chan->center_freq),
-                     wiphy_name(wiphy));
+       pr_debug("Found new beacon on frequency: %d MHz (Ch %d) on %s\n",
+                beacon_chan->center_freq,
+                ieee80211_frequency_to_channel(beacon_chan->center_freq),
+                wiphy_name(wiphy));
 
        memcpy(&reg_beacon->chan, beacon_chan,
               sizeof(struct ieee80211_channel));
@@ -2798,8 +2745,7 @@ bool reg_supported_dfs_region(enum nl80211_dfs_regions dfs_region)
        case NL80211_DFS_JP:
                return true;
        default:
-               REG_DBG_PRINT("Ignoring uknown DFS master region: %d\n",
-                             dfs_region);
+               pr_debug("Ignoring uknown DFS master region: %d\n", dfs_region);
                return false;
        }
 }
index 8020b5b094d4c8fba0c0f2431f8af7d8ecc40dca..79bd3a171caa83ed8ae811b744fd271475b0257a 100644 (file)
@@ -264,7 +264,7 @@ static struct cfg80211_bss *cfg80211_get_conn_bss(struct wireless_dev *wdev)
                               wdev->conn->params.bssid,
                               wdev->conn->params.ssid,
                               wdev->conn->params.ssid_len,
-                              IEEE80211_BSS_TYPE_ESS,
+                              wdev->conn_bss_type,
                               IEEE80211_PRIVACY(wdev->conn->params.privacy));
        if (!bss)
                return NULL;
@@ -687,7 +687,7 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
                WARN_ON_ONCE(!wiphy_to_rdev(wdev->wiphy)->ops->connect);
                bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
                                       wdev->ssid, wdev->ssid_len,
-                                      IEEE80211_BSS_TYPE_ESS,
+                                      wdev->conn_bss_type,
                                       IEEE80211_PRIVACY_ANY);
                if (bss)
                        cfg80211_hold_bss(bss_from_pub(bss));
@@ -846,7 +846,7 @@ void cfg80211_roamed(struct net_device *dev,
 
        bss = cfg80211_get_bss(wdev->wiphy, channel, bssid, wdev->ssid,
                               wdev->ssid_len,
-                              IEEE80211_BSS_TYPE_ESS, IEEE80211_PRIVACY_ANY);
+                              wdev->conn_bss_type, IEEE80211_PRIVACY_ANY);
        if (WARN_ON(!bss))
                return;
 
@@ -1017,6 +1017,9 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
        memcpy(wdev->ssid, connect->ssid, connect->ssid_len);
        wdev->ssid_len = connect->ssid_len;
 
+       wdev->conn_bss_type = connect->pbss ? IEEE80211_BSS_TYPE_PBSS :
+                                             IEEE80211_BSS_TYPE_ESS;
+
        if (!rdev->ops->connect)
                err = cfg80211_sme_connect(wdev, connect, prev_bssid);
        else
index 92770427b211f559be4735584d74043ec6301802..c7f6820bb25816346e35cd9935abed06446eafae 100644 (file)
@@ -393,9 +393,9 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb)
 }
 EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb);
 
-unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
+static unsigned int __ieee80211_get_mesh_hdrlen(u8 flags)
 {
-       int ae = meshhdr->flags & MESH_FLAGS_AE;
+       int ae = flags & MESH_FLAGS_AE;
        /* 802.11-2012, 8.2.4.7.3 */
        switch (ae) {
        default:
@@ -407,21 +407,31 @@ unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
                return 18;
        }
 }
+
+unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
+{
+       return __ieee80211_get_mesh_hdrlen(meshhdr->flags);
+}
 EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen);
 
-int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
-                          enum nl80211_iftype iftype)
+static int __ieee80211_data_to_8023(struct sk_buff *skb, struct ethhdr *ehdr,
+                                   const u8 *addr, enum nl80211_iftype iftype)
 {
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-       u16 hdrlen, ethertype;
-       u8 *payload;
-       u8 dst[ETH_ALEN];
-       u8 src[ETH_ALEN] __aligned(2);
+       struct {
+               u8 hdr[ETH_ALEN] __aligned(2);
+               __be16 proto;
+       } payload;
+       struct ethhdr tmp;
+       u16 hdrlen;
+       u8 mesh_flags = 0;
 
        if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
                return -1;
 
        hdrlen = ieee80211_hdrlen(hdr->frame_control);
+       if (skb->len < hdrlen + 8)
+               return -1;
 
        /* convert IEEE 802.11 header + possible LLC headers into Ethernet
         * header
@@ -432,8 +442,11 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
         *   1     0   BSSID SA    DA    n/a
         *   1     1   RA    TA    DA    SA
         */
-       memcpy(dst, ieee80211_get_DA(hdr), ETH_ALEN);
-       memcpy(src, ieee80211_get_SA(hdr), ETH_ALEN);
+       memcpy(tmp.h_dest, ieee80211_get_DA(hdr), ETH_ALEN);
+       memcpy(tmp.h_source, ieee80211_get_SA(hdr), ETH_ALEN);
+
+       if (iftype == NL80211_IFTYPE_MESH_POINT)
+               skb_copy_bits(skb, hdrlen, &mesh_flags, 1);
 
        switch (hdr->frame_control &
                cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) {
@@ -450,44 +463,31 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
                             iftype != NL80211_IFTYPE_STATION))
                        return -1;
                if (iftype == NL80211_IFTYPE_MESH_POINT) {
-                       struct ieee80211s_hdr *meshdr =
-                               (struct ieee80211s_hdr *) (skb->data + hdrlen);
-                       /* make sure meshdr->flags is on the linear part */
-                       if (!pskb_may_pull(skb, hdrlen + 1))
-                               return -1;
-                       if (meshdr->flags & MESH_FLAGS_AE_A4)
+                       if (mesh_flags & MESH_FLAGS_AE_A4)
                                return -1;
-                       if (meshdr->flags & MESH_FLAGS_AE_A5_A6) {
+                       if (mesh_flags & MESH_FLAGS_AE_A5_A6) {
                                skb_copy_bits(skb, hdrlen +
                                        offsetof(struct ieee80211s_hdr, eaddr1),
-                                       dst, ETH_ALEN);
-                               skb_copy_bits(skb, hdrlen +
-                                       offsetof(struct ieee80211s_hdr, eaddr2),
-                                       src, ETH_ALEN);
+                                       tmp.h_dest, 2 * ETH_ALEN);
                        }
-                       hdrlen += ieee80211_get_mesh_hdrlen(meshdr);
+                       hdrlen += __ieee80211_get_mesh_hdrlen(mesh_flags);
                }
                break;
        case cpu_to_le16(IEEE80211_FCTL_FROMDS):
                if ((iftype != NL80211_IFTYPE_STATION &&
                     iftype != NL80211_IFTYPE_P2P_CLIENT &&
                     iftype != NL80211_IFTYPE_MESH_POINT) ||
-                   (is_multicast_ether_addr(dst) &&
-                    ether_addr_equal(src, addr)))
+                   (is_multicast_ether_addr(tmp.h_dest) &&
+                    ether_addr_equal(tmp.h_source, addr)))
                        return -1;
                if (iftype == NL80211_IFTYPE_MESH_POINT) {
-                       struct ieee80211s_hdr *meshdr =
-                               (struct ieee80211s_hdr *) (skb->data + hdrlen);
-                       /* make sure meshdr->flags is on the linear part */
-                       if (!pskb_may_pull(skb, hdrlen + 1))
-                               return -1;
-                       if (meshdr->flags & MESH_FLAGS_AE_A5_A6)
+                       if (mesh_flags & MESH_FLAGS_AE_A5_A6)
                                return -1;
-                       if (meshdr->flags & MESH_FLAGS_AE_A4)
+                       if (mesh_flags & MESH_FLAGS_AE_A4)
                                skb_copy_bits(skb, hdrlen +
                                        offsetof(struct ieee80211s_hdr, eaddr1),
-                                       src, ETH_ALEN);
-                       hdrlen += ieee80211_get_mesh_hdrlen(meshdr);
+                                       tmp.h_source, ETH_ALEN);
+                       hdrlen += __ieee80211_get_mesh_hdrlen(mesh_flags);
                }
                break;
        case cpu_to_le16(0):
@@ -498,33 +498,33 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
                break;
        }
 
-       if (!pskb_may_pull(skb, hdrlen + 8))
-               return -1;
-
-       payload = skb->data + hdrlen;
-       ethertype = (payload[6] << 8) | payload[7];
+       skb_copy_bits(skb, hdrlen, &payload, sizeof(payload));
+       tmp.h_proto = payload.proto;
 
-       if (likely((ether_addr_equal(payload, rfc1042_header) &&
-                   ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
-                  ether_addr_equal(payload, bridge_tunnel_header))) {
+       if (likely((ether_addr_equal(payload.hdr, rfc1042_header) &&
+                   tmp.h_proto != htons(ETH_P_AARP) &&
+                   tmp.h_proto != htons(ETH_P_IPX)) ||
+                  ether_addr_equal(payload.hdr, bridge_tunnel_header)))
                /* remove RFC1042 or Bridge-Tunnel encapsulation and
                 * replace EtherType */
-               skb_pull(skb, hdrlen + 6);
-               memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
-               memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
-       } else {
-               struct ethhdr *ehdr;
-               __be16 len;
+               hdrlen += ETH_ALEN + 2;
+       else
+               tmp.h_proto = htons(skb->len);
 
-               skb_pull(skb, hdrlen);
-               len = htons(skb->len);
+       pskb_pull(skb, hdrlen);
+
+       if (!ehdr)
                ehdr = (struct ethhdr *) skb_push(skb, sizeof(struct ethhdr));
-               memcpy(ehdr->h_dest, dst, ETH_ALEN);
-               memcpy(ehdr->h_source, src, ETH_ALEN);
-               ehdr->h_proto = len;
-       }
+       memcpy(ehdr, &tmp, sizeof(tmp));
+
        return 0;
 }
+
+int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
+                          enum nl80211_iftype iftype)
+{
+       return __ieee80211_data_to_8023(skb, NULL, addr, iftype);
+}
 EXPORT_SYMBOL(ieee80211_data_to_8023);
 
 int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
@@ -644,70 +644,147 @@ int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
 }
 EXPORT_SYMBOL(ieee80211_data_from_8023);
 
+static void
+__frame_add_frag(struct sk_buff *skb, struct page *page,
+                void *ptr, int len, int size)
+{
+       struct skb_shared_info *sh = skb_shinfo(skb);
+       int page_offset;
+
+       atomic_inc(&page->_count);
+       page_offset = ptr - page_address(page);
+       skb_add_rx_frag(skb, sh->nr_frags, page, page_offset, len, size);
+}
+
+static void
+__ieee80211_amsdu_copy_frag(struct sk_buff *skb, struct sk_buff *frame,
+                           int offset, int len)
+{
+       struct skb_shared_info *sh = skb_shinfo(skb);
+       const skb_frag_t *frag = &sh->frags[-1];
+       struct page *frag_page;
+       void *frag_ptr;
+       int frag_len, frag_size;
+       int head_size = skb->len - skb->data_len;
+       int cur_len;
+
+       frag_page = virt_to_head_page(skb->head);
+       frag_ptr = skb->data;
+       frag_size = head_size;
+
+       while (offset >= frag_size) {
+               offset -= frag_size;
+               frag++;
+               frag_page = skb_frag_page(frag);
+               frag_ptr = skb_frag_address(frag);
+               frag_size = skb_frag_size(frag);
+       }
+
+       frag_ptr += offset;
+       frag_len = frag_size - offset;
+
+       cur_len = min(len, frag_len);
+
+       __frame_add_frag(frame, frag_page, frag_ptr, cur_len, frag_size);
+       len -= cur_len;
+
+       while (len > 0) {
+               frag++;
+               frag_len = skb_frag_size(frag);
+               cur_len = min(len, frag_len);
+               __frame_add_frag(frame, skb_frag_page(frag),
+                                skb_frag_address(frag), cur_len, frag_len);
+               len -= cur_len;
+       }
+}
+
+static struct sk_buff *
+__ieee80211_amsdu_copy(struct sk_buff *skb, unsigned int hlen,
+                      int offset, int len, bool reuse_frag)
+{
+       struct sk_buff *frame;
+       int cur_len = len;
+
+       if (skb->len - offset < len)
+               return NULL;
+
+       /*
+        * When reusing framents, copy some data to the head to simplify
+        * ethernet header handling and speed up protocol header processing
+        * in the stack later.
+        */
+       if (reuse_frag)
+               cur_len = min_t(int, len, 32);
+
+       /*
+        * Allocate and reserve two bytes more for payload
+        * alignment since sizeof(struct ethhdr) is 14.
+        */
+       frame = dev_alloc_skb(hlen + sizeof(struct ethhdr) + 2 + cur_len);
+
+       skb_reserve(frame, hlen + sizeof(struct ethhdr) + 2);
+       skb_copy_bits(skb, offset, skb_put(frame, cur_len), cur_len);
+
+       len -= cur_len;
+       if (!len)
+               return frame;
+
+       offset += cur_len;
+       __ieee80211_amsdu_copy_frag(skb, frame, offset, len);
+
+       return frame;
+}
 
 void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
                              const u8 *addr, enum nl80211_iftype iftype,
                              const unsigned int extra_headroom,
                              bool has_80211_header)
 {
+       unsigned int hlen = ALIGN(extra_headroom, 4);
        struct sk_buff *frame = NULL;
        u16 ethertype;
        u8 *payload;
-       const struct ethhdr *eth;
-       int remaining, err;
-       u8 dst[ETH_ALEN], src[ETH_ALEN];
+       int offset = 0, remaining, err;
+       struct ethhdr eth;
+       bool reuse_frag = skb->head_frag && !skb_has_frag_list(skb);
+       bool reuse_skb = false;
+       bool last = false;
 
        if (has_80211_header) {
-               err = ieee80211_data_to_8023(skb, addr, iftype);
+               err = __ieee80211_data_to_8023(skb, &eth, addr, iftype);
                if (err)
                        goto out;
-
-               /* skip the wrapping header */
-               eth = (struct ethhdr *) skb_pull(skb, sizeof(struct ethhdr));
-               if (!eth)
-                       goto out;
-       } else {
-               eth = (struct ethhdr *) skb->data;
        }
 
-       while (skb != frame) {
+       while (!last) {
+               unsigned int subframe_len;
+               int len;
                u8 padding;
-               __be16 len = eth->h_proto;
-               unsigned int subframe_len = sizeof(struct ethhdr) + ntohs(len);
-
-               remaining = skb->len;
-               memcpy(dst, eth->h_dest, ETH_ALEN);
-               memcpy(src, eth->h_source, ETH_ALEN);
 
+               skb_copy_bits(skb, offset, &eth, sizeof(eth));
+               len = ntohs(eth.h_proto);
+               subframe_len = sizeof(struct ethhdr) + len;
                padding = (4 - subframe_len) & 0x3;
+
                /* the last MSDU has no padding */
+               remaining = skb->len - offset;
                if (subframe_len > remaining)
                        goto purge;
 
-               skb_pull(skb, sizeof(struct ethhdr));
+               offset += sizeof(struct ethhdr);
                /* reuse skb for the last subframe */
-               if (remaining <= subframe_len + padding)
+               last = remaining <= subframe_len + padding;
+               if (!skb_is_nonlinear(skb) && !reuse_frag && last) {
+                       skb_pull(skb, offset);
                        frame = skb;
-               else {
-                       unsigned int hlen = ALIGN(extra_headroom, 4);
-                       /*
-                        * Allocate and reserve two bytes more for payload
-                        * alignment since sizeof(struct ethhdr) is 14.
-                        */
-                       frame = dev_alloc_skb(hlen + subframe_len + 2);
+                       reuse_skb = true;
+               } else {
+                       frame = __ieee80211_amsdu_copy(skb, hlen, offset, len,
+                                                      reuse_frag);
                        if (!frame)
                                goto purge;
 
-                       skb_reserve(frame, hlen + sizeof(struct ethhdr) + 2);
-                       memcpy(skb_put(frame, ntohs(len)), skb->data,
-                               ntohs(len));
-
-                       eth = (struct ethhdr *)skb_pull(skb, ntohs(len) +
-                                                       padding);
-                       if (!eth) {
-                               dev_kfree_skb(frame);
-                               goto purge;
-                       }
+                       offset += len + padding;
                }
 
                skb_reset_network_header(frame);
@@ -716,24 +793,20 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
 
                payload = frame->data;
                ethertype = (payload[6] << 8) | payload[7];
-
                if (likely((ether_addr_equal(payload, rfc1042_header) &&
                            ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
                           ether_addr_equal(payload, bridge_tunnel_header))) {
-                       /* remove RFC1042 or Bridge-Tunnel
-                        * encapsulation and replace EtherType */
-                       skb_pull(frame, 6);
-                       memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN);
-                       memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN);
-               } else {
-                       memcpy(skb_push(frame, sizeof(__be16)), &len,
-                               sizeof(__be16));
-                       memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN);
-                       memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN);
+                       eth.h_proto = htons(ethertype);
+                       skb_pull(frame, ETH_ALEN + 2);
                }
+
+               memcpy(skb_push(frame, sizeof(eth)), &eth, sizeof(eth));
                __skb_queue_tail(list, frame);
        }
 
+       if (!reuse_skb)
+               dev_kfree_skb(skb);
+
        return;
 
  purge:
index e882c832013558bc252963742f97afe21273e1e8..a8bf9081512b3c338803e2ec79247e83bacb0eeb 100644 (file)
 
 include ../../scripts/Makefile.include
 
-all: acpidump ec
-clean: acpidump_clean ec_clean
-install: acpidump_install ec_install
-uninstall: acpidump_uninstall ec_uninstall
+all: acpidbg acpidump ec
+clean: acpidbg_clean acpidump_clean ec_clean
+install: acpidbg_install acpidump_install ec_install
+uninstall: acpidbg_uninstall acpidump_uninstall ec_uninstall
 
-acpidump ec: FORCE
+acpidbg acpidump ec: FORCE
        $(call descend,tools/$@,all)
-acpidump_clean ec_clean:
+acpidbg_clean acpidump_clean ec_clean:
        $(call descend,tools/$(@:_clean=),clean)
-acpidump_install ec_install:
+acpidbg_install acpidump_install ec_install:
        $(call descend,tools/$(@:_install=),install)
-acpidump_uninstall ec_uninstall:
+acpidbg_uninstall acpidump_uninstall ec_uninstall:
        $(call descend,tools/$(@:_uninstall=),uninstall)
 
 .PHONY: FORCE
index 326e826a5d20ac5ee3829aea1aca23dfc964c2ce..efefe309367ac70b2b647ae0d70aa2fa476b80c3 100644 (file)
@@ -47,6 +47,7 @@
  * Option strings:
  *    "f"       - Option has no arguments
  *    "f:"      - Option requires an argument
+ *    "f+"      - Option has an optional argument
  *    "f^"      - Option has optional single-char sub-options
  *    "f|"      - Option has required single-char sub-options
  */
@@ -85,6 +86,7 @@ static int current_char_ptr = 1;
 
 int acpi_getopt_argument(int argc, char **argv)
 {
+
        acpi_gbl_optind--;
        current_char_ptr++;
 
index b51e40a9a12077d911da20246dea9ac65602d7f0..6df758302604e8a5b19d5aa2cf0d628290846017 100644 (file)
@@ -73,6 +73,7 @@ ACPI_FILE acpi_os_open_file(const char *path, u8 modes)
        if (modes & ACPI_FILE_WRITING) {
                modes_str[i++] = 'w';
        }
+
        if (modes & ACPI_FILE_BINARY) {
                modes_str[i++] = 'b';
        }
@@ -101,6 +102,7 @@ ACPI_FILE acpi_os_open_file(const char *path, u8 modes)
 
 void acpi_os_close_file(ACPI_FILE file)
 {
+
        fclose(file);
 }
 
@@ -202,6 +204,7 @@ acpi_status acpi_os_set_file_offset(ACPI_FILE file, long offset, u8 from)
        if (from == ACPI_FILE_BEGIN) {
                ret = fseek(file, offset, SEEK_SET);
        }
+
        if (from == ACPI_FILE_END) {
                ret = fseek(file, offset, SEEK_END);
        }
diff --git a/tools/power/acpi/tools/acpidbg/Makefile b/tools/power/acpi/tools/acpidbg/Makefile
new file mode 100644 (file)
index 0000000..352df4b
--- /dev/null
@@ -0,0 +1,27 @@
+# tools/power/acpi/tools/acpidbg/Makefile - ACPI tool Makefile
+#
+# Copyright (c) 2015, Intel Corporation
+#   Author: Lv Zheng <lv.zheng@intel.com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; version 2
+# of the License.
+
+include ../../Makefile.config
+
+TOOL = acpidbg
+vpath %.c \
+       ../../../../../drivers/acpi/acpica\
+       ../../common\
+       ../../os_specific/service_layers\
+       .
+CFLAGS += -DACPI_APPLICATION -DACPI_SINGLE_THREAD -DACPI_DEBUGGER\
+       -I.\
+       -I../../../../../drivers/acpi/acpica\
+       -I../../../../../include
+LDFLAGS += -lpthread
+TOOL_OBJS = \
+       acpidbg.o
+
+include ../../Makefile.rules
diff --git a/tools/power/acpi/tools/acpidbg/acpidbg.c b/tools/power/acpi/tools/acpidbg/acpidbg.c
new file mode 100644 (file)
index 0000000..d070fcc
--- /dev/null
@@ -0,0 +1,438 @@
+/*
+ * ACPI AML interfacing userspace utility
+ *
+ * Copyright (C) 2015, Intel Corporation
+ * Authors: Lv Zheng <lv.zheng@intel.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 <acpi/acpi.h>
+
+/* Headers not included by include/acpi/platform/aclinux.h */
+#include <stdbool.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <linux/circ_buf.h>
+
+#define ACPI_AML_FILE          "/sys/kernel/debug/acpi/acpidbg"
+#define ACPI_AML_SEC_TICK      1
+#define ACPI_AML_USEC_PEEK     200
+#define ACPI_AML_BUF_SIZE      4096
+
+#define ACPI_AML_BATCH_WRITE_CMD       0x00 /* Write command to kernel */
+#define ACPI_AML_BATCH_READ_LOG                0x01 /* Read log from kernel */
+#define ACPI_AML_BATCH_WRITE_LOG       0x02 /* Write log to console */
+
+#define ACPI_AML_LOG_START             0x00
+#define ACPI_AML_PROMPT_START          0x01
+#define ACPI_AML_PROMPT_STOP           0x02
+#define ACPI_AML_LOG_STOP              0x03
+#define ACPI_AML_PROMPT_ROLL           0x04
+
+#define ACPI_AML_INTERACTIVE   0x00
+#define ACPI_AML_BATCH         0x01
+
+#define circ_count(circ) \
+       (CIRC_CNT((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
+#define circ_count_to_end(circ) \
+       (CIRC_CNT_TO_END((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
+#define circ_space(circ) \
+       (CIRC_SPACE((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
+#define circ_space_to_end(circ) \
+       (CIRC_SPACE_TO_END((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
+
+#define acpi_aml_cmd_count()   circ_count(&acpi_aml_cmd_crc)
+#define acpi_aml_log_count()   circ_count(&acpi_aml_log_crc)
+#define acpi_aml_cmd_space()   circ_space(&acpi_aml_cmd_crc)
+#define acpi_aml_log_space()   circ_space(&acpi_aml_log_crc)
+
+#define ACPI_AML_DO(_fd, _op, _buf, _ret)                              \
+       do {                                                            \
+               _ret = acpi_aml_##_op(_fd, &acpi_aml_##_buf##_crc);     \
+               if (_ret == 0) {                                        \
+                       fprintf(stderr,                                 \
+                               "%s %s pipe closed.\n", #_buf, #_op);   \
+                       return;                                         \
+               }                                                       \
+       } while (0)
+#define ACPI_AML_BATCH_DO(_fd, _op, _buf, _ret)                                \
+       do {                                                            \
+               _ret = acpi_aml_##_op##_batch_##_buf(_fd,               \
+                        &acpi_aml_##_buf##_crc);                       \
+               if (_ret == 0)                                          \
+                       return;                                         \
+       } while (0)
+
+
+static char acpi_aml_cmd_buf[ACPI_AML_BUF_SIZE];
+static char acpi_aml_log_buf[ACPI_AML_BUF_SIZE];
+static struct circ_buf acpi_aml_cmd_crc = {
+       .buf = acpi_aml_cmd_buf,
+       .head = 0,
+       .tail = 0,
+};
+static struct circ_buf acpi_aml_log_crc = {
+       .buf = acpi_aml_log_buf,
+       .head = 0,
+       .tail = 0,
+};
+static const char *acpi_aml_file_path = ACPI_AML_FILE;
+static unsigned long acpi_aml_mode = ACPI_AML_INTERACTIVE;
+static bool acpi_aml_exit;
+
+static bool acpi_aml_batch_drain;
+static unsigned long acpi_aml_batch_state;
+static char acpi_aml_batch_prompt;
+static char acpi_aml_batch_roll;
+static unsigned long acpi_aml_log_state;
+static char *acpi_aml_batch_cmd = NULL;
+static char *acpi_aml_batch_pos = NULL;
+
+static int acpi_aml_set_fl(int fd, int flags)
+{
+       int ret;
+
+       ret = fcntl(fd, F_GETFL, 0);
+       if (ret < 0) {
+               perror("fcntl(F_GETFL)");
+               return ret;
+       }
+       flags |= ret;
+       ret = fcntl(fd, F_SETFL, flags);
+       if (ret < 0) {
+               perror("fcntl(F_SETFL)");
+               return ret;
+       }
+       return ret;
+}
+
+static int acpi_aml_set_fd(int fd, int maxfd, fd_set *set)
+{
+       if (fd > maxfd)
+               maxfd = fd;
+       FD_SET(fd, set);
+       return maxfd;
+}
+
+static int acpi_aml_read(int fd, struct circ_buf *crc)
+{
+       char *p;
+       int len;
+
+       p = &crc->buf[crc->head];
+       len = circ_space_to_end(crc);
+       len = read(fd, p, len);
+       if (len < 0)
+               perror("read");
+       else if (len > 0)
+               crc->head = (crc->head + len) & (ACPI_AML_BUF_SIZE - 1);
+       return len;
+}
+
+static int acpi_aml_read_batch_cmd(int unused, struct circ_buf *crc)
+{
+       char *p;
+       int len;
+       int remained = strlen(acpi_aml_batch_pos);
+
+       p = &crc->buf[crc->head];
+       len = circ_space_to_end(crc);
+       if (len > remained) {
+               memcpy(p, acpi_aml_batch_pos, remained);
+               acpi_aml_batch_pos += remained;
+               len = remained;
+       } else {
+               memcpy(p, acpi_aml_batch_pos, len);
+               acpi_aml_batch_pos += len;
+       }
+       if (len > 0)
+               crc->head = (crc->head + len) & (ACPI_AML_BUF_SIZE - 1);
+       return len;
+}
+
+static int acpi_aml_read_batch_log(int fd, struct circ_buf *crc)
+{
+       char *p;
+       int len;
+       int ret = 0;
+
+       p = &crc->buf[crc->head];
+       len = circ_space_to_end(crc);
+       while (ret < len && acpi_aml_log_state != ACPI_AML_LOG_STOP) {
+               if (acpi_aml_log_state == ACPI_AML_PROMPT_ROLL) {
+                       *p = acpi_aml_batch_roll;
+                       len = 1;
+                       crc->head = (crc->head + 1) & (ACPI_AML_BUF_SIZE - 1);
+                       ret += 1;
+                       acpi_aml_log_state = ACPI_AML_LOG_START;
+               } else {
+                       len = read(fd, p, 1);
+                       if (len <= 0) {
+                               if (len < 0)
+                                       perror("read");
+                               ret = len;
+                               break;
+                       }
+               }
+               switch (acpi_aml_log_state) {
+               case ACPI_AML_LOG_START:
+                       if (*p == '\n')
+                               acpi_aml_log_state = ACPI_AML_PROMPT_START;
+                       crc->head = (crc->head + 1) & (ACPI_AML_BUF_SIZE - 1);
+                       ret += 1;
+                       break;
+               case ACPI_AML_PROMPT_START:
+                       if (*p == ACPI_DEBUGGER_COMMAND_PROMPT ||
+                           *p == ACPI_DEBUGGER_EXECUTE_PROMPT) {
+                               acpi_aml_batch_prompt = *p;
+                               acpi_aml_log_state = ACPI_AML_PROMPT_STOP;
+                       } else {
+                               if (*p != '\n')
+                                       acpi_aml_log_state = ACPI_AML_LOG_START;
+                               crc->head = (crc->head + 1) & (ACPI_AML_BUF_SIZE - 1);
+                               ret += 1;
+                       }
+                       break;
+               case ACPI_AML_PROMPT_STOP:
+                       if (*p == ' ') {
+                               acpi_aml_log_state = ACPI_AML_LOG_STOP;
+                               acpi_aml_exit = true;
+                       } else {
+                               /* Roll back */
+                               acpi_aml_log_state = ACPI_AML_PROMPT_ROLL;
+                               acpi_aml_batch_roll = *p;
+                               *p = acpi_aml_batch_prompt;
+                               crc->head = (crc->head + 1) & (ACPI_AML_BUF_SIZE - 1);
+                               ret += 1;
+                       }
+                       break;
+               default:
+                       assert(0);
+                       break;
+               }
+       }
+       return ret;
+}
+
+static int acpi_aml_write(int fd, struct circ_buf *crc)
+{
+       char *p;
+       int len;
+
+       p = &crc->buf[crc->tail];
+       len = circ_count_to_end(crc);
+       len = write(fd, p, len);
+       if (len < 0)
+               perror("write");
+       else if (len > 0)
+               crc->tail = (crc->tail + len) & (ACPI_AML_BUF_SIZE - 1);
+       return len;
+}
+
+static int acpi_aml_write_batch_log(int fd, struct circ_buf *crc)
+{
+       char *p;
+       int len;
+
+       p = &crc->buf[crc->tail];
+       len = circ_count_to_end(crc);
+       if (!acpi_aml_batch_drain) {
+               len = write(fd, p, len);
+               if (len < 0)
+                       perror("write");
+       }
+       if (len > 0)
+               crc->tail = (crc->tail + len) & (ACPI_AML_BUF_SIZE - 1);
+       return len;
+}
+
+static int acpi_aml_write_batch_cmd(int fd, struct circ_buf *crc)
+{
+       int len;
+
+       len = acpi_aml_write(fd, crc);
+       if (circ_count_to_end(crc) == 0)
+               acpi_aml_batch_state = ACPI_AML_BATCH_READ_LOG;
+       return len;
+}
+
+static void acpi_aml_loop(int fd)
+{
+       fd_set rfds;
+       fd_set wfds;
+       struct timeval tv;
+       int ret;
+       int maxfd = 0;
+
+       if (acpi_aml_mode == ACPI_AML_BATCH) {
+               acpi_aml_log_state = ACPI_AML_LOG_START;
+               acpi_aml_batch_pos = acpi_aml_batch_cmd;
+               if (acpi_aml_batch_drain)
+                       acpi_aml_batch_state = ACPI_AML_BATCH_READ_LOG;
+               else
+                       acpi_aml_batch_state = ACPI_AML_BATCH_WRITE_CMD;
+       }
+       acpi_aml_exit = false;
+       while (!acpi_aml_exit) {
+               tv.tv_sec = ACPI_AML_SEC_TICK;
+               tv.tv_usec = 0;
+               FD_ZERO(&rfds);
+               FD_ZERO(&wfds);
+
+               if (acpi_aml_cmd_space()) {
+                       if (acpi_aml_mode == ACPI_AML_INTERACTIVE)
+                               maxfd = acpi_aml_set_fd(STDIN_FILENO, maxfd, &rfds);
+                       else if (strlen(acpi_aml_batch_pos) &&
+                                acpi_aml_batch_state == ACPI_AML_BATCH_WRITE_CMD)
+                               ACPI_AML_BATCH_DO(STDIN_FILENO, read, cmd, ret);
+               }
+               if (acpi_aml_cmd_count() &&
+                   (acpi_aml_mode == ACPI_AML_INTERACTIVE ||
+                    acpi_aml_batch_state == ACPI_AML_BATCH_WRITE_CMD))
+                       maxfd = acpi_aml_set_fd(fd, maxfd, &wfds);
+               if (acpi_aml_log_space() &&
+                   (acpi_aml_mode == ACPI_AML_INTERACTIVE ||
+                    acpi_aml_batch_state == ACPI_AML_BATCH_READ_LOG))
+                       maxfd = acpi_aml_set_fd(fd, maxfd, &rfds);
+               if (acpi_aml_log_count())
+                       maxfd = acpi_aml_set_fd(STDOUT_FILENO, maxfd, &wfds);
+
+               ret = select(maxfd+1, &rfds, &wfds, NULL, &tv);
+               if (ret < 0) {
+                       perror("select");
+                       break;
+               }
+               if (ret > 0) {
+                       if (FD_ISSET(STDIN_FILENO, &rfds))
+                               ACPI_AML_DO(STDIN_FILENO, read, cmd, ret);
+                       if (FD_ISSET(fd, &wfds)) {
+                               if (acpi_aml_mode == ACPI_AML_BATCH)
+                                       ACPI_AML_BATCH_DO(fd, write, cmd, ret);
+                               else
+                                       ACPI_AML_DO(fd, write, cmd, ret);
+                       }
+                       if (FD_ISSET(fd, &rfds)) {
+                               if (acpi_aml_mode == ACPI_AML_BATCH)
+                                       ACPI_AML_BATCH_DO(fd, read, log, ret);
+                               else
+                                       ACPI_AML_DO(fd, read, log, ret);
+                       }
+                       if (FD_ISSET(STDOUT_FILENO, &wfds)) {
+                               if (acpi_aml_mode == ACPI_AML_BATCH)
+                                       ACPI_AML_BATCH_DO(STDOUT_FILENO, write, log, ret);
+                               else
+                                       ACPI_AML_DO(STDOUT_FILENO, write, log, ret);
+                       }
+               }
+       }
+}
+
+static bool acpi_aml_readable(int fd)
+{
+       fd_set rfds;
+       struct timeval tv;
+       int ret;
+       int maxfd = 0;
+
+       tv.tv_sec = 0;
+       tv.tv_usec = ACPI_AML_USEC_PEEK;
+       FD_ZERO(&rfds);
+       maxfd = acpi_aml_set_fd(fd, maxfd, &rfds);
+       ret = select(maxfd+1, &rfds, NULL, NULL, &tv);
+       if (ret < 0)
+               perror("select");
+       if (ret > 0 && FD_ISSET(fd, &rfds))
+               return true;
+       return false;
+}
+
+/*
+ * This is a userspace IO flush implementation, replying on the prompt
+ * characters and can be turned into a flush() call after kernel implements
+ * .flush() filesystem operation.
+ */
+static void acpi_aml_flush(int fd)
+{
+       while (acpi_aml_readable(fd)) {
+               acpi_aml_batch_drain = true;
+               acpi_aml_loop(fd);
+               acpi_aml_batch_drain = false;
+       }
+}
+
+void usage(FILE *file, char *progname)
+{
+       fprintf(file, "usage: %s [-b cmd] [-f file] [-h]\n", progname);
+       fprintf(file, "\nOptions:\n");
+       fprintf(file, "  -b     Specify command to be executed in batch mode\n");
+       fprintf(file, "  -f     Specify interface file other than");
+       fprintf(file, "         /sys/kernel/debug/acpi/acpidbg\n");
+       fprintf(file, "  -h     Print this help message\n");
+}
+
+int main(int argc, char **argv)
+{
+       int fd = 0;
+       int ch;
+       int len;
+       int ret = EXIT_SUCCESS;
+
+       while ((ch = getopt(argc, argv, "b:f:h")) != -1) {
+               switch (ch) {
+               case 'b':
+                       if (acpi_aml_batch_cmd) {
+                               fprintf(stderr, "Already specify %s\n",
+                                       acpi_aml_batch_cmd);
+                               ret = EXIT_FAILURE;
+                               goto exit;
+                       }
+                       len = strlen(optarg);
+                       acpi_aml_batch_cmd = calloc(len + 2, 1);
+                       if (!acpi_aml_batch_cmd) {
+                               perror("calloc");
+                               ret = EXIT_FAILURE;
+                               goto exit;
+                       }
+                       memcpy(acpi_aml_batch_cmd, optarg, len);
+                       acpi_aml_batch_cmd[len] = '\n';
+                       acpi_aml_mode = ACPI_AML_BATCH;
+                       break;
+               case 'f':
+                       acpi_aml_file_path = optarg;
+                       break;
+               case 'h':
+                       usage(stdout, argv[0]);
+                       goto exit;
+                       break;
+               case '?':
+               default:
+                       usage(stderr, argv[0]);
+                       ret = EXIT_FAILURE;
+                       goto exit;
+                       break;
+               }
+       }
+
+       fd = open(acpi_aml_file_path, O_RDWR | O_NONBLOCK);
+       if (fd < 0) {
+               perror("open");
+               ret = EXIT_FAILURE;
+               goto exit;
+       }
+       acpi_aml_set_fl(STDIN_FILENO, O_NONBLOCK);
+       acpi_aml_set_fl(STDOUT_FILENO, O_NONBLOCK);
+
+       if (acpi_aml_mode == ACPI_AML_BATCH)
+               acpi_aml_flush(fd);
+       acpi_aml_loop(fd);
+
+exit:
+       if (fd < 0)
+               close(fd);
+       if (acpi_aml_batch_cmd)
+               free(acpi_aml_batch_cmd);
+       return ret;
+}
index a1c62de42a3bc479e04818df981885eb2e458a47..bbdf9e8e25bc64fb655cb9bfa0dd0d14b11577ac 100644 (file)
 
 static int ap_is_existing_file(char *pathname);
 
+/******************************************************************************
+ *
+ * FUNCTION:    ap_is_existing_file
+ *
+ * PARAMETERS:  pathname            - Output filename
+ *
+ * RETURN:      0 on success
+ *
+ * DESCRIPTION: Query for file overwrite if it already exists.
+ *
+ ******************************************************************************/
+
 static int ap_is_existing_file(char *pathname)
 {
 #ifndef _GNU_EFI
@@ -136,6 +148,7 @@ int ap_write_to_binary_file(struct acpi_table_header *table, u32 instance)
        } else {
                ACPI_MOVE_NAME(filename, table->signature);
        }
+
        filename[0] = (char)tolower((int)filename[0]);
        filename[1] = (char)tolower((int)filename[1]);
        filename[2] = (char)tolower((int)filename[2]);
index 2e2ba2efa0d9f97629ec5af9fb1136b3dee8962d..0adaf0c7c03a0f47985f5d6e116ae249df64bd83 100644 (file)
@@ -47,6 +47,11 @@ NLS ?=               true
 # cpufreq-bench benchmarking tool
 CPUFREQ_BENCH ?= true
 
+# Do not build libraries, but build the code in statically
+# Libraries are still built, otherwise the Makefile code would
+# be rather ugly.
+export STATIC ?= false
+
 # Prefix to the directories we're installing to
 DESTDIR ?=
 
@@ -161,6 +166,12 @@ ifeq ($(strip $(CPUFREQ_BENCH)),true)
        COMPILE_BENCH += compile-bench
 endif
 
+ifeq ($(strip $(STATIC)),true)
+        UTIL_OBJS += $(LIB_OBJS)
+        UTIL_HEADERS += $(LIB_HEADERS)
+        UTIL_SRC += $(LIB_SRC)
+endif
+
 CFLAGS += $(WARNINGS)
 
 ifeq ($(strip $(V)),false)
@@ -209,7 +220,11 @@ $(OUTPUT)%.o: %.c
 
 $(OUTPUT)cpupower: $(UTIL_OBJS) $(OUTPUT)libcpupower.so.$(LIB_MAJ)
        $(ECHO) "  CC      " $@
+ifeq ($(strip $(STATIC)),true)
+       $(QUIET) $(CC) $(CFLAGS) $(LDFLAGS) $(UTIL_OBJS) -lrt -lpci -L$(OUTPUT) -o $@
+else
        $(QUIET) $(CC) $(CFLAGS) $(LDFLAGS) $(UTIL_OBJS) -lcpupower -lrt -lpci -L$(OUTPUT) -o $@
+endif
        $(QUIET) $(STRIPCMD) $@
 
 $(OUTPUT)po/$(PACKAGE).pot: $(UTIL_SRC)
@@ -291,7 +306,11 @@ install-bench:
        @#DESTDIR must be set from outside to survive
        @sbindir=$(sbindir) bindir=$(bindir) docdir=$(docdir) confdir=$(confdir) $(MAKE) -C bench O=$(OUTPUT) install
 
+ifeq ($(strip $(STATIC)),true)
+install: all install-tools install-man $(INSTALL_NLS) $(INSTALL_BENCH)
+else
 install: all install-lib install-tools install-man $(INSTALL_NLS) $(INSTALL_BENCH)
+endif
 
 uninstall:
        - rm -f $(DESTDIR)${libdir}/libcpupower.*
index 7ec7021a29cd8d37a9abf4ecc08c396d50368501..d0f879b223fc24b28f5c6126f153321191afb62f 100644 (file)
@@ -5,9 +5,15 @@ ifneq ($(O),)
 endif
 endif
 
+ifeq ($(strip $(STATIC)),true)
+LIBS = -L../ -L$(OUTPUT) -lm
+OBJS = $(OUTPUT)main.o $(OUTPUT)parse.o $(OUTPUT)system.o $(OUTPUT)benchmark.o \
+       $(OUTPUT)../lib/cpufreq.o $(OUTPUT)../lib/sysfs.o
+else
 LIBS = -L../ -L$(OUTPUT) -lm -lcpupower
-
 OBJS = $(OUTPUT)main.o $(OUTPUT)parse.o $(OUTPUT)system.o $(OUTPUT)benchmark.o
+endif
+
 CFLAGS += -D_GNU_SOURCE -I../lib -DDEFAULT_CONFIG_FILE=\"$(confdir)/cpufreq-bench.conf\"
 
 $(OUTPUT)%.o : %.c
index 0e676433024109bef6d9a87e08709c40be37b2df..8f3f5bb9c74ef514fd003990e20dce019603b6ea 100644 (file)
@@ -14,6 +14,7 @@
 #include <getopt.h>
 
 #include "cpufreq.h"
+#include "helpers/sysfs.h"
 #include "helpers/helpers.h"
 #include "helpers/bitmask.h"
 
@@ -244,149 +245,21 @@ static int get_boost_mode(unsigned int cpu)
        return 0;
 }
 
-static void debug_output_one(unsigned int cpu)
-{
-       char *driver;
-       struct cpufreq_affected_cpus *cpus;
-       struct cpufreq_available_frequencies *freqs;
-       unsigned long min, max, freq_kernel, freq_hardware;
-       unsigned long total_trans, latency;
-       unsigned long long total_time;
-       struct cpufreq_policy *policy;
-       struct cpufreq_available_governors *governors;
-       struct cpufreq_stats *stats;
-
-       if (cpufreq_cpu_exists(cpu))
-               return;
-
-       freq_kernel = cpufreq_get_freq_kernel(cpu);
-       freq_hardware = cpufreq_get_freq_hardware(cpu);
-
-       driver = cpufreq_get_driver(cpu);
-       if (!driver) {
-               printf(_("  no or unknown cpufreq driver is active on this CPU\n"));
-       } else {
-               printf(_("  driver: %s\n"), driver);
-               cpufreq_put_driver(driver);
-       }
-
-       cpus = cpufreq_get_related_cpus(cpu);
-       if (cpus) {
-               printf(_("  CPUs which run at the same hardware frequency: "));
-               while (cpus->next) {
-                       printf("%d ", cpus->cpu);
-                       cpus = cpus->next;
-               }
-               printf("%d\n", cpus->cpu);
-               cpufreq_put_related_cpus(cpus);
-       }
-
-       cpus = cpufreq_get_affected_cpus(cpu);
-       if (cpus) {
-               printf(_("  CPUs which need to have their frequency coordinated by software: "));
-               while (cpus->next) {
-                       printf("%d ", cpus->cpu);
-                       cpus = cpus->next;
-               }
-               printf("%d\n", cpus->cpu);
-               cpufreq_put_affected_cpus(cpus);
-       }
-
-       latency = cpufreq_get_transition_latency(cpu);
-       if (latency) {
-               printf(_("  maximum transition latency: "));
-               print_duration(latency);
-               printf(".\n");
-       }
-
-       if (!(cpufreq_get_hardware_limits(cpu, &min, &max))) {
-               printf(_("  hardware limits: "));
-               print_speed(min);
-               printf(" - ");
-               print_speed(max);
-               printf("\n");
-       }
-
-       freqs = cpufreq_get_available_frequencies(cpu);
-       if (freqs) {
-               printf(_("  available frequency steps: "));
-               while (freqs->next) {
-                       print_speed(freqs->frequency);
-                       printf(", ");
-                       freqs = freqs->next;
-               }
-               print_speed(freqs->frequency);
-               printf("\n");
-               cpufreq_put_available_frequencies(freqs);
-       }
-
-       governors = cpufreq_get_available_governors(cpu);
-       if (governors) {
-               printf(_("  available cpufreq governors: "));
-               while (governors->next) {
-                       printf("%s, ", governors->governor);
-                       governors = governors->next;
-               }
-               printf("%s\n", governors->governor);
-               cpufreq_put_available_governors(governors);
-       }
-
-       policy = cpufreq_get_policy(cpu);
-       if (policy) {
-               printf(_("  current policy: frequency should be within "));
-               print_speed(policy->min);
-               printf(_(" and "));
-               print_speed(policy->max);
-
-               printf(".\n                  ");
-               printf(_("The governor \"%s\" may"
-                      " decide which speed to use\n                  within this range.\n"),
-                      policy->governor);
-               cpufreq_put_policy(policy);
-       }
-
-       if (freq_kernel || freq_hardware) {
-               printf(_("  current CPU frequency is "));
-               if (freq_hardware) {
-                       print_speed(freq_hardware);
-                       printf(_(" (asserted by call to hardware)"));
-               } else
-                       print_speed(freq_kernel);
-               printf(".\n");
-       }
-       stats = cpufreq_get_stats(cpu, &total_time);
-       if (stats) {
-               printf(_("  cpufreq stats: "));
-               while (stats) {
-                       print_speed(stats->frequency);
-                       printf(":%.2f%%", (100.0 * stats->time_in_state) / total_time);
-                       stats = stats->next;
-                       if (stats)
-                               printf(", ");
-               }
-               cpufreq_put_stats(stats);
-               total_trans = cpufreq_get_transitions(cpu);
-               if (total_trans)
-                       printf("  (%lu)\n", total_trans);
-               else
-                       printf("\n");
-       }
-       get_boost_mode(cpu);
-
-}
-
 /* --freq / -f */
 
 static int get_freq_kernel(unsigned int cpu, unsigned int human)
 {
        unsigned long freq = cpufreq_get_freq_kernel(cpu);
-       if (!freq)
+       printf(_("  current CPU frequency: "));
+       if (!freq) {
+               printf(_(" Unable to call to kernel\n"));
                return -EINVAL;
+       }
        if (human) {
                print_speed(freq);
-               printf("\n");
        } else
-               printf("%lu\n", freq);
+               printf("%lu", freq);
+       printf(_(" (asserted by call to kernel)\n"));
        return 0;
 }
 
@@ -396,13 +269,16 @@ static int get_freq_kernel(unsigned int cpu, unsigned int human)
 static int get_freq_hardware(unsigned int cpu, unsigned int human)
 {
        unsigned long freq = cpufreq_get_freq_hardware(cpu);
-       if (!freq)
+       printf(_("  current CPU frequency: "));
+       if (!freq) {
+               printf("Unable to call hardware\n");
                return -EINVAL;
+       }
        if (human) {
                print_speed(freq);
-               printf("\n");
        } else
-               printf("%lu\n", freq);
+               printf("%lu", freq);
+       printf(_(" (asserted by call to hardware)\n"));
        return 0;
 }
 
@@ -411,9 +287,17 @@ static int get_freq_hardware(unsigned int cpu, unsigned int human)
 static int get_hardware_limits(unsigned int cpu)
 {
        unsigned long min, max;
-       if (cpufreq_get_hardware_limits(cpu, &min, &max))
+
+       printf(_("  hardware limits: "));
+       if (cpufreq_get_hardware_limits(cpu, &min, &max)) {
+               printf(_("Not Available\n"));
                return -EINVAL;
-       printf("%lu %lu\n", min, max);
+       }
+
+       print_speed(min);
+       printf(" - ");
+       print_speed(max);
+       printf("\n");
        return 0;
 }
 
@@ -422,9 +306,11 @@ static int get_hardware_limits(unsigned int cpu)
 static int get_driver(unsigned int cpu)
 {
        char *driver = cpufreq_get_driver(cpu);
-       if (!driver)
+       if (!driver) {
+               printf(_("  no or unknown cpufreq driver is active on this CPU\n"));
                return -EINVAL;
-       printf("%s\n", driver);
+       }
+       printf("  driver: %s\n", driver);
        cpufreq_put_driver(driver);
        return 0;
 }
@@ -434,9 +320,19 @@ static int get_driver(unsigned int cpu)
 static int get_policy(unsigned int cpu)
 {
        struct cpufreq_policy *policy = cpufreq_get_policy(cpu);
-       if (!policy)
+       if (!policy) {
+               printf(_("  Unable to determine current policy\n"));
                return -EINVAL;
-       printf("%lu %lu %s\n", policy->min, policy->max, policy->governor);
+       }
+       printf(_("  current policy: frequency should be within "));
+       print_speed(policy->min);
+       printf(_(" and "));
+       print_speed(policy->max);
+
+       printf(".\n                  ");
+       printf(_("The governor \"%s\" may decide which speed to use\n"
+              "                  within this range.\n"),
+              policy->governor);
        cpufreq_put_policy(policy);
        return 0;
 }
@@ -447,8 +343,12 @@ static int get_available_governors(unsigned int cpu)
 {
        struct cpufreq_available_governors *governors =
                cpufreq_get_available_governors(cpu);
-       if (!governors)
+
+       printf(_("  available cpufreq governors: "));
+       if (!governors) {
+               printf(_("Not Available\n"));
                return -EINVAL;
+       }
 
        while (governors->next) {
                printf("%s ", governors->governor);
@@ -465,8 +365,12 @@ static int get_available_governors(unsigned int cpu)
 static int get_affected_cpus(unsigned int cpu)
 {
        struct cpufreq_affected_cpus *cpus = cpufreq_get_affected_cpus(cpu);
-       if (!cpus)
+
+       printf(_("  CPUs which need to have their frequency coordinated by software: "));
+       if (!cpus) {
+               printf(_("Not Available\n"));
                return -EINVAL;
+       }
 
        while (cpus->next) {
                printf("%d ", cpus->cpu);
@@ -482,8 +386,12 @@ static int get_affected_cpus(unsigned int cpu)
 static int get_related_cpus(unsigned int cpu)
 {
        struct cpufreq_affected_cpus *cpus = cpufreq_get_related_cpus(cpu);
-       if (!cpus)
+
+       printf(_("  CPUs which run at the same hardware frequency: "));
+       if (!cpus) {
+               printf(_("Not Available\n"));
                return -EINVAL;
+       }
 
        while (cpus->next) {
                printf("%d ", cpus->cpu);
@@ -524,8 +432,12 @@ static int get_freq_stats(unsigned int cpu, unsigned int human)
 static int get_latency(unsigned int cpu, unsigned int human)
 {
        unsigned long latency = cpufreq_get_transition_latency(cpu);
-       if (!latency)
+
+       printf(_("  maximum transition latency: "));
+       if (!latency || latency == UINT_MAX) {
+               printf(_(" Cannot determine or is not supported.\n"));
                return -EINVAL;
+       }
 
        if (human) {
                print_duration(latency);
@@ -535,6 +447,36 @@ static int get_latency(unsigned int cpu, unsigned int human)
        return 0;
 }
 
+static void debug_output_one(unsigned int cpu)
+{
+       struct cpufreq_available_frequencies *freqs;
+
+       get_driver(cpu);
+       get_related_cpus(cpu);
+       get_affected_cpus(cpu);
+       get_latency(cpu, 1);
+       get_hardware_limits(cpu);
+
+       freqs = cpufreq_get_available_frequencies(cpu);
+       if (freqs) {
+               printf(_("  available frequency steps:  "));
+               while (freqs->next) {
+                       print_speed(freqs->frequency);
+                       printf(", ");
+                       freqs = freqs->next;
+               }
+               print_speed(freqs->frequency);
+               printf("\n");
+               cpufreq_put_available_frequencies(freqs);
+       }
+
+       get_available_governors(cpu);
+       get_policy(cpu);
+       if (get_freq_hardware(cpu, 1) < 0)
+               get_freq_kernel(cpu, 1);
+       get_boost_mode(cpu);
+}
+
 static struct option info_opts[] = {
        {"debug",        no_argument,            NULL,   'e'},
        {"boost",        no_argument,            NULL,   'b'},
@@ -647,11 +589,14 @@ int cmd_freq_info(int argc, char **argv)
 
                if (!bitmask_isbitset(cpus_chosen, cpu))
                        continue;
-               if (cpufreq_cpu_exists(cpu)) {
-                       printf(_("couldn't analyze CPU %d as it doesn't seem to be present\n"), cpu);
+
+               printf(_("analyzing CPU %d:\n"), cpu);
+
+               if (sysfs_is_cpu_online(cpu) != 1) {
+                       printf(_(" *is offline\n"));
+                       printf("\n");
                        continue;
                }
-               printf(_("analyzing CPU %d:\n"), cpu);
 
                switch (output_param) {
                case 'b':
@@ -693,6 +638,7 @@ int cmd_freq_info(int argc, char **argv)
                }
                if (ret)
                        return ret;
+               printf("\n");
        }
        return ret;
 }
index 750c1d82c3f7b7f16a3eea71df3c9d6e7a4ceb7d..8bf8ab5ffa25d18580a850eb79b276fed712cfbf 100644 (file)
@@ -12,7 +12,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <getopt.h>
-#include <cpufreq.h>
 
 #include "helpers/helpers.h"
 #include "helpers/sysfs.h"
@@ -25,8 +24,6 @@ static void cpuidle_cpu_output(unsigned int cpu, int verbose)
        unsigned int idlestates, idlestate;
        char *tmp;
 
-       printf(_ ("Analyzing CPU %d:\n"), cpu);
-
        idlestates = sysfs_get_idlestate_count(cpu);
        if (idlestates == 0) {
                printf(_("CPU %u: No idle states\n"), cpu);
@@ -71,7 +68,6 @@ static void cpuidle_cpu_output(unsigned int cpu, int verbose)
                printf(_("Duration: %llu\n"),
                       sysfs_get_idlestate_time(cpu, idlestate));
        }
-       printf("\n");
 }
 
 static void cpuidle_general_output(void)
@@ -189,10 +185,17 @@ int cmd_idle_info(int argc, char **argv)
        for (cpu = bitmask_first(cpus_chosen);
             cpu <= bitmask_last(cpus_chosen); cpu++) {
 
-               if (!bitmask_isbitset(cpus_chosen, cpu) ||
-                   cpufreq_cpu_exists(cpu))
+               if (!bitmask_isbitset(cpus_chosen, cpu))
                        continue;
 
+               printf(_("analyzing CPU %d:\n"), cpu);
+
+               if (sysfs_is_cpu_online(cpu) != 1) {
+                       printf(_(" *is offline\n"));
+                       printf("\n");
+                       continue;
+               }
+
                switch (output_param) {
 
                case 'o':
@@ -203,6 +206,7 @@ int cmd_idle_info(int argc, char **argv)
                        cpuidle_cpu_output(cpu, verbose);
                        break;
                }
+               printf("\n");
        }
        return EXIT_SUCCESS;
 }
index 10299f2e9d2a6917f0601dd07eedb0ff03c6bc92..c7caa8eaa6d06e13581c597724cc9452a6957cca 100644 (file)
@@ -12,7 +12,6 @@
 #include <string.h>
 #include <getopt.h>
 
-#include <cpufreq.h>
 #include "helpers/helpers.h"
 #include "helpers/sysfs.h"
 
@@ -83,12 +82,16 @@ int cmd_info(int argc, char **argv)
        for (cpu = bitmask_first(cpus_chosen);
             cpu <= bitmask_last(cpus_chosen); cpu++) {
 
-               if (!bitmask_isbitset(cpus_chosen, cpu) ||
-                   cpufreq_cpu_exists(cpu))
+               if (!bitmask_isbitset(cpus_chosen, cpu))
                        continue;
 
                printf(_("analyzing CPU %d:\n"), cpu);
 
+               if (sysfs_is_cpu_online(cpu) != 1){
+                       printf(_(" *is offline\n"));
+                       continue;
+               }
+
                if (params.perf_bias) {
                        ret = msr_intel_get_perf_bias(cpu);
                        if (ret < 0) {
index 3e6f374f8dd73ddc1fd1b6d3b30f175fcc7f9e4b..532f46b9a3351d33848cccce2c5d212ff6fd671a 100644 (file)
@@ -12,7 +12,6 @@
 #include <string.h>
 #include <getopt.h>
 
-#include <cpufreq.h>
 #include "helpers/helpers.h"
 #include "helpers/sysfs.h"
 #include "helpers/bitmask.h"
@@ -78,10 +77,15 @@ int cmd_set(int argc, char **argv)
        for (cpu = bitmask_first(cpus_chosen);
             cpu <= bitmask_last(cpus_chosen); cpu++) {
 
-               if (!bitmask_isbitset(cpus_chosen, cpu) ||
-                   cpufreq_cpu_exists(cpu))
+               if (!bitmask_isbitset(cpus_chosen, cpu))
                        continue;
 
+               if (sysfs_is_cpu_online(cpu) != 1){
+                       fprintf(stderr, _("Cannot set values on CPU %d:"), cpu);
+                       fprintf(stderr, _(" *is offline\n"));
+                       continue;
+               }
+
                if (params.perf_bias) {
                        ret = msr_intel_set_perf_bias(cpu, perf_bias);
                        if (ret) {
index 9cbb7fd7517122c423d316efb5e736a52c799d3a..5f9c908f4557e8cadd14d5e4ee1a0c2017cad1f5 100644 (file)
@@ -106,7 +106,7 @@ int get_cpu_topology(struct cpupower_topology *cpu_top)
                        cpu_top->pkgs++;
                }
        }
-       if (!cpu_top->core_info[0].pkg == -1)
+       if (!(cpu_top->core_info[0].pkg == -1))
                cpu_top->pkgs++;
 
        /* Intel's cores count is not consecutively numbered, there may
diff --git a/tools/testing/selftests/ftrace/test.d/instances/instance.tc b/tools/testing/selftests/ftrace/test.d/instances/instance.tc
new file mode 100644 (file)
index 0000000..773e276
--- /dev/null
@@ -0,0 +1,90 @@
+#!/bin/sh
+# description: Test creation and deletion of trace instances
+
+if [ ! -d instances ] ; then
+    echo "no instance directory with this kernel"
+    exit_unsupported;
+fi
+
+fail() { # mesg
+    rmdir x y z 2>/dev/null
+    echo $1
+    set -e
+    exit $FAIL
+}
+
+cd instances
+
+# we don't want to fail on error
+set +e
+
+mkdir x
+rmdir x
+result=$?
+
+if [ $result -ne 0 ]; then
+    echo "instance rmdir not supported"
+    exit_unsupported
+fi
+
+instance_slam() {
+    while :; do
+       mkdir x
+       mkdir y
+       mkdir z
+       rmdir x
+       rmdir y
+       rmdir z
+    done 2>/dev/null
+}
+
+instance_slam &
+x=`jobs -l`
+p1=`echo $x | cut -d' ' -f2`
+echo $p1
+
+instance_slam &
+x=`jobs -l | tail -1`
+p2=`echo $x | cut -d' ' -f2`
+echo $p2
+
+instance_slam &
+x=`jobs -l | tail -1`
+p3=`echo $x | cut -d' ' -f2`
+echo $p3
+
+instance_slam &
+x=`jobs -l | tail -1`
+p4=`echo $x | cut -d' ' -f2`
+echo $p4
+
+instance_slam &
+x=`jobs -l | tail -1`
+p5=`echo $x | cut -d' ' -f2`
+echo $p5
+
+ls -lR >/dev/null
+sleep 1
+
+kill -1 $p1
+kill -1 $p2
+kill -1 $p3
+kill -1 $p4
+kill -1 $p5
+
+echo "Wait for processes to finish"
+wait $p1 $p2 $p3 $p4 $p5
+echo "all processes finished, wait for cleanup"
+
+mkdir x y z
+ls x y z
+rmdir x y z
+for d in x y z; do
+        if [ -d $d ]; then
+                fail "instance $d still exists"
+        fi
+done
+
+set -e
+
+exit 0