Merge tag 'pm+acpi-3.18-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 24 Oct 2014 18:29:31 +0000 (11:29 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 24 Oct 2014 18:29:31 +0000 (11:29 -0700)
Pull ACPI and power management updates from Rafael Wysocki:
 "This is material that didn't make it to my 3.18-rc1 pull request for
  various reasons, mostly related to timing and travel (LinuxCon EU /
  LPC) plus a couple of fixes for recent bugs.

  The only really new thing here is the PM QoS class for memory
  bandwidth, but it is simple enough and users of it will be added in
  the next cycle.  One major change in behavior is that platform devices
  enumerated by ACPI will use 32-bit DMA mask by default.  Also included
  is an ACPICA update to a new upstream release, but that's mostly
  cleanups, changes in tools and similar.  The rest is fixes and
  cleanups mostly.

  Specifics:

   - Fix for a recent PCI power management change that overlooked the
     fact that some IRQ chips might not be able to configure PCIe PME
     for system wakeup from Lucas Stach.

   - Fix for a bug introduced in 3.17 where acpi_device_wakeup() is
     called with a wrong ordering of arguments from Zhang Rui.

   - A bunch of intel_pstate driver fixes (all -stable candidates) from
     Dirk Brandewie, Gabriele Mazzotta and Pali Roh├ír.

   - Fixes for a rather long-standing problem with the OOM killer and
     the freezer that frozen processes killed by the OOM do not actually
     release any memory until they are thawed, so OOM-killing them is
     rather pointless, with a couple of cleanups on top (Michal Hocko,
     Cong Wang, Rafael J Wysocki).

   - ACPICA update to upstream release 20140926, inlcuding mostly
     cleanups reducing differences between the upstream ACPICA and the
     kernel code, tools changes (acpidump, acpiexec) and support for the
     _DDN object (Bob Moore, Lv Zheng).

   - New PM QoS class for memory bandwidth from Tomeu Vizoso.

   - Default 32-bit DMA mask for platform devices enumerated by ACPI
     (this change is mostly needed for some drivers development in
     progress targeted at 3.19) from Heikki Krogerus.

   - ACPI EC driver cleanups, mostly related to debugging, from Lv
     Zheng.

   - cpufreq-dt driver updates from Thomas Petazzoni.

   - powernv cpuidle driver update from Preeti U Murthy"

* tag 'pm+acpi-3.18-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (34 commits)
  intel_pstate: Correct BYT VID values.
  intel_pstate: Fix BYT frequency reporting
  intel_pstate: Don't lose sysfs settings during cpu offline
  cpufreq: intel_pstate: Reflect current no_turbo state correctly
  cpufreq: expose scaling_cur_freq sysfs file for set_policy() drivers
  cpufreq: intel_pstate: Fix setting max_perf_pct in performance policy
  PCI / PM: handle failure to enable wakeup on PCIe PME
  ACPI: invoke acpi_device_wakeup() with correct parameters
  PM / freezer: Clean up code after recent fixes
  PM: convert do_each_thread to for_each_process_thread
  OOM, PM: OOM killed task shouldn't escape PM suspend
  freezer: remove obsolete comments in __thaw_task()
  freezer: Do not freeze tasks killed by OOM killer
  ACPI / platform: provide default DMA mask
  cpuidle: powernv: Populate cpuidle state details by querying the device-tree
  cpufreq: cpufreq-dt: adjust message related to regulators
  cpufreq: cpufreq-dt: extend with platform_data
  cpufreq: allow driver-specific data
  ACPI / EC: Cleanup coding style.
  ACPI / EC: Refine event/query debugging messages.
  ...

311 files changed:
Documentation/devicetree/bindings/mailbox/mailbox.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pwm/pwm-fsl-ftm.txt
Documentation/devicetree/bindings/pwm/pwm-rockchip.txt
Documentation/devicetree/bindings/thermal/imx-thermal.txt
Documentation/devicetree/bindings/watchdog/cadence-wdt.txt [new file with mode: 0644]
Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.txt
Documentation/devicetree/bindings/watchdog/meson6-wdt.txt [new file with mode: 0644]
Documentation/devicetree/bindings/watchdog/qcom-wdt.txt [new file with mode: 0644]
Documentation/devicetree/bindings/watchdog/samsung-wdt.txt
Documentation/kernel-parameters.txt
Documentation/mailbox.txt [new file with mode: 0644]
Documentation/scsi/osd.txt
Documentation/target/tcmu-design.txt [new file with mode: 0644]
MAINTAINERS
arch/arc/Kconfig
arch/arc/Makefile
arch/arc/boot/dts/angel4.dts
arch/arc/boot/dts/nsimosci.dts
arch/arc/configs/fpga_defconfig
arch/arc/configs/fpga_noramfs_defconfig
arch/arc/configs/nsimosci_defconfig
arch/arc/include/asm/arcregs.h
arch/arc/include/asm/atomic.h
arch/arc/include/asm/bitops.h
arch/arc/include/asm/bug.h
arch/arc/include/asm/cache.h
arch/arc/include/asm/current.h
arch/arc/include/asm/irqflags.h
arch/arc/include/asm/kgdb.h
arch/arc/include/asm/processor.h
arch/arc/include/asm/setup.h
arch/arc/include/asm/smp.h
arch/arc/include/asm/string.h
arch/arc/include/asm/syscalls.h
arch/arc/include/asm/thread_info.h
arch/arc/include/asm/unaligned.h
arch/arc/kernel/Makefile
arch/arc/kernel/disasm.c
arch/arc/kernel/head.S
arch/arc/kernel/kgdb.c
arch/arc/kernel/perf_event.c
arch/arc/kernel/setup.c
arch/arc/kernel/smp.c
arch/arc/mm/cache_arc700.c
arch/arc/mm/tlb.c
arch/arc/plat-arcfpga/Kconfig
arch/arc/plat-arcfpga/include/plat/irq.h [deleted file]
arch/arc/plat-arcfpga/include/plat/memmap.h [deleted file]
arch/arc/plat-arcfpga/platform.c
arch/arc/plat-arcfpga/smp.c
arch/arc/plat-tb10x/Kconfig
arch/arc/plat-tb10x/tb10x.c
arch/arm/configs/multi_v7_defconfig
arch/arm/mach-highbank/highbank.c
arch/arm64/kernel/efi.c
arch/ia64/kernel/efi.c
arch/powerpc/configs/pseries_le_defconfig
arch/powerpc/include/asm/eeh.h
arch/powerpc/include/asm/perf_event.h
arch/powerpc/include/asm/reg.h
arch/powerpc/include/asm/syscall.h
arch/powerpc/kernel/dma.c
arch/powerpc/kernel/eeh.c
arch/powerpc/kernel/eeh_driver.c
arch/powerpc/kernel/eeh_pe.c
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/irq.c
arch/powerpc/kernel/misc.S
arch/powerpc/kernel/ppc_ksyms.c
arch/powerpc/kernel/process.c
arch/powerpc/kernel/rtas_pci.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/kernel/stacktrace.c
arch/powerpc/mm/numa.c
arch/powerpc/platforms/powernv/eeh-ioda.c
arch/powerpc/platforms/powernv/eeh-powernv.c
arch/powerpc/platforms/powernv/opal.c
arch/powerpc/platforms/powernv/pci.c
arch/powerpc/platforms/pseries/dlpar.c
arch/powerpc/platforms/pseries/hotplug-cpu.c
arch/powerpc/platforms/pseries/iommu.c
arch/powerpc/platforms/pseries/pseries.h
arch/powerpc/sysdev/msi_bitmap.c
arch/s390/include/uapi/asm/unistd.h
arch/s390/kernel/compat_wrapper.c
arch/s390/kernel/syscalls.S
arch/s390/kernel/uprobes.c
arch/s390/lib/probes.c
arch/s390/mm/pgtable.c
arch/x86/boot/compressed/eboot.c
arch/x86/include/asm/efi.h
arch/x86/platform/efi/efi-bgrt.c
arch/x86/platform/efi/efi.c
arch/x86/platform/efi/efi_32.c
arch/x86/platform/efi/efi_64.c
arch/x86/platform/efi/efi_stub_32.S
arch/x86/platform/intel-mid/intel_mid_weak_decls.h
drivers/acpi/Kconfig
drivers/acpi/Makefile
drivers/acpi/acpi_platform.c
drivers/acpi/device_pm.c
drivers/acpi/fan.c
drivers/acpi/int340x_thermal.c [new file with mode: 0644]
drivers/acpi/internal.h
drivers/acpi/scan.c
drivers/acpi/thermal.c
drivers/acpi/utils.c
drivers/cpufreq/highbank-cpufreq.c
drivers/firmware/efi/efi.c
drivers/firmware/efi/libstub/arm-stub.c
drivers/firmware/efi/libstub/efi-stub-helper.c
drivers/firmware/efi/runtime-wrappers.c
drivers/firmware/efi/vars.c
drivers/gpu/drm/cirrus/cirrus_drv.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_panel.c
drivers/gpu/drm/nouveau/core/engine/graph/ctxnv50.c
drivers/gpu/drm/nouveau/nouveau_chan.c
drivers/gpu/drm/qxl/qxl_display.c
drivers/gpu/drm/radeon/btc_dpm.c
drivers/gpu/drm/radeon/btc_dpm.h
drivers/gpu/drm/radeon/ci_dpm.c
drivers/gpu/drm/radeon/cik_sdma.c
drivers/gpu/drm/radeon/cypress_dpm.c
drivers/gpu/drm/radeon/dce3_1_afmt.c
drivers/gpu/drm/radeon/dce6_afmt.c
drivers/gpu/drm/radeon/evergreen_hdmi.c
drivers/gpu/drm/radeon/ni_dpm.c
drivers/gpu/drm/radeon/r600_dma.c
drivers/gpu/drm/radeon/r600_dpm.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/rs780_dpm.c
drivers/gpu/drm/radeon/rv6xx_dpm.c
drivers/gpu/drm/radeon/rv770_dpm.c
drivers/gpu/drm/radeon/si_dpm.c
drivers/gpu/drm/radeon/sumo_dpm.c
drivers/gpu/drm/radeon/trinity_dpm.c
drivers/gpu/drm/ttm/ttm_bo.c
drivers/hwmon/menf21bmc_hwmon.c
drivers/infiniband/ulp/isert/ib_isert.c
drivers/leds/led-class.c
drivers/leds/led-core.c
drivers/leds/leds-gpio-register.c
drivers/leds/leds-gpio.c
drivers/leds/leds-lp3944.c
drivers/leds/trigger/ledtrig-gpio.c
drivers/mailbox/Makefile
drivers/mailbox/mailbox.c [new file with mode: 0644]
drivers/mailbox/pl320-ipc.c
drivers/pwm/Kconfig
drivers/pwm/Makefile
drivers/pwm/core.c
drivers/pwm/pwm-atmel.c
drivers/pwm/pwm-fsl-ftm.c
drivers/pwm/pwm-imx.c
drivers/pwm/pwm-lpss-pci.c [new file with mode: 0644]
drivers/pwm/pwm-lpss-platform.c [new file with mode: 0644]
drivers/pwm/pwm-lpss.c
drivers/pwm/pwm-lpss.h [new file with mode: 0644]
drivers/pwm/pwm-rockchip.c
drivers/rtc/Kconfig
drivers/rtc/rtc-efi.c
drivers/s390/char/Kconfig
drivers/scsi/osd/Kbuild
drivers/scsi/osd/Kconfig
drivers/scsi/osd/osd_debug.h
drivers/scsi/osd/osd_initiator.c
drivers/scsi/osd/osd_uld.c
drivers/scsi/qla2xxx/qla_target.c
drivers/scsi/qla2xxx/qla_target.h
drivers/scsi/qla2xxx/tcm_qla2xxx.c
drivers/target/Kconfig
drivers/target/Makefile
drivers/target/iscsi/iscsi_target.c
drivers/target/iscsi/iscsi_target_configfs.c
drivers/target/iscsi/iscsi_target_erl0.c
drivers/target/iscsi/iscsi_target_login.c
drivers/target/iscsi/iscsi_target_util.c
drivers/target/loopback/tcm_loop.c
drivers/target/target_core_alua.c
drivers/target/target_core_configfs.c
drivers/target/target_core_device.c
drivers/target/target_core_fabric_configfs.c
drivers/target/target_core_fabric_lib.c
drivers/target/target_core_file.c
drivers/target/target_core_internal.h
drivers/target/target_core_pr.c
drivers/target/target_core_pr.h
drivers/target/target_core_pscsi.c
drivers/target/target_core_sbc.c
drivers/target/target_core_tmr.c
drivers/target/target_core_tpg.c
drivers/target/target_core_transport.c
drivers/target/target_core_ua.c
drivers/target/target_core_ua.h
drivers/target/target_core_user.c [new file with mode: 0644]
drivers/target/tcm_fc/tfc_sess.c
drivers/thermal/Kconfig
drivers/thermal/Makefile
drivers/thermal/fair_share.c
drivers/thermal/gov_bang_bang.c [new file with mode: 0644]
drivers/thermal/imx_thermal.c
drivers/thermal/int3403_thermal.c [deleted file]
drivers/thermal/int340x_thermal/Makefile [new file with mode: 0644]
drivers/thermal/int340x_thermal/acpi_thermal_rel.c [new file with mode: 0644]
drivers/thermal/int340x_thermal/acpi_thermal_rel.h [new file with mode: 0644]
drivers/thermal/int340x_thermal/int3400_thermal.c [new file with mode: 0644]
drivers/thermal/int340x_thermal/int3402_thermal.c [new file with mode: 0644]
drivers/thermal/int340x_thermal/int3403_thermal.c [new file with mode: 0644]
drivers/thermal/of-thermal.c
drivers/thermal/step_wise.c
drivers/thermal/thermal_core.c
drivers/thermal/thermal_core.h
drivers/uio/uio.c
drivers/watchdog/Kconfig
drivers/watchdog/Makefile
drivers/watchdog/booke_wdt.c
drivers/watchdog/cadence_wdt.c [new file with mode: 0644]
drivers/watchdog/da9063_wdt.c [new file with mode: 0644]
drivers/watchdog/dw_wdt.c
drivers/watchdog/imx2_wdt.c
drivers/watchdog/meson_wdt.c [new file with mode: 0644]
drivers/watchdog/of_xilinx_wdt.c
drivers/watchdog/qcom-wdt.c [new file with mode: 0644]
drivers/watchdog/rn5t618_wdt.c [new file with mode: 0644]
drivers/watchdog/s3c2410_wdt.c
drivers/watchdog/stmp3xxx_rtc_wdt.c
drivers/watchdog/sunxi_wdt.c
drivers/watchdog/ts72xx_wdt.c
fs/buffer.c
fs/exofs/Kbuild
fs/exofs/common.h
fs/exofs/dir.c
fs/exofs/exofs.h
fs/exofs/file.c
fs/exofs/inode.c
fs/exofs/namei.c
fs/exofs/ore.c
fs/exofs/ore_raid.c
fs/exofs/ore_raid.h
fs/exofs/super.c
fs/exofs/symlink.c
fs/exofs/sys.c
fs/ext4/balloc.c
fs/ext4/bitmap.c
fs/ext4/dir.c
fs/ext4/ext4.h
fs/ext4/ext4_extents.h
fs/ext4/ext4_jbd2.c
fs/ext4/ext4_jbd2.h
fs/ext4/extents.c
fs/ext4/extents_status.c
fs/ext4/extents_status.h
fs/ext4/ialloc.c
fs/ext4/indirect.c
fs/ext4/inline.c
fs/ext4/inode.c
fs/ext4/ioctl.c
fs/ext4/mballoc.c
fs/ext4/migrate.c
fs/ext4/mmp.c
fs/ext4/move_extent.c
fs/ext4/namei.c
fs/ext4/resize.c
fs/ext4/super.c
fs/ext4/xattr.c
fs/jbd/journal.c
fs/jbd2/checkpoint.c
fs/jbd2/journal.c
fs/jbd2/recovery.c
fs/nfs/objlayout/objio_osd.c
fs/nfs/objlayout/objlayout.c
fs/nfs/objlayout/objlayout.h
fs/nfs/objlayout/pnfs_osd_xdr_cli.c
include/acpi/acpi_bus.h
include/linux/acpi.h
include/linux/audit.h
include/linux/buffer_head.h
include/linux/clocksource.h
include/linux/crash_dump.h
include/linux/efi.h
include/linux/jbd2.h
include/linux/kernel.h
include/linux/kgdb.h
include/linux/leds.h
include/linux/mailbox_client.h [new file with mode: 0644]
include/linux/mailbox_controller.h [new file with mode: 0644]
include/linux/memory.h
include/linux/mm.h
include/linux/pl320-ipc.h [moved from include/linux/mailbox.h with 100% similarity]
include/linux/pnfs_osd_xdr.h
include/linux/thermal.h
include/linux/uio_driver.h
include/linux/uprobes.h
include/linux/watchdog.h
include/scsi/osd_initiator.h
include/scsi/osd_ore.h
include/scsi/osd_protocol.h
include/scsi/osd_sec.h
include/scsi/osd_sense.h
include/scsi/osd_types.h
include/target/target_core_base.h
include/trace/events/ext4.h
include/trace/events/thermal.h [new file with mode: 0644]
include/uapi/linux/Kbuild
include/uapi/linux/target_core_user.h [new file with mode: 0644]
lib/cmdline.c
mm/truncate.c

diff --git a/Documentation/devicetree/bindings/mailbox/mailbox.txt b/Documentation/devicetree/bindings/mailbox/mailbox.txt
new file mode 100644 (file)
index 0000000..1a2cd3d
--- /dev/null
@@ -0,0 +1,38 @@
+* Generic Mailbox Controller and client driver bindings
+
+Generic binding to provide a way for Mailbox controller drivers to
+assign appropriate mailbox channel to client drivers.
+
+* Mailbox Controller
+
+Required property:
+- #mbox-cells: Must be at least 1. Number of cells in a mailbox
+               specifier.
+
+Example:
+       mailbox: mailbox {
+               ...
+               #mbox-cells = <1>;
+       };
+
+
+* Mailbox Client
+
+Required property:
+- mboxes: List of phandle and mailbox channel specifiers.
+
+Optional property:
+- mbox-names: List of identifier strings for each mailbox channel
+               required by the client. The use of this property
+               is discouraged in favor of using index in list of
+               'mboxes' while requesting a mailbox. Instead the
+               platforms may define channel indices, in DT headers,
+               to something legible.
+
+Example:
+       pwr_cntrl: power {
+               ...
+               mbox-names = "pwr-ctrl", "rpc";
+               mboxes = <&mailbox 0
+                       &mailbox 1>;
+       };
index 0bda229a6171d219a393d7133305a5853943bd1a..3899d6a557c15af8482f3c0574404e437b462e5d 100644 (file)
@@ -1,5 +1,20 @@
 Freescale FlexTimer Module (FTM) PWM controller
 
+The same FTM PWM device can have a different endianness on different SoCs. The
+device tree provides a property to describing this so that an operating system
+device driver can handle all variants of the device. Refer to the table below
+for the endianness of the FTM PWM block as integrated into the existing SoCs:
+
+       SoC     | FTM-PWM endianness
+       --------+-------------------
+       Vybrid  | LE
+       LS1     | BE
+       LS2     | LE
+
+Please see ../regmap/regmap.txt for more detail about how to specify endian
+modes in device tree.
+
+
 Required properties:
 - compatible: Should be "fsl,vf610-ftm-pwm".
 - reg: Physical base address and length of the controller's registers
@@ -16,7 +31,8 @@ Required properties:
 - pinctrl-names: Must contain a "default" entry.
 - pinctrl-NNN: One property must exist for each entry in pinctrl-names.
   See pinctrl/pinctrl-bindings.txt for details of the property values.
-
+- big-endian: Boolean property, required if the FTM PWM registers use a big-
+  endian rather than little-endian layout.
 
 Example:
 
@@ -32,4 +48,5 @@ pwm0: pwm@40038000 {
                        <&clks VF610_CLK_FTM0_EXT_FIX_EN>;
                pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_pwm0_1>;
+               big-endian;
 };
index d47d15a6a2985e7f3eae08db0d9ad3986e80c227..b8be3d09ee26b7522fa373eefd1903aef8ce3d41 100644 (file)
@@ -7,8 +7,8 @@ Required properties:
    "rockchip,vop-pwm": found integrated in VOP on RK3288 SoC
  - reg: physical base address and length of the controller's registers
  - clocks: phandle and clock specifier of the PWM reference clock
- - #pwm-cells: should be 2. See pwm.txt in this directory for a
-   description of the cell format.
+ - #pwm-cells: must be 2 (rk2928) or 3 (rk3288). See pwm.txt in this directory
+   for a description of the cell format.
 
 Example:
 
index 1f0f67234a917bae606b17ad2432e45d7d171895..3c67bd50aa104ee152ea22132c377dcd2e6d3673 100644 (file)
@@ -1,7 +1,10 @@
 * Temperature Monitor (TEMPMON) on Freescale i.MX SoCs
 
 Required properties:
-- compatible : "fsl,imx6q-thermal"
+- compatible : "fsl,imx6q-tempmon" for i.MX6Q, "fsl,imx6sx-tempmon" for i.MX6SX.
+  i.MX6SX has two more IRQs than i.MX6Q, one is IRQ_LOW and the other is IRQ_PANIC,
+  when temperature is below than low threshold, IRQ_LOW will be triggered, when temperature
+  is higher than panic threshold, system will auto reboot by SRC module.
 - fsl,tempmon : phandle pointer to system controller that contains TEMPMON
   control registers, e.g. ANATOP on imx6q.
 - fsl,tempmon-data : phandle pointer to fuse controller that contains TEMPMON
diff --git a/Documentation/devicetree/bindings/watchdog/cadence-wdt.txt b/Documentation/devicetree/bindings/watchdog/cadence-wdt.txt
new file mode 100644 (file)
index 0000000..c3a36ee
--- /dev/null
@@ -0,0 +1,24 @@
+Zynq Watchdog Device Tree Bindings
+-------------------------------------------
+
+Required properties:
+- compatible           : Should be "cdns,wdt-r1p2".
+- clocks               : This is pclk (APB clock).
+- interrupts           : This is wd_irq - watchdog timeout interrupt.
+- interrupt-parent     : Must be core interrupt controller.
+
+Optional properties
+- reset-on-timeout     : If this property exists, then a reset is done
+                         when watchdog times out.
+- timeout-sec          : Watchdog timeout value (in seconds).
+
+Example:
+       watchdog@f8005000 {
+               compatible = "cdns,wdt-r1p2";
+               clocks = <&clkc 45>;
+               interrupt-parent = <&intc>;
+               interrupts = <0 9 1>;
+               reg = <0xf8005000 0x1000>;
+               reset-on-timeout;
+               timeout-sec = <10>;
+       };
index e52ba2da868ce120daf7348aa15cdda02fcc34af..8dab6fd024aa4edb889b880db02225e13cb44c61 100644 (file)
@@ -7,7 +7,8 @@ Required properties:
 
 Optional property:
 - big-endian: If present the watchdog device's registers are implemented
-  in big endian mode, otherwise in little mode.
+  in big endian mode, otherwise in native mode(same with CPU), for more
+  detail please see: Documentation/devicetree/bindings/regmap/regmap.txt.
 
 Examples:
 
diff --git a/Documentation/devicetree/bindings/watchdog/meson6-wdt.txt b/Documentation/devicetree/bindings/watchdog/meson6-wdt.txt
new file mode 100644 (file)
index 0000000..9200fc2
--- /dev/null
@@ -0,0 +1,13 @@
+Meson SoCs Watchdog timer
+
+Required properties:
+
+- compatible : should be "amlogic,meson6-wdt"
+- reg : Specifies base physical address and size of the registers.
+
+Example:
+
+wdt: watchdog@c1109900 {
+       compatible = "amlogic,meson6-wdt";
+       reg = <0xc1109900 0x8>;
+};
diff --git a/Documentation/devicetree/bindings/watchdog/qcom-wdt.txt b/Documentation/devicetree/bindings/watchdog/qcom-wdt.txt
new file mode 100644 (file)
index 0000000..4726924
--- /dev/null
@@ -0,0 +1,24 @@
+Qualcomm Krait Processor Sub-system (KPSS) Watchdog
+---------------------------------------------------
+
+Required properties :
+- compatible : shall contain only one of the following:
+
+                       "qcom,kpss-wdt-msm8960"
+                       "qcom,kpss-wdt-apq8064"
+                       "qcom,kpss-wdt-ipq8064"
+
+- reg : shall contain base register location and length
+- clocks : shall contain the input clock
+
+Optional properties :
+- timeout-sec : shall contain the default watchdog timeout in seconds,
+                if unset, the default timeout is 30 seconds
+
+Example:
+       watchdog@208a038 {
+               compatible = "qcom,kpss-wdt-ipq8064";
+               reg = <0x0208a038 0x40>;
+               clocks = <&sleep_clk>;
+               timeout-sec = <10>;
+       };
index cfff37511aac0e3e1f3d42f6e9805c087a8bc286..8f3d96af81d70303e5bb449ecc366a85846bdd00 100644 (file)
@@ -9,6 +9,7 @@ Required properties:
        (a) "samsung,s3c2410-wdt" for Exynos4 and previous SoCs
        (b) "samsung,exynos5250-wdt" for Exynos5250
        (c) "samsung,exynos5420-wdt" for Exynos5420
+       (c) "samsung,exynos7-wdt" for Exynos7
 
 - reg : base physical address of the controller and length of memory mapped
        region.
index 7dbe5ec9d9cd08afac13797e2adac291fb703eec..74339c57b914f94caa72bc67dc3b416674f9b76b 100644 (file)
@@ -1015,10 +1015,14 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        Format: {"off" | "on" | "skip[mbr]"}
 
        efi=            [EFI]
-                       Format: { "old_map" }
+                       Format: { "old_map", "nochunk", "noruntime" }
                        old_map [X86-64]: switch to the old ioremap-based EFI
                        runtime services mapping. 32-bit still uses this one by
                        default.
+                       nochunk: disable reading files in "chunks" in the EFI
+                       boot stub, as chunking can cause problems with some
+                       firmware implementations.
+                       noruntime : disable EFI runtime services support
 
        efi_no_storage_paranoia [EFI; X86]
                        Using this parameter you can use more than 50% of
@@ -2232,7 +2236,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 
        nodsp           [SH] Disable hardware DSP at boot time.
 
-       noefi           [X86] Disable EFI runtime services support.
+       noefi           Disable EFI runtime services support.
 
        noexec          [IA-64]
 
@@ -3465,6 +3469,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        e.g. base its process migration decisions on it.
                        Default is on.
 
+       topology_updates= [KNL, PPC, NUMA]
+                       Format: {off}
+                       Specify if the kernel should ignore (off)
+                       topology updates sent by the hypervisor to this
+                       LPAR.
+
        tp720=          [HW,PS2]
 
        tpm_suspend_pcr=[HW,TPM]
diff --git a/Documentation/mailbox.txt b/Documentation/mailbox.txt
new file mode 100644 (file)
index 0000000..60f43ff
--- /dev/null
@@ -0,0 +1,122 @@
+               The Common Mailbox Framework
+               Jassi Brar <jaswinder.singh@linaro.org>
+
+ This document aims to help developers write client and controller
+drivers for the API. But before we start, let us note that the
+client (especially) and controller drivers are likely going to be
+very platform specific because the remote firmware is likely to be
+proprietary and implement non-standard protocol. So even if two
+platforms employ, say, PL320 controller, the client drivers can't
+be shared across them. Even the PL320 driver might need to accommodate
+some platform specific quirks. So the API is meant mainly to avoid
+similar copies of code written for each platform. Having said that,
+nothing prevents the remote f/w to also be Linux based and use the
+same api there. However none of that helps us locally because we only
+ever deal at client's protocol level.
+ Some of the choices made during implementation are the result of this
+peculiarity of this "common" framework.
+
+
+
+       Part 1 - Controller Driver (See include/linux/mailbox_controller.h)
+
+ Allocate mbox_controller and the array of mbox_chan.
+Populate mbox_chan_ops, except peek_data() all are mandatory.
+The controller driver might know a message has been consumed
+by the remote by getting an IRQ or polling some hardware flag
+or it can never know (the client knows by way of the protocol).
+The method in order of preference is IRQ -> Poll -> None, which
+the controller driver should set via 'txdone_irq' or 'txdone_poll'
+or neither.
+
+
+       Part 2 - Client Driver (See include/linux/mailbox_client.h)
+
+ The client might want to operate in blocking mode (synchronously
+send a message through before returning) or non-blocking/async mode (submit
+a message and a callback function to the API and return immediately).
+
+
+struct demo_client {
+       struct mbox_client cl;
+       struct mbox_chan *mbox;
+       struct completion c;
+       bool async;
+       /* ... */
+};
+
+/*
+ * This is the handler for data received from remote. The behaviour is purely
+ * dependent upon the protocol. This is just an example.
+ */
+static void message_from_remote(struct mbox_client *cl, void *mssg)
+{
+       struct demo_client *dc = container_of(mbox_client,
+                                               struct demo_client, cl);
+       if (dc->aysnc) {
+               if (is_an_ack(mssg)) {
+                       /* An ACK to our last sample sent */
+                       return; /* Or do something else here */
+               } else { /* A new message from remote */
+                       queue_req(mssg);
+               }
+       } else {
+               /* Remote f/w sends only ACK packets on this channel */
+               return;
+       }
+}
+
+static void sample_sent(struct mbox_client *cl, void *mssg, int r)
+{
+       struct demo_client *dc = container_of(mbox_client,
+                                               struct demo_client, cl);
+       complete(&dc->c);
+}
+
+static void client_demo(struct platform_device *pdev)
+{
+       struct demo_client *dc_sync, *dc_async;
+       /* The controller already knows async_pkt and sync_pkt */
+       struct async_pkt ap;
+       struct sync_pkt sp;
+
+       dc_sync = kzalloc(sizeof(*dc_sync), GFP_KERNEL);
+       dc_async = kzalloc(sizeof(*dc_async), GFP_KERNEL);
+
+       /* Populate non-blocking mode client */
+       dc_async->cl.dev = &pdev->dev;
+       dc_async->cl.rx_callback = message_from_remote;
+       dc_async->cl.tx_done = sample_sent;
+       dc_async->cl.tx_block = false;
+       dc_async->cl.tx_tout = 0; /* doesn't matter here */
+       dc_async->cl.knows_txdone = false; /* depending upon protocol */
+       dc_async->async = true;
+       init_completion(&dc_async->c);
+
+       /* Populate blocking mode client */
+       dc_sync->cl.dev = &pdev->dev;
+       dc_sync->cl.rx_callback = message_from_remote;
+       dc_sync->cl.tx_done = NULL; /* operate in blocking mode */
+       dc_sync->cl.tx_block = true;
+       dc_sync->cl.tx_tout = 500; /* by half a second */
+       dc_sync->cl.knows_txdone = false; /* depending upon protocol */
+       dc_sync->async = false;
+
+       /* ASync mailbox is listed second in 'mboxes' property */
+       dc_async->mbox = mbox_request_channel(&dc_async->cl, 1);
+       /* Populate data packet */
+       /* ap.xxx = 123; etc */
+       /* Send async message to remote */
+       mbox_send_message(dc_async->mbox, &ap);
+
+       /* Sync mailbox is listed first in 'mboxes' property */
+       dc_sync->mbox = mbox_request_channel(&dc_sync->cl, 0);
+       /* Populate data packet */
+       /* sp.abc = 123; etc */
+       /* Send message to remote in blocking mode */
+       mbox_send_message(dc_sync->mbox, &sp);
+       /* At this point 'sp' has been sent */
+
+       /* Now wait for async chan to be done */
+       wait_for_completion(&dc_async->c);
+}
index da162f7fd5f5182893e249ac6423865fe627facf..5a9879bad07357a459aa9e9ba36a7686b090f0f3 100644 (file)
@@ -184,8 +184,7 @@ Any problems, questions, bug reports, lonely OSD nights, please email:
 More up-to-date information can be found on:
 http://open-osd.org
 
-Boaz Harrosh <bharrosh@panasas.com>
-Benny Halevy <bhalevy@panasas.com>
+Boaz Harrosh <ooo@electrozaur.com>
 
 References
 ==========
diff --git a/Documentation/target/tcmu-design.txt b/Documentation/target/tcmu-design.txt
new file mode 100644 (file)
index 0000000..5518465
--- /dev/null
@@ -0,0 +1,378 @@
+Contents:
+
+1) TCM Userspace Design
+  a) Background
+  b) Benefits
+  c) Design constraints
+  d) Implementation overview
+     i. Mailbox
+     ii. Command ring
+     iii. Data Area
+  e) Device discovery
+  f) Device events
+  g) Other contingencies
+2) Writing a user pass-through handler
+  a) Discovering and configuring TCMU uio devices
+  b) Waiting for events on the device(s)
+  c) Managing the command ring
+3) Command filtering and pass_level
+4) A final note
+
+
+TCM Userspace Design
+--------------------
+
+TCM is another name for LIO, an in-kernel iSCSI target (server).
+Existing TCM targets run in the kernel.  TCMU (TCM in Userspace)
+allows userspace programs to be written which act as iSCSI targets.
+This document describes the design.
+
+The existing kernel provides modules for different SCSI transport
+protocols.  TCM also modularizes the data storage.  There are existing
+modules for file, block device, RAM or using another SCSI device as
+storage.  These are called "backstores" or "storage engines".  These
+built-in modules are implemented entirely as kernel code.
+
+Background:
+
+In addition to modularizing the transport protocol used for carrying
+SCSI commands ("fabrics"), the Linux kernel target, LIO, also modularizes
+the actual data storage as well. These are referred to as "backstores"
+or "storage engines". The target comes with backstores that allow a
+file, a block device, RAM, or another SCSI device to be used for the
+local storage needed for the exported SCSI LUN. Like the rest of LIO,
+these are implemented entirely as kernel code.
+
+These backstores cover the most common use cases, but not all. One new
+use case that other non-kernel target solutions, such as tgt, are able
+to support is using Gluster's GLFS or Ceph's RBD as a backstore. The
+target then serves as a translator, allowing initiators to store data
+in these non-traditional networked storage systems, while still only
+using standard protocols themselves.
+
+If the target is a userspace process, supporting these is easy. tgt,
+for example, needs only a small adapter module for each, because the
+modules just use the available userspace libraries for RBD and GLFS.
+
+Adding support for these backstores in LIO is considerably more
+difficult, because LIO is entirely kernel code. Instead of undertaking
+the significant work to port the GLFS or RBD APIs and protocols to the
+kernel, another approach is to create a userspace pass-through
+backstore for LIO, "TCMU".
+
+
+Benefits:
+
+In addition to allowing relatively easy support for RBD and GLFS, TCMU
+will also allow easier development of new backstores. TCMU combines
+with the LIO loopback fabric to become something similar to FUSE
+(Filesystem in Userspace), but at the SCSI layer instead of the
+filesystem layer. A SUSE, if you will.
+
+The disadvantage is there are more distinct components to configure, and
+potentially to malfunction. This is unavoidable, but hopefully not
+fatal if we're careful to keep things as simple as possible.
+
+Design constraints:
+
+- Good performance: high throughput, low latency
+- Cleanly handle if userspace:
+   1) never attaches
+   2) hangs
+   3) dies
+   4) misbehaves
+- Allow future flexibility in user & kernel implementations
+- Be reasonably memory-efficient
+- Simple to configure & run
+- Simple to write a userspace backend
+
+
+Implementation overview:
+
+The core of the TCMU interface is a memory region that is shared
+between kernel and userspace. Within this region is: a control area
+(mailbox); a lockless producer/consumer circular buffer for commands
+to be passed up, and status returned; and an in/out data buffer area.
+
+TCMU uses the pre-existing UIO subsystem. UIO allows device driver
+development in userspace, and this is conceptually very close to the
+TCMU use case, except instead of a physical device, TCMU implements a
+memory-mapped layout designed for SCSI commands. Using UIO also
+benefits TCMU by handling device introspection (e.g. a way for
+userspace to determine how large the shared region is) and signaling
+mechanisms in both directions.
+
+There are no embedded pointers in the memory region. Everything is
+expressed as an offset from the region's starting address. This allows
+the ring to still work if the user process dies and is restarted with
+the region mapped at a different virtual address.
+
+See target_core_user.h for the struct definitions.
+
+The Mailbox:
+
+The mailbox is always at the start of the shared memory region, and
+contains a version, details about the starting offset and size of the
+command ring, and head and tail pointers to be used by the kernel and
+userspace (respectively) to put commands on the ring, and indicate
+when the commands are completed.
+
+version - 1 (userspace should abort if otherwise)
+flags - none yet defined.
+cmdr_off - The offset of the start of the command ring from the start
+of the memory region, to account for the mailbox size.
+cmdr_size - The size of the command ring. This does *not* need to be a
+power of two.
+cmd_head - Modified by the kernel to indicate when a command has been
+placed on the ring.
+cmd_tail - Modified by userspace to indicate when it has completed
+processing of a command.
+
+The Command Ring:
+
+Commands are placed on the ring by the kernel incrementing
+mailbox.cmd_head by the size of the command, modulo cmdr_size, and
+then signaling userspace via uio_event_notify(). Once the command is
+completed, userspace updates mailbox.cmd_tail in the same way and
+signals the kernel via a 4-byte write(). When cmd_head equals
+cmd_tail, the ring is empty -- no commands are currently waiting to be
+processed by userspace.
+
+TCMU commands start with a common header containing "len_op", a 32-bit
+value that stores the length, as well as the opcode in the lowest
+unused bits. Currently only two opcodes are defined, TCMU_OP_PAD and
+TCMU_OP_CMD. When userspace encounters a command with PAD opcode, it
+should skip ahead by the bytes in "length". (The kernel inserts PAD
+entries to ensure each CMD entry fits contigously into the circular
+buffer.)
+
+When userspace handles a CMD, it finds the SCSI CDB (Command Data
+Block) via tcmu_cmd_entry.req.cdb_off. This is an offset from the
+start of the overall shared memory region, not the entry. The data
+in/out buffers are accessible via tht req.iov[] array. Note that
+each iov.iov_base is also an offset from the start of the region.
+
+TCMU currently does not support BIDI operations.
+
+When completing a command, userspace sets rsp.scsi_status, and
+rsp.sense_buffer if necessary. Userspace then increments
+mailbox.cmd_tail by entry.hdr.length (mod cmdr_size) and signals the
+kernel via the UIO method, a 4-byte write to the file descriptor.
+
+The Data Area:
+
+This is shared-memory space after the command ring. The organization
+of this area is not defined in the TCMU interface, and userspace
+should access only the parts referenced by pending iovs.
+
+
+Device Discovery:
+
+Other devices may be using UIO besides TCMU. Unrelated user processes
+may also be handling different sets of TCMU devices. TCMU userspace
+processes must find their devices by scanning sysfs
+class/uio/uio*/name. For TCMU devices, these names will be of the
+format:
+
+tcm-user/<hba_num>/<device_name>/<subtype>/<path>
+
+where "tcm-user" is common for all TCMU-backed UIO devices. <hba_num>
+and <device_name> allow userspace to find the device's path in the
+kernel target's configfs tree. Assuming the usual mount point, it is
+found at:
+
+/sys/kernel/config/target/core/user_<hba_num>/<device_name>
+
+This location contains attributes such as "hw_block_size", that
+userspace needs to know for correct operation.
+
+<subtype> will be a userspace-process-unique string to identify the
+TCMU device as expecting to be backed by a certain handler, and <path>
+will be an additional handler-specific string for the user process to
+configure the device, if needed. The name cannot contain ':', due to
+LIO limitations.
+
+For all devices so discovered, the user handler opens /dev/uioX and
+calls mmap():
+
+mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)
+
+where size must be equal to the value read from
+/sys/class/uio/uioX/maps/map0/size.
+
+
+Device Events:
+
+If a new device is added or removed, a notification will be broadcast
+over netlink, using a generic netlink family name of "TCM-USER" and a
+multicast group named "config". This will include the UIO name as
+described in the previous section, as well as the UIO minor
+number. This should allow userspace to identify both the UIO device and
+the LIO device, so that after determining the device is supported
+(based on subtype) it can take the appropriate action.
+
+
+Other contingencies:
+
+Userspace handler process never attaches:
+
+- TCMU will post commands, and then abort them after a timeout period
+  (30 seconds.)
+
+Userspace handler process is killed:
+
+- It is still possible to restart and re-connect to TCMU
+  devices. Command ring is preserved. However, after the timeout period,
+  the kernel will abort pending tasks.
+
+Userspace handler process hangs:
+
+- The kernel will abort pending tasks after a timeout period.
+
+Userspace handler process is malicious:
+
+- The process can trivially break the handling of devices it controls,
+  but should not be able to access kernel memory outside its shared
+  memory areas.
+
+
+Writing a user pass-through handler (with example code)
+-------------------------------------------------------
+
+A user process handing a TCMU device must support the following:
+
+a) Discovering and configuring TCMU uio devices
+b) Waiting for events on the device(s)
+c) Managing the command ring: Parsing operations and commands,
+   performing work as needed, setting response fields (scsi_status and
+   possibly sense_buffer), updating cmd_tail, and notifying the kernel
+   that work has been finished
+
+First, consider instead writing a plugin for tcmu-runner. tcmu-runner
+implements all of this, and provides a higher-level API for plugin
+authors.
+
+TCMU is designed so that multiple unrelated processes can manage TCMU
+devices separately. All handlers should make sure to only open their
+devices, based opon a known subtype string.
+
+a) Discovering and configuring TCMU UIO devices:
+
+(error checking omitted for brevity)
+
+int fd, dev_fd;
+char buf[256];
+unsigned long long map_len;
+void *map;
+
+fd = open("/sys/class/uio/uio0/name", O_RDONLY);
+ret = read(fd, buf, sizeof(buf));
+close(fd);
+buf[ret-1] = '\0'; /* null-terminate and chop off the \n */
+
+/* we only want uio devices whose name is a format we expect */
+if (strncmp(buf, "tcm-user", 8))
+       exit(-1);
+
+/* Further checking for subtype also needed here */
+
+fd = open(/sys/class/uio/%s/maps/map0/size, O_RDONLY);
+ret = read(fd, buf, sizeof(buf));
+close(fd);
+str_buf[ret-1] = '\0'; /* null-terminate and chop off the \n */
+
+map_len = strtoull(buf, NULL, 0);
+
+dev_fd = open("/dev/uio0", O_RDWR);
+map = mmap(NULL, map_len, PROT_READ|PROT_WRITE, MAP_SHARED, dev_fd, 0);
+
+
+b) Waiting for events on the device(s)
+
+while (1) {
+  char buf[4];
+
+  int ret = read(dev_fd, buf, 4); /* will block */
+
+  handle_device_events(dev_fd, map);
+}
+
+
+c) Managing the command ring
+
+#include <linux/target_core_user.h>
+
+int handle_device_events(int fd, void *map)
+{
+  struct tcmu_mailbox *mb = map;
+  struct tcmu_cmd_entry *ent = (void *) mb + mb->cmdr_off + mb->cmd_tail;
+  int did_some_work = 0;
+
+  /* Process events from cmd ring until we catch up with cmd_head */
+  while (ent != (void *)mb + mb->cmdr_off + mb->cmd_head) {
+
+    if (tcmu_hdr_get_op(&ent->hdr) == TCMU_OP_CMD) {
+      uint8_t *cdb = (void *)mb + ent->req.cdb_off;
+      bool success = true;
+
+      /* Handle command here. */
+      printf("SCSI opcode: 0x%x\n", cdb[0]);
+
+      /* Set response fields */
+      if (success)
+        ent->rsp.scsi_status = SCSI_NO_SENSE;
+      else {
+        /* Also fill in rsp->sense_buffer here */
+        ent->rsp.scsi_status = SCSI_CHECK_CONDITION;
+      }
+    }
+    else {
+      /* Do nothing for PAD entries */
+    }
+
+    /* update cmd_tail */
+    mb->cmd_tail = (mb->cmd_tail + tcmu_hdr_get_len(&ent->hdr)) % mb->cmdr_size;
+    ent = (void *) mb + mb->cmdr_off + mb->cmd_tail;
+    did_some_work = 1;
+  }
+
+  /* Notify the kernel that work has been finished */
+  if (did_some_work) {
+    uint32_t buf = 0;
+
+    write(fd, &buf, 4);
+  }
+
+  return 0;
+}
+
+
+Command filtering and pass_level
+--------------------------------
+
+TCMU supports a "pass_level" option with valid values of 0 or 1.  When
+the value is 0 (the default), nearly all SCSI commands received for
+the device are passed through to the handler. This allows maximum
+flexibility but increases the amount of code required by the handler,
+to support all mandatory SCSI commands. If pass_level is set to 1,
+then only IO-related commands are presented, and the rest are handled
+by LIO's in-kernel command emulation. The commands presented at level
+1 include all versions of:
+
+READ
+WRITE
+WRITE_VERIFY
+XDWRITEREAD
+WRITE_SAME
+COMPARE_AND_WRITE
+SYNCHRONIZE_CACHE
+UNMAP
+
+
+A final note
+------------
+
+Please be careful to return codes as defined by the SCSI
+specifications. These are different than some values defined in the
+scsi/scsi.h include file. For example, CHECK CONDITION's status code
+is 2, not 1.
index a20df9bf8ab0efc22f5ced80f39ff2b4f429a89c..0484f2c526f0c80b5750981b2cf1f8f877d578f9 100644 (file)
@@ -5834,6 +5834,14 @@ S:       Maintained
 F:     drivers/net/macvlan.c
 F:     include/linux/if_macvlan.h
 
+MAILBOX API
+M:     Jassi Brar <jassisinghbrar@gmail.com>
+L:     linux-kernel@vger.kernel.org
+S:     Maintained
+F:     drivers/mailbox/
+F:     include/linux/mailbox_client.h
+F:     include/linux/mailbox_controller.h
+
 MAN-PAGES: MANUAL PAGES FOR LINUX -- Sections 2, 3, 4, 5, and 7
 M:     Michael Kerrisk <mtk.manpages@gmail.com>
 W:     http://www.kernel.org/doc/man-pages
@@ -6822,7 +6830,7 @@ S:        Orphan
 F:     drivers/net/wireless/orinoco/
 
 OSD LIBRARY and FILESYSTEM
-M:     Boaz Harrosh <bharrosh@panasas.com>
+M:     Boaz Harrosh <ooo@electrozaur.com>
 M:     Benny Halevy <bhalevy@primarydata.com>
 L:     osd-dev@open-osd.org
 W:     http://open-osd.org
index 9596b0ab108d14de64763a0b7dfded5a7cddd4f3..fe44b24946094d7ee7b0ea3add74c61c73f3a15a 100644 (file)
@@ -9,6 +9,7 @@
 config ARC
        def_bool y
        select BUILDTIME_EXTABLE_SORT
+       select COMMON_CLK
        select CLONE_BACKWARDS
        # ARC Busybox based initramfs absolutely relies on DEVTMPFS for /dev
        select DEVTMPFS if !INITRAMFS_SOURCE=""
@@ -73,9 +74,6 @@ config STACKTRACE_SUPPORT
 config HAVE_LATENCYTOP_SUPPORT
        def_bool y
 
-config NO_DMA
-       def_bool n
-
 source "init/Kconfig"
 source "kernel/Kconfig.freezer"
 
@@ -354,7 +352,7 @@ config ARC_CURR_IN_REG
          kernel mode. This saves memory access for each such access
 
 
-config ARC_MISALIGN_ACCESS
+config ARC_EMUL_UNALIGNED
        bool "Emulate unaligned memory access (userspace only)"
        select SYSCTL_ARCH_UNALIGN_NO_WARN
        select SYSCTL_ARCH_UNALIGN_ALLOW
index 8c0b1aa56f7ef0f885bb51a94ff6291c867bbf82..10bc3d4e8a443b891007f9d10b01bb2072413342 100644 (file)
@@ -25,7 +25,6 @@ ifdef CONFIG_ARC_CURR_IN_REG
 LINUXINCLUDE   +=  -include ${src}/arch/arc/include/asm/current.h
 endif
 
-upto_gcc42    :=  $(call cc-ifversion, -le, 0402, y)
 upto_gcc44    :=  $(call cc-ifversion, -le, 0404, y)
 atleast_gcc44 :=  $(call cc-ifversion, -ge, 0404, y)
 atleast_gcc48 :=  $(call cc-ifversion, -ge, 0408, y)
@@ -60,25 +59,11 @@ ldflags-$(CONFIG_CPU_BIG_ENDIAN)    += -EB
 # --build-id w/o "-marclinux". Default arc-elf32-ld is OK
 ldflags-$(upto_gcc44)                  += -marclinux
 
-ARC_LIBGCC                             := -mA7
-cflags-$(CONFIG_ARC_HAS_HW_MPY)                += -multcost=16
-
 ifndef CONFIG_ARC_HAS_HW_MPY
        cflags-y        += -mno-mpy
-
-# newlib for ARC700 assumes MPY to be always present, which is generally true
-# However, if someone really doesn't want MPY, we need to use the 600 ver
-# which coupled with -mno-mpy will use mpy emulation
-# With gcc 4.4.7, -mno-mpy is enough to make any other related adjustments,
-# e.g. increased cost of MPY. With gcc 4.2.1 this had to be explicitly hinted
-
-       ifeq ($(upto_gcc42),y)
-               ARC_LIBGCC      := -marc600
-               cflags-y        += -multcost=30
-       endif
 endif
 
-LIBGCC := $(shell $(CC) $(ARC_LIBGCC) $(cflags-y) --print-libgcc-file-name)
+LIBGCC := $(shell $(CC) $(cflags-y) --print-libgcc-file-name)
 
 # Modules with short calls might break for calls into builtin-kernel
 KBUILD_CFLAGS_MODULE   += -mlong-calls
index 6b57475967a6f7abef31275a9e63f090468399bb..757e0c62c4f98c18139d3ce71c008467549b87ef 100644 (file)
                serial0 = &arcuart0;
        };
 
-       memory {
-               device_type = "memory";
-               reg = <0x00000000 0x10000000>;  /* 256M */
-       };
-
        fpga {
                compatible = "simple-bus";
                #address-cells = <1>;
index 4f31b2eb5cdf680cb6b26dbae5aa0119d39bef33..cfaedd9c61c99d89f42c50ea694cfda48f2a2b18 100644 (file)
                /* this is for console on PGU */
                /* bootargs = "console=tty0 consoleblank=0"; */
                /* this is for console on serial */
-               bootargs = "earlycon=uart8250,mmio32,0xc0000000,115200n8 console=ttyS0,115200n8 consoleblank=0 debug";
+               bootargs = "earlycon=uart8250,mmio32,0xc0000000,115200n8 console=tty0 console=ttyS0,115200n8 consoleblank=0 debug";
        };
 
        aliases {
                serial0 = &uart0;
        };
 
-       memory {
-               device_type = "memory";
-               reg = <0x80000000 0x10000000>;  /* 256M */
-       };
-
        fpga {
                compatible = "simple-bus";
                #address-cells = <1>;
index e283aa586934cdb33a2be23955e82bfce5e74394..ef4d3bc7b6c05fdaa414c3c0312bfb829ab769e9 100644 (file)
@@ -23,7 +23,6 @@ CONFIG_MODULES=y
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
 CONFIG_ARC_PLAT_FPGA_LEGACY=y
-CONFIG_ARC_BOARD_ML509=y
 # CONFIG_ARC_HAS_RTSC is not set
 CONFIG_ARC_BUILTIN_DTB_NAME="angel4"
 CONFIG_PREEMPT=y
index 5276a52f6a2f45494ad1f83545b59e91718a07c6..49c93011ab96ed322cf3bf35b729ee5a0fa40c81 100644 (file)
@@ -20,7 +20,6 @@ CONFIG_MODULES=y
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
 CONFIG_ARC_PLAT_FPGA_LEGACY=y
-CONFIG_ARC_BOARD_ML509=y
 # CONFIG_ARC_HAS_RTSC is not set
 CONFIG_ARC_BUILTIN_DTB_NAME="angel4"
 CONFIG_PREEMPT=y
index c01ba35a4effc12b9598740d3eff14d234bf753e..278dacf2a3f94c66830815572a28d2f754e6abc8 100644 (file)
@@ -21,7 +21,6 @@ CONFIG_MODULES=y
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
 CONFIG_ARC_PLAT_FPGA_LEGACY=y
-CONFIG_ARC_BOARD_ML509=y
 # CONFIG_ARC_IDE is not set
 # CONFIG_ARCTANGENT_EMAC is not set
 # CONFIG_ARC_HAS_RTSC is not set
index 372466b371bf8c855944b2007efaa0ec7ba69fcf..be33db8a2ee3c3af4ea3d2c9670d4388933a1969 100644 (file)
@@ -9,19 +9,16 @@
 #ifndef _ASM_ARC_ARCREGS_H
 #define _ASM_ARC_ARCREGS_H
 
-#ifdef __KERNEL__
-
 /* Build Configuration Registers */
 #define ARC_REG_DCCMBASE_BCR   0x61    /* DCCM Base Addr */
 #define ARC_REG_CRC_BCR                0x62
-#define ARC_REG_DVFB_BCR       0x64
-#define ARC_REG_EXTARITH_BCR   0x65
 #define ARC_REG_VECBASE_BCR    0x68
 #define ARC_REG_PERIBASE_BCR   0x69
-#define ARC_REG_FP_BCR         0x6B    /* Single-Precision FPU */
-#define ARC_REG_DPFP_BCR       0x6C    /* Dbl Precision FPU */
+#define ARC_REG_FP_BCR         0x6B    /* ARCompact: Single-Precision FPU */
+#define ARC_REG_DPFP_BCR       0x6C    /* ARCompact: Dbl Precision FPU */
 #define ARC_REG_DCCM_BCR       0x74    /* DCCM Present + SZ */
 #define ARC_REG_TIMERS_BCR     0x75
+#define ARC_REG_AP_BCR         0x76
 #define ARC_REG_ICCM_BCR       0x78
 #define ARC_REG_XY_MEM_BCR     0x79
 #define ARC_REG_MAC_BCR                0x7a
@@ -31,6 +28,9 @@
 #define ARC_REG_MIXMAX_BCR     0x7e
 #define ARC_REG_BARREL_BCR     0x7f
 #define ARC_REG_D_UNCACH_BCR   0x6A
+#define ARC_REG_BPU_BCR                0xc0
+#define ARC_REG_ISA_CFG_BCR    0xc1
+#define ARC_REG_SMART_BCR      0xFF
 
 /* status32 Bits Positions */
 #define STATUS_AE_BIT          5       /* Exception active */
 #define PAGES_TO_KB(n_pages)   ((n_pages) << (PAGE_SHIFT - 10))
 #define PAGES_TO_MB(n_pages)   (PAGES_TO_KB(n_pages) >> 10)
 
-#ifdef CONFIG_ARC_FPU_SAVE_RESTORE
-/* These DPFP regs need to be saved/restored across ctx-sw */
-struct arc_fpu {
-       struct {
-               unsigned int l, h;
-       } aux_dpfp[2];
-};
-#endif
 
 /*
  ***************************************************************
@@ -212,27 +204,19 @@ struct bcr_identity {
 #endif
 };
 
-#define EXTN_SWAP_VALID     0x1
-#define EXTN_NORM_VALID     0x2
-#define EXTN_MINMAX_VALID   0x2
-#define EXTN_BARREL_VALID   0x2
-
-struct bcr_extn {
+struct bcr_isa {
 #ifdef CONFIG_CPU_BIG_ENDIAN
-       unsigned int pad:20, crc:1, ext_arith:2, mul:2, barrel:2, minmax:2,
-                    norm:2, swap:1;
+       unsigned int pad1:23, atomic1:1, ver:8;
 #else
-       unsigned int swap:1, norm:2, minmax:2, barrel:2, mul:2, ext_arith:2,
-                    crc:1, pad:20;
+       unsigned int ver:8, atomic1:1, pad1:23;
 #endif
 };
 
-/* DSP Options Ref Manual */
-struct bcr_extn_mac_mul {
+struct bcr_mpy {
 #ifdef CONFIG_CPU_BIG_ENDIAN
-       unsigned int pad:16, type:8, ver:8;
+       unsigned int pad:8, x1616:8, dsp:4, cycles:2, type:2, ver:8;
 #else
-       unsigned int ver:8, type:8, pad:16;
+       unsigned int ver:8, type:2, cycles:2, dsp:4, x1616:8, pad:8;
 #endif
 };
 
@@ -251,6 +235,7 @@ struct bcr_perip {
        unsigned int pad:8, sz:8, pad2:8, start:8;
 #endif
 };
+
 struct bcr_iccm {
 #ifdef CONFIG_CPU_BIG_ENDIAN
        unsigned int base:16, pad:5, sz:3, ver:8;
@@ -277,8 +262,8 @@ struct bcr_dccm {
 #endif
 };
 
-/* Both SP and DP FPU BCRs have same format */
-struct bcr_fp {
+/* ARCompact: Both SP and DP FPU BCRs have same format */
+struct bcr_fp_arcompact {
 #ifdef CONFIG_CPU_BIG_ENDIAN
        unsigned int fast:1, ver:8;
 #else
@@ -286,6 +271,30 @@ struct bcr_fp {
 #endif
 };
 
+struct bcr_timer {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+       unsigned int pad2:15, rtsc:1, pad1:6, t1:1, t0:1, ver:8;
+#else
+       unsigned int ver:8, t0:1, t1:1, pad1:6, rtsc:1, pad2:15;
+#endif
+};
+
+struct bcr_bpu_arcompact {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+       unsigned int pad2:19, fam:1, pad:2, ent:2, ver:8;
+#else
+       unsigned int ver:8, ent:2, pad:2, fam:1, pad2:19;
+#endif
+};
+
+struct bcr_generic {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+       unsigned int pad:24, ver:8;
+#else
+       unsigned int ver:8, pad:24;
+#endif
+};
+
 /*
  *******************************************************************
  * Generic structures to hold build configuration used at runtime
@@ -299,6 +308,10 @@ struct cpuinfo_arc_cache {
        unsigned int sz_k:8, line_len:8, assoc:4, ver:4, alias:1, vipt:1, pad:6;
 };
 
+struct cpuinfo_arc_bpu {
+       unsigned int ver, full, num_cache, num_pred;
+};
+
 struct cpuinfo_arc_ccm {
        unsigned int base_addr, sz;
 };
@@ -306,21 +319,25 @@ struct cpuinfo_arc_ccm {
 struct cpuinfo_arc {
        struct cpuinfo_arc_cache icache, dcache;
        struct cpuinfo_arc_mmu mmu;
+       struct cpuinfo_arc_bpu bpu;
        struct bcr_identity core;
-       unsigned int timers;
+       struct bcr_isa isa;
+       struct bcr_timer timers;
        unsigned int vec_base;
        unsigned int uncached_base;
        struct cpuinfo_arc_ccm iccm, dccm;
-       struct bcr_extn extn;
+       struct {
+               unsigned int swap:1, norm:1, minmax:1, barrel:1, crc:1, pad1:3,
+                            fpu_sp:1, fpu_dp:1, pad2:6,
+                            debug:1, ap:1, smart:1, rtt:1, pad3:4,
+                            pad4:8;
+       } extn;
+       struct bcr_mpy extn_mpy;
        struct bcr_extn_xymem extn_xymem;
-       struct bcr_extn_mac_mul extn_mac_mul;
-       struct bcr_fp fp, dpfp;
 };
 
 extern struct cpuinfo_arc cpuinfo_arc700[];
 
 #endif /* __ASEMBLY__ */
 
-#endif /* __KERNEL__ */
-
 #endif /* _ASM_ARC_ARCREGS_H */
index 173f303a868f20854cbdcc598cf991e4f6d6d0e5..067551b6920af99fe733f1f13d4aee8b1903a77b 100644 (file)
@@ -9,8 +9,6 @@
 #ifndef _ASM_ARC_ATOMIC_H
 #define _ASM_ARC_ATOMIC_H
 
-#ifdef __KERNEL__
-
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -170,5 +168,3 @@ ATOMIC_OP(and, &=, and)
 #endif
 
 #endif
-
-#endif
index ebc0cf3164dcc6b3a1f8a14c0ba7df66ee05648f..1a5bf07eefe2d445861ecafd2ac03b0b36e9c458 100644 (file)
@@ -13,8 +13,6 @@
 #error only <linux/bitops.h> can be included directly
 #endif
 
-#ifdef __KERNEL__
-
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -508,6 +506,4 @@ static inline __attribute__ ((const)) int __ffs(unsigned long word)
 
 #endif /* !__ASSEMBLY__ */
 
-#endif /* __KERNEL__ */
-
 #endif
index 5b18e94c6678cd2b9eda3eace0dff4f9dd35585c..ea022d47896cef2761bbb8a147844c506f358621 100644 (file)
@@ -21,10 +21,9 @@ void show_kernel_fault_diag(const char *str, struct pt_regs *regs,
                            unsigned long address);
 void die(const char *str, struct pt_regs *regs, unsigned long address);
 
-#define BUG()  do {                            \
-       dump_stack();                                   \
-       pr_warn("Kernel BUG in %s: %s: %d!\n",  \
-               __FILE__, __func__,  __LINE__); \
+#define BUG()  do {                                                            \
+       pr_warn("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
+       dump_stack();                                                           \
 } while (0)
 
 #define HAVE_ARCH_BUG
index b3c750979aa1c84051e6b2a684bdb0accc043c6c..7861255da32d64aa62e03d6fa881f84d9abf3b2f 100644 (file)
@@ -20,7 +20,7 @@
 #define CACHE_LINE_MASK                (~(L1_CACHE_BYTES - 1))
 
 /*
- * ARC700 doesn't cache any access in top 256M.
+ * ARC700 doesn't cache any access in top 1G (0xc000_0000 to 0xFFFF_FFFF)
  * Ideal for wiring memory mapped peripherals as we don't need to do
  * explicit uncached accesses (LD.di/ST.di) hence more portable drivers
  */
index 87b918585c4adc94d530059679e8360f8687f3b6..c2453ee628013700d899a8a47553c7d51a4e6cef 100644 (file)
@@ -12,8 +12,6 @@
 #ifndef _ASM_ARC_CURRENT_H
 #define _ASM_ARC_CURRENT_H
 
-#ifdef __KERNEL__
-
 #ifndef __ASSEMBLY__
 
 #ifdef CONFIG_ARC_CURR_IN_REG
@@ -27,6 +25,4 @@ register struct task_struct *curr_arc asm("r25");
 
 #endif /* ! __ASSEMBLY__ */
 
-#endif /* __KERNEL__ */
-
 #endif /* _ASM_ARC_CURRENT_H */
index 587df8236e8b4c91e896893522f7b060c3cc6d0d..742816f1b2101e2e8ef090ea9d14d444ae97aec8 100644 (file)
@@ -15,8 +15,6 @@
  *  -Conditionally disable interrupts (if they are not enabled, don't disable)
 */
 
-#ifdef __KERNEL__
-
 #include <asm/arcregs.h>
 
 /* status32 Reg bits related to Interrupt Handling */
@@ -169,6 +167,4 @@ static inline int arch_irqs_disabled(void)
 
 #endif /* __ASSEMBLY__ */
 
-#endif /* KERNEL */
-
 #endif
index b65fca7ffeb5e70d5e72e8bf011fc7834d9d33ea..fea9316341366e92c270ef135f5888664797ca76 100644 (file)
@@ -19,7 +19,7 @@
  * register API yet */
 #undef DBG_MAX_REG_NUM
 
-#define GDB_MAX_REGS           39
+#define GDB_MAX_REGS           87
 
 #define BREAK_INSTR_SIZE       2
 #define CACHE_FLUSH_IS_SAFE    1
@@ -33,23 +33,27 @@ static inline void arch_kgdb_breakpoint(void)
 
 extern void kgdb_trap(struct pt_regs *regs);
 
-enum arc700_linux_regnums {
+/* This is the numbering of registers according to the GDB. See GDB's
+ * arc-tdep.h for details.
+ *
+ * Registers are ordered for GDB 7.5. It is incompatible with GDB 6.8. */
+enum arc_linux_regnums {
        _R0             = 0,
        _R1, _R2, _R3, _R4, _R5, _R6, _R7, _R8, _R9, _R10, _R11, _R12, _R13,
        _R14, _R15, _R16, _R17, _R18, _R19, _R20, _R21, _R22, _R23, _R24,
        _R25, _R26,
-       _BTA            = 27,
-       _LP_START       = 28,
-       _LP_END         = 29,
-       _LP_COUNT       = 30,
-       _STATUS32       = 31,
-       _BLINK          = 32,
-       _FP             = 33,
-       __SP            = 34,
-       _EFA            = 35,
-       _RET            = 36,
-       _ORIG_R8        = 37,
-       _STOP_PC        = 38
+       _FP             = 27,
+       __SP            = 28,
+       _R30            = 30,
+       _BLINK          = 31,
+       _LP_COUNT       = 60,
+       _STOP_PC        = 64,
+       _RET            = 64,
+       _LP_START       = 65,
+       _LP_END         = 66,
+       _STATUS32       = 67,
+       _ECR            = 76,
+       _BTA            = 82,
 };
 
 #else
index 82588f3ba77f6b940fd8aa607af34d049614a993..210fe97464c386e91d004fa87d624a83a3e16403 100644 (file)
 #ifndef __ASM_ARC_PROCESSOR_H
 #define __ASM_ARC_PROCESSOR_H
 
-#ifdef __KERNEL__
-
 #ifndef __ASSEMBLY__
 
 #include <asm/ptrace.h>
 
+#ifdef CONFIG_ARC_FPU_SAVE_RESTORE
+/* These DPFP regs need to be saved/restored across ctx-sw */
+struct arc_fpu {
+       struct {
+               unsigned int l, h;
+       } aux_dpfp[2];
+};
+#endif
+
 /* Arch specific stuff which needs to be saved per task.
  * However these items are not so important so as to earn a place in
  * struct thread_info
@@ -128,6 +135,4 @@ extern unsigned int get_wchan(struct task_struct *p);
  */
 #define TASK_UNMAPPED_BASE      (TASK_SIZE / 3)
 
-#endif /* __KERNEL__ */
-
 #endif /* __ASM_ARC_PROCESSOR_H */
index e10f8cef56a8efcaaaf1ff77190ed8125b2d3e1a..6e3ef5ba4f74adca5d4fd1ed78440579166b4b64 100644 (file)
@@ -29,7 +29,6 @@ struct cpuinfo_data {
 };
 
 extern int root_mountflags, end_mem;
-extern int running_on_hw;
 
 void setup_processor(void);
 void __init setup_arch_memory(void);
index 5d06eee43ea9a18ddd8876ac66c7c6d5fed29ec6..3845b9e94f69b0ee5dbda11fe9467c3d4b517aed 100644 (file)
@@ -59,7 +59,15 @@ struct plat_smp_ops {
 /* TBD: stop exporting it for direct population by platform */
 extern struct plat_smp_ops  plat_smp_ops;
 
-#endif  /* CONFIG_SMP */
+#else /* CONFIG_SMP */
+
+static inline void smp_init_cpus(void) {}
+static inline const char *arc_platform_smp_cpuinfo(void)
+{
+       return "";
+}
+
+#endif  /* !CONFIG_SMP */
 
 /*
  * ARC700 doesn't support atomic Read-Modify-Write ops.
index 87676c8f14121e18f178a97ad8475f75b1c7f007..95822b550a18add505329b958035aaa87be7d66d 100644 (file)
@@ -17,8 +17,6 @@
 
 #include <linux/types.h>
 
-#ifdef __KERNEL__
-
 #define __HAVE_ARCH_MEMSET
 #define __HAVE_ARCH_MEMCPY
 #define __HAVE_ARCH_MEMCMP
@@ -36,5 +34,4 @@ extern char *strcpy(char *dest, const char *src);
 extern int strcmp(const char *cs, const char *ct);
 extern __kernel_size_t strlen(const char *);
 
-#endif /* __KERNEL__ */
 #endif /* _ASM_ARC_STRING_H */
index dd785befe7fd1eaa3b6b7d5df5ee8ef77e849587..e56f9fcc558133277ca03d93461a56da5f02a4b9 100644 (file)
@@ -9,8 +9,6 @@
 #ifndef _ASM_ARC_SYSCALLS_H
 #define _ASM_ARC_SYSCALLS_H  1
 
-#ifdef __KERNEL__
-
 #include <linux/compiler.h>
 #include <linux/linkage.h>
 #include <linux/types.h>
@@ -22,6 +20,4 @@ int sys_arc_gettls(void);
 
 #include <asm-generic/syscalls.h>
 
-#endif /* __KERNEL__ */
-
 #endif
index 45be2167201183172695d0a788c0b20b87ec7ce2..02bc5ec0fb2e4e813249aeb42d04bb97aea8f4e9 100644 (file)
@@ -16,8 +16,6 @@
 #ifndef _ASM_THREAD_INFO_H
 #define _ASM_THREAD_INFO_H
 
-#ifdef __KERNEL__
-
 #include <asm/page.h>
 
 #ifdef CONFIG_16KSTACKS
@@ -114,6 +112,4 @@ static inline __attribute_const__ struct thread_info *current_thread_info(void)
  * syscall, so all that reamins to be tested is _TIF_WORK_MASK
  */
 
-#endif /* __KERNEL__ */
-
 #endif /* _ASM_THREAD_INFO_H */
index 3e5f071bc00c7541cebf06ea00855ad53719d359..6da6b4edaeda56801e31cbd0ef5291bfdbe43d67 100644 (file)
@@ -14,7 +14,7 @@
 #include <asm-generic/unaligned.h>
 #include <asm/ptrace.h>
 
-#ifdef CONFIG_ARC_MISALIGN_ACCESS
+#ifdef CONFIG_ARC_EMUL_UNALIGNED
 int misaligned_fixup(unsigned long address, struct pt_regs *regs,
                     struct callee_regs *cregs);
 #else
index 8004b4fa64615cd3c570219e8e5575848e4c99ac..113f2033da9f096a45588a40b00193c8305cf693 100644 (file)
@@ -16,7 +16,7 @@ obj-$(CONFIG_MODULES)                 += arcksyms.o module.o
 obj-$(CONFIG_SMP)                      += smp.o
 obj-$(CONFIG_ARC_DW2_UNWIND)           += unwind.o
 obj-$(CONFIG_KPROBES)                  += kprobes.o
-obj-$(CONFIG_ARC_MISALIGN_ACCESS)      += unaligned.o
+obj-$(CONFIG_ARC_EMUL_UNALIGNED)       += unaligned.o
 obj-$(CONFIG_KGDB)                     += kgdb.o
 obj-$(CONFIG_ARC_METAWARE_HLINK)       += arc_hostlink.o
 obj-$(CONFIG_PERF_EVENTS)              += perf_event.o
index b8a549c4f54071f97d26c473a9dca532e1db8b41..3b7cd4864ba20fa67896de08913395d9978a2dd5 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/uaccess.h>
 #include <asm/disasm.h>
 
-#if defined(CONFIG_KGDB) || defined(CONFIG_ARC_MISALIGN_ACCESS) || \
+#if defined(CONFIG_KGDB) || defined(CONFIG_ARC_EMUL_UNALIGNED) || \
        defined(CONFIG_KPROBES)
 
 /* disasm_instr: Analyses instruction at addr, stores
@@ -535,4 +535,4 @@ int __kprobes disasm_next_pc(unsigned long pc, struct pt_regs *regs,
        return instr.is_branch;
 }
 
-#endif /* CONFIG_KGDB || CONFIG_ARC_MISALIGN_ACCESS || CONFIG_KPROBES */
+#endif /* CONFIG_KGDB || CONFIG_ARC_EMUL_UNALIGNED || CONFIG_KPROBES */
index 4d2481bd8b98dc9e1017b953afafcdf3379c3c27..b0e8666fdccc755ac11763a3bf0b6594f4ed628a 100644 (file)
@@ -91,16 +91,6 @@ stext:
        st      r0, [@uboot_tag]
        st      r2, [@uboot_arg]
 
-       ; Identify if running on ISS vs Silicon
-       ;       IDENTITY Reg [ 3  2  1  0 ]
-       ;       (chip-id)      ^^^^^            ==> 0xffff for ISS
-       lr      r0, [identity]
-       lsr     r3, r0, 16
-       cmp     r3, 0xffff
-       mov.z   r4, 0
-       mov.nz  r4, 1
-       st      r4, [@running_on_hw]
-
        ; setup "current" tsk and optionally cache it in dedicated r25
        mov     r9, @init_task
        SET_CURR_TASK_ON_CPU  r9, r0    ; r9 = tsk, r0 = scratch
index a2ff5c5d1450a7e58a11e2a771e42e93f01ce8e8..ecf6a78693758ba1eecb88a868b8c9d431f52f16 100644 (file)
@@ -158,11 +158,6 @@ int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
        return -1;
 }
 
-unsigned long kgdb_arch_pc(int exception, struct pt_regs *regs)
-{
-       return instruction_pointer(regs);
-}
-
 int kgdb_arch_init(void)
 {
        single_step_data.armed = 0;
index b9a5685a990e25d3aeaec535e7a24bd3c991a019..ae1c485cbc68ea116d84a0625050c0ab80fea89c 100644 (file)
@@ -244,25 +244,23 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
                pr_err("This core does not have performance counters!\n");
                return -ENODEV;
        }
+       BUG_ON(pct_bcr.c > ARC_PMU_MAX_HWEVENTS);
 
-       arc_pmu = devm_kzalloc(&pdev->dev, sizeof(struct arc_pmu),
-                              GFP_KERNEL);
+       READ_BCR(ARC_REG_CC_BUILD, cc_bcr);
+       if (!cc_bcr.v) {
+               pr_err("Performance counters exist, but no countable conditions?\n");
+               return -ENODEV;
+       }
+
+       arc_pmu = devm_kzalloc(&pdev->dev, sizeof(struct arc_pmu), GFP_KERNEL);
        if (!arc_pmu)
                return -ENOMEM;
 
        arc_pmu->n_counters = pct_bcr.c;
-       BUG_ON(arc_pmu->n_counters > ARC_PMU_MAX_HWEVENTS);
-
        arc_pmu->counter_size = 32 + (pct_bcr.s << 4);
-       pr_info("ARC PMU found with %d counters of size %d bits\n",
-               arc_pmu->n_counters, arc_pmu->counter_size);
-
-       READ_BCR(ARC_REG_CC_BUILD, cc_bcr);
-
-       if (!cc_bcr.v)
-               pr_err("Strange! Performance counters exist, but no countable conditions?\n");
 
-       pr_info("ARC PMU has %d countable conditions\n", cc_bcr.c);
+       pr_info("ARC perf\t: %d counters (%d bits), %d countable conditions\n",
+               arc_pmu->n_counters, arc_pmu->counter_size, cc_bcr.c);
 
        cc_name.str[8] = 0;
        for (i = 0; i < PERF_COUNT_HW_MAX; i++)
index 119dddb752b2892ff81a7ab7ce43011eef056b35..252bf603db9c7db023d75b5374580d8f5325c85d 100644 (file)
@@ -13,7 +13,9 @@
 #include <linux/console.h>
 #include <linux/module.h>
 #include <linux/cpu.h>
+#include <linux/clk-provider.h>
 #include <linux/of_fdt.h>
+#include <linux/of_platform.h>
 #include <linux/cache.h>
 #include <asm/sections.h>
 #include <asm/arcregs.h>
 #include <asm/unwind.h>
 #include <asm/clk.h>
 #include <asm/mach_desc.h>
+#include <asm/smp.h>
 
 #define FIX_PTR(x)  __asm__ __volatile__(";" : "+r"(x))
 
-int running_on_hw = 1; /* vs. on ISS */
-
 /* Part of U-boot ABI: see head.S */
 int __initdata uboot_tag;
 char __initdata *uboot_arg;
@@ -42,26 +43,26 @@ struct cpuinfo_arc cpuinfo_arc700[NR_CPUS];
 static void read_arc_build_cfg_regs(void)
 {
        struct bcr_perip uncached_space;
+       struct bcr_generic bcr;
        struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];
        FIX_PTR(cpu);
 
        READ_BCR(AUX_IDENTITY, cpu->core);
+       READ_BCR(ARC_REG_ISA_CFG_BCR, cpu->isa);
 
-       cpu->timers = read_aux_reg(ARC_REG_TIMERS_BCR);
+       READ_BCR(ARC_REG_TIMERS_BCR, cpu->timers);
        cpu->vec_base = read_aux_reg(AUX_INTR_VEC_BASE);
 
        READ_BCR(ARC_REG_D_UNCACH_BCR, uncached_space);
        cpu->uncached_base = uncached_space.start << 24;
 
-       cpu->extn.mul = read_aux_reg(ARC_REG_MUL_BCR);
-       cpu->extn.swap = read_aux_reg(ARC_REG_SWAP_BCR);
-       cpu->extn.norm = read_aux_reg(ARC_REG_NORM_BCR);
-       cpu->extn.minmax = read_aux_reg(ARC_REG_MIXMAX_BCR);
-       cpu->extn.barrel = read_aux_reg(ARC_REG_BARREL_BCR);
-       READ_BCR(ARC_REG_MAC_BCR, cpu->extn_mac_mul);
+       READ_BCR(ARC_REG_MUL_BCR, cpu->extn_mpy);
 
-       cpu->extn.ext_arith = read_aux_reg(ARC_REG_EXTARITH_BCR);
-       cpu->extn.crc = read_aux_reg(ARC_REG_CRC_BCR);
+       cpu->extn.norm = read_aux_reg(ARC_REG_NORM_BCR) > 1 ? 1 : 0; /* 2,3 */
+       cpu->extn.barrel = read_aux_reg(ARC_REG_BARREL_BCR) > 1 ? 1 : 0; /* 2,3 */
+       cpu->extn.swap = read_aux_reg(ARC_REG_SWAP_BCR) ? 1 : 0;        /* 1,3 */
+       cpu->extn.crc = read_aux_reg(ARC_REG_CRC_BCR) ? 1 : 0;
+       cpu->extn.minmax = read_aux_reg(ARC_REG_MIXMAX_BCR) > 1 ? 1 : 0; /* 2 */
 
        /* Note that we read the CCM BCRs independent of kernel config
         * This is to catch the cases where user doesn't know that
@@ -95,43 +96,76 @@ static void read_arc_build_cfg_regs(void)
        read_decode_mmu_bcr();
        read_decode_cache_bcr();
 
-       READ_BCR(ARC_REG_FP_BCR, cpu->fp);
-       READ_BCR(ARC_REG_DPFP_BCR, cpu->dpfp);
+       {
+               struct bcr_fp_arcompact sp, dp;
+               struct bcr_bpu_arcompact bpu;
+
+               READ_BCR(ARC_REG_FP_BCR, sp);
+               READ_BCR(ARC_REG_DPFP_BCR, dp);
+               cpu->extn.fpu_sp = sp.ver ? 1 : 0;
+               cpu->extn.fpu_dp = dp.ver ? 1 : 0;
+
+               READ_BCR(ARC_REG_BPU_BCR, bpu);
+               cpu->bpu.ver = bpu.ver;
+               cpu->bpu.full = bpu.fam ? 1 : 0;
+               if (bpu.ent) {
+                       cpu->bpu.num_cache = 256 << (bpu.ent - 1);
+                       cpu->bpu.num_pred = 256 << (bpu.ent - 1);
+               }
+       }
+
+       READ_BCR(ARC_REG_AP_BCR, bcr);
+       cpu->extn.ap = bcr.ver ? 1 : 0;
+
+       READ_BCR(ARC_REG_SMART_BCR, bcr);
+       cpu->extn.smart = bcr.ver ? 1 : 0;
+
+       cpu->extn.debug = cpu->extn.ap | cpu->extn.smart;
 }
 
 static const struct cpuinfo_data arc_cpu_tbl[] = {
-       { {0x10, "ARCTangent A5"}, 0x1F},
        { {0x20, "ARC 600"      }, 0x2F},
        { {0x30, "ARC 700"      }, 0x33},
        { {0x34, "ARC 700 R4.10"}, 0x34},
+       { {0x35, "ARC 700 R4.11"}, 0x35},
        { {0x00, NULL           } }
 };
 
+#define IS_AVAIL1(v, str)      ((v) ? str : "")
+#define IS_USED(cfg)           (IS_ENABLED(cfg) ? "" : "(not used) ")
+#define IS_AVAIL2(v, str, cfg)  IS_AVAIL1(v, str), IS_AVAIL1(v, IS_USED(cfg))
+
 static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)
 {
-       int n = 0;
        struct cpuinfo_arc *cpu = &cpuinfo_arc700[cpu_id];
        struct bcr_identity *core = &cpu->core;
        const struct cpuinfo_data *tbl;
-       int be = 0;
-#ifdef CONFIG_CPU_BIG_ENDIAN
-       be = 1;
-#endif
+       char *isa_nm;
+       int i, be, atomic;
+       int n = 0;
+
        FIX_PTR(cpu);
 
+       {
+               isa_nm = "ARCompact";
+               be = IS_ENABLED(CONFIG_CPU_BIG_ENDIAN);
+
+               atomic = cpu->isa.atomic1;
+               if (!cpu->isa.ver)      /* ISA BCR absent, use Kconfig info */
+                       atomic = IS_ENABLED(CONFIG_ARC_HAS_LLSC);
+       }
+
        n += scnprintf(buf + n, len - n,
-                      "\nARC IDENTITY\t: Family [%#02x]"
-                      " Cpu-id [%#02x] Chip-id [%#4x]\n",
-                      core->family, core->cpu_id,
-                      core->chip_id);
+                      "\nIDENTITY\t: ARCVER [%#02x] ARCNUM [%#02x] CHIPID [%#4x]\n",
+                      core->family, core->cpu_id, core->chip_id);
 
        for (tbl = &arc_cpu_tbl[0]; tbl->info.id != 0; tbl++) {
                if ((core->family >= tbl->info.id) &&
                    (core->family <= tbl->up_range)) {
                        n += scnprintf(buf + n, len - n,
-                                      "processor\t: %s %s\n",
-                                      tbl->info.str,
-                                      be ? "[Big Endian]" : "");
+                                      "processor [%d]\t: %s (%s ISA) %s\n",
+                                      cpu_id, tbl->info.str, isa_nm,
+                                      IS_AVAIL1(be, "[Big-Endian]"));
                        break;
                }
        }
@@ -143,34 +177,35 @@ static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)
                       (unsigned int)(arc_get_core_freq() / 1000000),
                       (unsigned int)(arc_get_core_freq() / 10000) % 100);
 
-       n += scnprintf(buf + n, len - n, "Timers\t\t: %s %s\n",
-                      (cpu->timers & 0x200) ? "TIMER1" : "",
-                      (cpu->timers & 0x100) ? "TIMER0" : "");
+       n += scnprintf(buf + n, len - n, "Timers\t\t: %s%s%s%s\nISA Extn\t: ",
+                      IS_AVAIL1(cpu->timers.t0, "Timer0 "),
+                      IS_AVAIL1(cpu->timers.t1, "Timer1 "),
+                      IS_AVAIL2(cpu->timers.rtsc, "64-bit RTSC ", CONFIG_ARC_HAS_RTSC));
 
-       n += scnprintf(buf + n, len - n, "Vect Tbl Base\t: %#x\n",
-                      cpu->vec_base);
+       n += i = scnprintf(buf + n, len - n, "%s%s",
+                          IS_AVAIL2(atomic, "atomic ", CONFIG_ARC_HAS_LLSC));
 
-       n += scnprintf(buf + n, len - n, "UNCACHED Base\t: %#x\n",
-                      cpu->uncached_base);
+       if (i)
+               n += scnprintf(buf + n, len - n, "\n\t\t: ");
 
-       return buf;
-}
+       n += scnprintf(buf + n, len - n, "%s%s%s%s%s%s%s%s\n",
+                      IS_AVAIL1(cpu->extn_mpy.ver, "mpy "),
+                      IS_AVAIL1(cpu->extn.norm, "norm "),
+                      IS_AVAIL1(cpu->extn.barrel, "barrel-shift "),
+                      IS_AVAIL1(cpu->extn.swap, "swap "),
+                      IS_AVAIL1(cpu->extn.minmax, "minmax "),
+                      IS_AVAIL1(cpu->extn.crc, "crc "),
+                      IS_AVAIL2(1, "swape", CONFIG_ARC_HAS_SWAPE));
 
-static const struct id_to_str mul_type_nm[] = {
-       { 0x0, "N/A"},
-       { 0x1, "32x32 (spl Result Reg)" },
-       { 0x2, "32x32 (ANY Result Reg)" }
-};
+       if (cpu->bpu.ver)
+               n += scnprintf(buf + n, len - n,
+                             "BPU\t\t: %s%s match, cache:%d, Predict Table:%d\n",
+                             IS_AVAIL1(cpu->bpu.full, "full"),
+                             IS_AVAIL1(!cpu->bpu.full, "partial"),
+                             cpu->bpu.num_cache, cpu->bpu.num_pred);
 
-static const struct id_to_str mac_mul_nm[] = {
-       {0x0, "N/A"},
-       {0x1, "N/A"},
-       {0x2, "Dual 16 x 16"},
-       {0x3, "N/A"},
-       {0x4, "32x16"},
-       {0x5, "N/A"},
-       {0x6, "Dual 16x16 and 32x16"}
-};
+       return buf;
+}
 
 static char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len)
 {
@@ -178,67 +213,46 @@ static char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len)
        struct cpuinfo_arc *cpu = &cpuinfo_arc700[cpu_id];
 
        FIX_PTR(cpu);
-#define IS_AVAIL1(var, str)    ((var) ? str : "")
-#define IS_AVAIL2(var, str)    ((var == 0x2) ? str : "")
-#define IS_USED(cfg)           (IS_ENABLED(cfg) ? "(in-use)" : "(not used)")
 
        n += scnprintf(buf + n, len - n,
-                      "Extn [700-Base]\t: %s %s %s %s %s %s\n",
-                      IS_AVAIL2(cpu->extn.norm, "norm,"),
-                      IS_AVAIL2(cpu->extn.barrel, "barrel-shift,"),
-                      IS_AVAIL1(cpu->extn.swap, "swap,"),
-                      IS_AVAIL2(cpu->extn.minmax, "minmax,"),
-                      IS_AVAIL1(cpu->extn.crc, "crc,"),
-                      IS_AVAIL2(cpu->extn.ext_arith, "ext-arith"));
-
-       n += scnprintf(buf + n, len - n, "Extn [700-MPY]\t: %s",
-                      mul_type_nm[cpu->extn.mul].str);
-
-       n += scnprintf(buf + n, len - n, "   MAC MPY: %s\n",
-                      mac_mul_nm[cpu->extn_mac_mul.type].str);
-
-       if (cpu->core.family == 0x34) {
-               n += scnprintf(buf + n, len - n,
-               "Extn [700-4.10]\t: LLOCK/SCOND %s, SWAPE %s, RTSC %s\n",
-                              IS_USED(CONFIG_ARC_HAS_LLSC),
-                              IS_USED(CONFIG_ARC_HAS_SWAPE),
-                              IS_USED(CONFIG_ARC_HAS_RTSC));
-       }
-
-       n += scnprintf(buf + n, len - n, "Extn [CCM]\t: %s",
-                      !(cpu->dccm.sz || cpu->iccm.sz) ? "N/A" : "");
-
-       if (cpu->dccm.sz)
-               n += scnprintf(buf + n, len - n, "DCCM: @ %x, %d KB ",
-                              cpu->dccm.base_addr, TO_KB(cpu->dccm.sz));
-
-       if (cpu->iccm.sz)
-               n += scnprintf(buf + n, len - n, "ICCM: @ %x, %d KB",
+                      "Vector Table\t: %#x\nUncached Base\t: %#x\n",
+                      cpu->vec_base, cpu->uncached_base);
+
+       if (cpu->extn.fpu_sp || cpu->extn.fpu_dp)
+               n += scnprintf(buf + n, len - n, "FPU\t\t: %s%s\n",
+                              IS_AVAIL1(cpu->extn.fpu_sp, "SP "),
+                              IS_AVAIL1(cpu->extn.fpu_dp, "DP "));
+
+       if (cpu->extn.debug)
+               n += scnprintf(buf + n, len - n, "DEBUG\t\t: %s%s%s\n",
+                              IS_AVAIL1(cpu->extn.ap, "ActionPoint "),
+                              IS_AVAIL1(cpu->extn.smart, "smaRT "),
+                              IS_AVAIL1(cpu->extn.rtt, "RTT "));
+
+       if (cpu->dccm.sz || cpu->iccm.sz)
+               n += scnprintf(buf + n, len - n, "Extn [CCM]\t: DCCM @ %x, %d KB / ICCM: @ %x, %d KB\n",
+                              cpu->dccm.base_addr, TO_KB(cpu->dccm.sz),
                               cpu->iccm.base_addr, TO_KB(cpu->iccm.sz));
 
-       n += scnprintf(buf + n, len - n, "\nExtn [FPU]\t: %s",
-                      !(cpu->fp.ver || cpu->dpfp.ver) ? "N/A" : "");
-
-       if (cpu->fp.ver)
-               n += scnprintf(buf + n, len - n, "SP [v%d] %s",
-                              cpu->fp.ver, cpu->fp.fast ? "(fast)" : "");
-
-       if (cpu->dpfp.ver)
-               n += scnprintf(buf + n, len - n, "DP [v%d] %s",
-                              cpu->dpfp.ver, cpu->dpfp.fast ? "(fast)" : "");
-
-       n += scnprintf(buf + n, len - n, "\n");
-
        n += scnprintf(buf + n, len - n,
                       "OS ABI [v3]\t: no-legacy-syscalls\n");
 
        return buf;
 }
 
-static void arc_chk_ccms(void)
+static void arc_chk_core_config(void)
 {
-#if defined(CONFIG_ARC_HAS_DCCM) || defined(CONFIG_ARC_HAS_ICCM)
        struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];
+       int fpu_enabled;
+
+       if (!cpu->timers.t0)
+               panic("Timer0 is not present!\n");
+
+       if (!cpu->timers.t1)
+               panic("Timer1 is not present!\n");
+
+       if (IS_ENABLED(CONFIG_ARC_HAS_RTSC) && !cpu->timers.rtsc)
+               panic("RTSC is not present\n");
 
 #ifdef CONFIG_ARC_HAS_DCCM
        /*
@@ -256,33 +270,20 @@ static void arc_chk_ccms(void)
        if (CONFIG_ARC_ICCM_SZ != cpu->iccm.sz)
                panic("Linux built with incorrect ICCM Size\n");
 #endif
-#endif
-}
 
-/*
- * Ensure that FP hardware and kernel config match
- * -If hardware contains DPFP, kernel needs to save/restore FPU state
- *  across context switches
- * -If hardware lacks DPFP, but kernel configured to save FPU state then
- *  kernel trying to access non-existant DPFP regs will crash
- *
- * We only check for Dbl precision Floating Point, because only DPFP
- * hardware has dedicated regs which need to be saved/restored on ctx-sw
- * (Single Precision uses core regs), thus kernel is kind of oblivious to it
- */
-static void arc_chk_fpu(void)
-{
-       struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];
+       /*
+        * FP hardware/software config sanity
+        * -If hardware contains DPFP, kernel needs to save/restore FPU state
+        * -If not, it will crash trying to save/restore the non-existant regs
+        *
+        * (only DPDP checked since SP has no arch visible regs)
+        */
+       fpu_enabled = IS_ENABLED(CONFIG_ARC_FPU_SAVE_RESTORE);
 
-       if (cpu->dpfp.ver) {
-#ifndef CONFIG_ARC_FPU_SAVE_RESTORE
-               pr_warn("DPFP support broken in this kernel...\n");
-#endif
-       } else {
-#ifdef CONFIG_ARC_FPU_SAVE_RESTORE
-               panic("H/w lacks DPFP support, apps won't work\n");
-#endif
-       }
+       if (cpu->extn.fpu_dp && !fpu_enabled)
+               pr_warn("CONFIG_ARC_FPU_SAVE_RESTORE needed for working apps\n");
+       else if (!cpu->extn.fpu_dp && fpu_enabled)
+               panic("FPU non-existent, disable CONFIG_ARC_FPU_SAVE_RESTORE\n");
 }
 
 /*
@@ -303,15 +304,11 @@ void setup_processor(void)
 
        arc_mmu_init();
        arc_cache_init();
-       arc_chk_ccms();
 
        printk(arc_extn_mumbojumbo(cpu_id, str, sizeof(str)));
-
-#ifdef CONFIG_SMP
        printk(arc_platform_smp_cpuinfo());
-#endif
 
-       arc_chk_fpu();
+       arc_chk_core_config();
 }
 
 static inline int is_kernel(unsigned long addr)
@@ -360,11 +357,7 @@ void __init setup_arch(char **cmdline_p)
                machine_desc->init_early();
 
        setup_processor();
-
-#ifdef CONFIG_SMP
        smp_init_cpus();
-#endif
-
        setup_arch_memory();
 
        /* copy flat DT out of .init and then unflatten it */
@@ -385,7 +378,13 @@ void __init setup_arch(char **cmdline_p)
 
 static int __init customize_machine(void)
 {
-       /* Add platform devices */
+       of_clk_init(NULL);
+       /*
+        * Traverses flattened DeviceTree - registering platform devices
+        * (if any) complete with their resources
+        */
+       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+
        if (machine_desc->init_machine)
                machine_desc->init_machine();
 
@@ -419,19 +418,14 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 
        seq_printf(m, arc_cpu_mumbojumbo(cpu_id, str, PAGE_SIZE));
 
-       seq_printf(m, "Bogo MIPS : \t%lu.%02lu\n",
+       seq_printf(m, "Bogo MIPS\t: %lu.%02lu\n",
                   loops_per_jiffy / (500000 / HZ),
                   (loops_per_jiffy / (5000 / HZ)) % 100);
 
        seq_printf(m, arc_mmu_mumbojumbo(cpu_id, str, PAGE_SIZE));
-
        seq_printf(m, arc_cache_mumbojumbo(cpu_id, str, PAGE_SIZE));
-
        seq_printf(m, arc_extn_mumbojumbo(cpu_id, str, PAGE_SIZE));
-
-#ifdef CONFIG_SMP
        seq_printf(m, arc_platform_smp_cpuinfo());
-#endif
 
        free_page((unsigned long)str);
 done:
index dcd317c47d098f0fef9391d8173cff82a1b96ba7..d01df0c517a2044ddc15f5fdb895303aa3de56bb 100644 (file)
@@ -101,7 +101,7 @@ void __weak arc_platform_smp_wait_to_boot(int cpu)
 
 const char *arc_platform_smp_cpuinfo(void)
 {
-       return plat_smp_ops.info;
+       return plat_smp_ops.info ? : "";
 }
 
 /*
index 9e1142729fd14c003c4f302a8305de1d735ab7a2..8c3a3e02ba92c8adbc368dba9a3cd283f32c3e72 100644 (file)
@@ -530,16 +530,9 @@ EXPORT_SYMBOL(dma_cache_wback);
  */
 void flush_icache_range(unsigned long kstart, unsigned long kend)
 {
-       unsigned int tot_sz, off, sz;
-       unsigned long phy, pfn;
+       unsigned int tot_sz;
 
-       /* printk("Kernel Cache Cohenercy: %lx to %lx\n",kstart, kend); */
-
-       /* This is not the right API for user virtual address */
-       if (kstart < TASK_SIZE) {
-               BUG_ON("Flush icache range for user virtual addr space");
-               return;
-       }
+       WARN(kstart < TASK_SIZE, "%s() can't handle user vaddr", __func__);
 
        /* Shortcut for bigger flush ranges.
         * Here we don't care if this was kernel virtual or phy addr
@@ -572,6 +565,9 @@ void flush_icache_range(unsigned long kstart, unsigned long kend)
         *     straddles across 2 virtual pages and hence need for loop
         */
        while (tot_sz > 0) {
+               unsigned int off, sz;
+               unsigned long phy, pfn;
+
                off = kstart % PAGE_SIZE;
                pfn = vmalloc_to_pfn((void *)kstart);
                phy = (pfn << PAGE_SHIFT) + off;
index e1acf0ce56479d63be92629ad7b7c19c2ddd8950..7f47d2a56f44374e00939e6742ed6717c452c58a 100644 (file)
@@ -609,14 +609,12 @@ char *arc_mmu_mumbojumbo(int cpu_id, char *buf, int len)
        int n = 0;
        struct cpuinfo_arc_mmu *p_mmu = &cpuinfo_arc700[cpu_id].mmu;
 
-       n += scnprintf(buf + n, len - n, "ARC700 MMU [v%x]\t: %dk PAGE, ",
-                      p_mmu->ver, TO_KB(p_mmu->pg_sz));
-
        n += scnprintf(buf + n, len - n,
-                      "J-TLB %d (%dx%d), uDTLB %d, uITLB %d, %s\n",
+                     "MMU [v%x]\t: %dk PAGE, JTLB %d (%dx%d), uDTLB %d, uITLB %d %s\n",
+                      p_mmu->ver, TO_KB(p_mmu->pg_sz),
                       p_mmu->num_tlb, p_mmu->sets, p_mmu->ways,
                       p_mmu->u_dtlb, p_mmu->u_itlb,
-                      IS_ENABLED(CONFIG_ARC_MMU_SASID) ? "SASID" : "");
+                      IS_ENABLED(CONFIG_ARC_MMU_SASID) ? ",SASID" : "");
 
        return buf;
 }
index b9f34cf55acf47c653d6d6b7e5c09adde2d9d324..217593a7075134f72d3aa2dafcbc4e585ec5cf05 100644 (file)
@@ -8,7 +8,7 @@
 
 menuconfig ARC_PLAT_FPGA_LEGACY
        bool "\"Legacy\" ARC FPGA dev Boards"
-       select ISS_SMP_EXTN if SMP
+       select ARC_HAS_COH_CACHES if SMP
        help
          Support for ARC development boards, provided by Synopsys.
          These are based on FPGA or ISS. e.g.
@@ -18,17 +18,6 @@ menuconfig ARC_PLAT_FPGA_LEGACY
 
 if ARC_PLAT_FPGA_LEGACY
 
-config ARC_BOARD_ANGEL4
-       bool "ARC Angel4"
-       default y
-       help
-         ARC Angel4 FPGA Ref Platform (Xilinx Virtex Based)
-
-config ARC_BOARD_ML509
-       bool "ML509"
-       help
-         ARC ML509 FPGA Ref Platform (Xilinx Virtex-5 Based)
-
 config ISS_SMP_EXTN
        bool "ARC SMP Extensions (ISS Models only)"
        default n
diff --git a/arch/arc/plat-arcfpga/include/plat/irq.h b/arch/arc/plat-arcfpga/include/plat/irq.h
deleted file mode 100644 (file)
index 2c9dea6..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.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.
- *
- * vineetg: Feb 2009
- *  -For AA4 board, IRQ assignments to peripherals
- */
-
-#ifndef __PLAT_IRQ_H
-#define __PLAT_IRQ_H
-
-#define UART0_IRQ      5
-#define UART1_IRQ      10
-#define UART2_IRQ      11
-
-#define IDE_IRQ                13
-#define PCI_IRQ                14
-#define PS2_IRQ                15
-
-#ifdef CONFIG_SMP
-#define IDU_INTERRUPT_0 16
-#endif
-
-#endif
diff --git a/arch/arc/plat-arcfpga/include/plat/memmap.h b/arch/arc/plat-arcfpga/include/plat/memmap.h
deleted file mode 100644 (file)
index 5c78e61..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.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.
- *
- * vineetg: Feb 2009
- *  -For AA4 board, System Memory Map for Peripherals etc
- */
-
-#ifndef __PLAT_MEMMAP_H
-#define __PLAT_MEMMAP_H
-
-#define UART0_BASE              0xC0FC1000
-#define UART1_BASE              0xC0FC1100
-
-#define IDE_CONTROLLER_BASE     0xC0FC9000
-
-#define AHB_PCI_HOST_BRG_BASE   0xC0FD0000
-
-#define PGU_BASEADDR            0xC0FC8000
-#define VLCK_ADDR               0xC0FCF028
-
-#define BVCI_LAT_UNIT_BASE      0xC0FED000
-
-#define PS2_BASE_ADDR          0xC0FCC000
-
-#endif
index 1038949a99a177a0c5e4429be113332268f20f29..afc88254acc1bb74763141008987e9f38f96cb81 100644 (file)
@@ -8,37 +8,9 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/types.h>
 #include <linux/init.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/console.h>
-#include <linux/of_platform.h>
-#include <asm/setup.h>
-#include <asm/clk.h>
 #include <asm/mach_desc.h>
-#include <plat/memmap.h>
 #include <plat/smp.h>
-#include <plat/irq.h>
-
-static void __init plat_fpga_early_init(void)
-{
-       pr_info("[plat-arcfpga]: registering early dev resources\n");
-
-#ifdef CONFIG_ISS_SMP_EXTN
-       iss_model_init_early_smp();
-#endif
-}
-
-static void __init plat_fpga_populate_dev(void)
-{
-       /*
-        * Traverses flattened DeviceTree - registering platform devices
-        * (if any) complete with their resources
-        */
-       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-}
 
 /*----------------------- Machine Descriptions ------------------------------
  *
@@ -48,41 +20,26 @@ static void __init plat_fpga_populate_dev(void)
  * callback set, by matching the DT compatible name.
  */
 
-static const char *aa4_compat[] __initconst = {
+static const char *legacy_fpga_compat[] __initconst = {
        "snps,arc-angel4",
-       NULL,
-};
-
-MACHINE_START(ANGEL4, "angel4")
-       .dt_compat      = aa4_compat,
-       .init_early     = plat_fpga_early_init,
-       .init_machine   = plat_fpga_populate_dev,
-#ifdef CONFIG_ISS_SMP_EXTN
-       .init_smp       = iss_model_init_smp,
-#endif
-MACHINE_END
-
-static const char *ml509_compat[] __initconst = {
        "snps,arc-ml509",
        NULL,
 };
 
-MACHINE_START(ML509, "ml509")
-       .dt_compat      = ml509_compat,
-       .init_early     = plat_fpga_early_init,
-       .init_machine   = plat_fpga_populate_dev,
-#ifdef CONFIG_SMP
+MACHINE_START(LEGACY_FPGA, "legacy_fpga")
+       .dt_compat      = legacy_fpga_compat,
+#ifdef CONFIG_ISS_SMP_EXTN
+       .init_early     = iss_model_init_early_smp,
        .init_smp       = iss_model_init_smp,
 #endif
 MACHINE_END
 
-static const char *nsimosci_compat[] __initconst = {
+static const char *simulation_compat[] __initconst = {
+       "snps,nsim",
        "snps,nsimosci",
        NULL,
 };
 
-MACHINE_START(NSIMOSCI, "nsimosci")
-       .dt_compat      = nsimosci_compat,
-       .init_early     = NULL,
-       .init_machine   = plat_fpga_populate_dev,
+MACHINE_START(SIMULATION, "simulation")
+       .dt_compat      = simulation_compat,
 MACHINE_END
index 92bad9122077dc00b22fc82c6e22be8f5219787b..64797ba3bbe3eed4487fd20911b86e60f3ef0486 100644 (file)
 
 #include <linux/smp.h>
 #include <linux/irq.h>
-#include <plat/irq.h>
 #include <plat/smp.h>
 
+#define IDU_INTERRUPT_0 16
+
 static char smp_cpuinfo_buf[128];
 
 /*
index 6994c188dc88c82bbc256f6835c6e54b6107545a..d14b3d3c5dfdd9b51d0f1bd819dab2c00f1f57fa 100644 (file)
@@ -18,7 +18,6 @@
 
 menuconfig ARC_PLAT_TB10X
        bool "Abilis TB10x"
-       select COMMON_CLK
        select PINCTRL
        select PINCTRL_TB10X
        select PINMUX
index 06cb309294608a6753652049e7c4f3df6d8f8ada..da0ac0960a4b7c992c8e7ad6ad5690f212540b1e 100644 (file)
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
-
 #include <linux/init.h>
-#include <linux/of_platform.h>
-#include <linux/clk-provider.h>
-#include <linux/pinctrl/consumer.h>
-
 #include <asm/mach_desc.h>
 
-
-static void __init tb10x_platform_init(void)
-{
-       of_clk_init(NULL);
-       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-}
-
 static const char *tb10x_compat[] __initdata = {
        "abilis,arc-tb10x",
        NULL,
@@ -41,5 +29,4 @@ static const char *tb10x_compat[] __initdata = {
 
 MACHINE_START(TB10x, "tb10x")
        .dt_compat      = tb10x_compat,
-       .init_machine   = tb10x_platform_init,
 MACHINE_END
index 491b7d5523bf8f2d2f741f078739b168443dfa8d..9702b140ae041d40aca40be34402bbf3c490d106 100644 (file)
@@ -261,6 +261,7 @@ CONFIG_WATCHDOG=y
 CONFIG_XILINX_WATCHDOG=y
 CONFIG_ORION_WATCHDOG=y
 CONFIG_SUNXI_WATCHDOG=y
+CONFIG_MESON_WATCHDOG=y
 CONFIG_MFD_AS3722=y
 CONFIG_MFD_BCM590XX=y
 CONFIG_MFD_CROS_EC=y
index 8c35ae4ff17640acb17610d1000ed720257623a3..07a09570175d8b034082a3639ddfa01999bf59d3 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/input.h>
 #include <linux/io.h>
 #include <linux/irqchip.h>
-#include <linux/mailbox.h>
+#include <linux/pl320-ipc.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
index 03aaa99e1ea00a3d4caf79d27cea669d857a9090..95c49ebc660dd85864981bfdfa13bc1f5066d76f 100644 (file)
@@ -89,7 +89,8 @@ static int __init uefi_init(void)
         */
        if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) {
                pr_err("System table signature incorrect\n");
-               return -EINVAL;
+               retval = -EINVAL;
+               goto out;
        }
        if ((efi.systab->hdr.revision >> 16) < 2)
                pr_warn("Warning: EFI system table version %d.%02d, expected 2.00 or greater\n",
@@ -103,6 +104,7 @@ static int __init uefi_init(void)
                for (i = 0; i < (int) sizeof(vendor) - 1 && *c16; ++i)
                        vendor[i] = c16[i];
                vendor[i] = '\0';
+               early_memunmap(c16, sizeof(vendor));
        }
 
        pr_info("EFI v%u.%.02u by %s\n",
@@ -113,29 +115,11 @@ static int __init uefi_init(void)
        if (retval == 0)
                set_bit(EFI_CONFIG_TABLES, &efi.flags);
 
-       early_memunmap(c16, sizeof(vendor));
+out:
        early_memunmap(efi.systab,  sizeof(efi_system_table_t));
-
        return retval;
 }
 
-static __initdata char memory_type_name[][32] = {
-       {"Reserved"},
-       {"Loader Code"},
-       {"Loader Data"},
-       {"Boot Code"},
-       {"Boot Data"},
-       {"Runtime Code"},
-       {"Runtime Data"},
-       {"Conventional Memory"},
-       {"Unusable Memory"},
-       {"ACPI Reclaim Memory"},
-       {"ACPI Memory NVS"},
-       {"Memory Mapped I/O"},
-       {"MMIO Port Space"},
-       {"PAL Code"},
-};
-
 /*
  * Return true for RAM regions we want to permanently reserve.
  */
@@ -166,10 +150,13 @@ static __init void reserve_regions(void)
                paddr = md->phys_addr;
                npages = md->num_pages;
 
-               if (uefi_debug)
-                       pr_info("  0x%012llx-0x%012llx [%s]",
+               if (uefi_debug) {
+                       char buf[64];
+
+                       pr_info("  0x%012llx-0x%012llx %s",
                                paddr, paddr + (npages << EFI_PAGE_SHIFT) - 1,
-                               memory_type_name[md->type]);
+                               efi_md_typeattr_format(buf, sizeof(buf), md));
+               }
 
                memrange_efi_to_native(&paddr, &npages);
                size = npages << PAGE_SHIFT;
@@ -393,11 +380,16 @@ static int __init arm64_enter_virtual_mode(void)
                return -1;
        }
 
-       pr_info("Remapping and enabling EFI services.\n");
-
-       /* replace early memmap mapping with permanent mapping */
        mapsize = memmap.map_end - memmap.map;
        early_memunmap(memmap.map, mapsize);
+
+       if (efi_runtime_disabled()) {
+               pr_info("EFI runtime services will be disabled.\n");
+               return -1;
+       }
+
+       pr_info("Remapping and enabling EFI services.\n");
+       /* replace early memmap mapping with permanent mapping */
        memmap.map = (__force void *)ioremap_cache((phys_addr_t)memmap.phys_map,
                                                   mapsize);
        memmap.map_end = memmap.map + mapsize;
index 741b99c1a0b1483b153be8823ae681a141d71bf5..c52d7540dc05f4c8ca324e0f6f9ce118f9570d71 100644 (file)
@@ -568,6 +568,7 @@ efi_init (void)
                {
                        const char *unit;
                        unsigned long size;
+                       char buf[64];
 
                        md = p;
                        size = md->num_pages << EFI_PAGE_SHIFT;
@@ -586,9 +587,10 @@ efi_init (void)
                                unit = "KB";
                        }
 
-                       printk("mem%02d: type=%2u, attr=0x%016lx, "
+                       printk("mem%02d: %s "
                               "range=[0x%016lx-0x%016lx) (%4lu%s)\n",
-                              i, md->type, md->attribute, md->phys_addr,
+                              i, efi_md_typeattr_format(buf, sizeof(buf), md),
+                              md->phys_addr,
                               md->phys_addr + efi_md_size(md), size, unit);
                }
        }
index 63392f4b29a4f7876210b48a52bff5ba39f2ee77..d2008887eb8c7fd8f3271b73438f8d5c578cb2b4 100644 (file)
@@ -48,7 +48,6 @@ CONFIG_KEXEC=y
 CONFIG_IRQ_ALL_CPUS=y
 CONFIG_MEMORY_HOTPLUG=y
 CONFIG_MEMORY_HOTREMOVE=y
-CONFIG_CMA=y
 CONFIG_PPC_64K_PAGES=y
 CONFIG_PPC_SUBPAGE_PROT=y
 CONFIG_SCHED_SMT=y
@@ -138,6 +137,7 @@ CONFIG_NETCONSOLE=y
 CONFIG_NETPOLL_TRAP=y
 CONFIG_TUN=m
 CONFIG_VIRTIO_NET=m
+CONFIG_VHOST_NET=m
 CONFIG_VORTEX=y
 CONFIG_ACENIC=m
 CONFIG_ACENIC_OMIT_TIGON_I=y
@@ -303,4 +303,9 @@ CONFIG_CRYPTO_LZO=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_DEV_NX=y
 CONFIG_CRYPTO_DEV_NX_ENCRYPT=m
+CONFIG_VIRTUALIZATION=y
+CONFIG_KVM_BOOK3S_64=m
+CONFIG_KVM_BOOK3S_64_HV=y
+CONFIG_TRANSPARENT_HUGEPAGE=y
+CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
 CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
index 3b260efbfbf9833a5d23263b64f50c833564b74a..ca07f9c27335dd7beb66c9d11e4dba89b30dadc2 100644 (file)
@@ -71,9 +71,10 @@ struct device_node;
 
 #define EEH_PE_ISOLATED                (1 << 0)        /* Isolated PE          */
 #define EEH_PE_RECOVERING      (1 << 1)        /* Recovering PE        */
-#define EEH_PE_RESET           (1 << 2)        /* PE reset in progress */
+#define EEH_PE_CFG_BLOCKED     (1 << 2)        /* Block config access  */
 
 #define EEH_PE_KEEP            (1 << 8)        /* Keep PE on hotplug   */
+#define EEH_PE_CFG_RESTRICTED  (1 << 9)        /* Block config on error */
 
 struct eeh_pe {
        int type;                       /* PE type: PHB/Bus/Device      */
index 0bb23725b1e721a0d5e89f23db233f15b8a9b3ac..8bf1b6351716ee424d80bf240bbcea54abc35c9e 100644 (file)
@@ -34,7 +34,7 @@
        do {                                                    \
                (regs)->result = 0;                             \
                (regs)->nip = __ip;                             \
-               (regs)->gpr[1] = *(unsigned long *)__get_SP();  \
+               (regs)->gpr[1] = current_stack_pointer();       \
                asm volatile("mfmsr %0" : "=r" ((regs)->msr));  \
        } while (0)
 #endif
index fe3f9488f321e5ec20448ac92c6e6a3e16d4fc77..c998279bd85b1b5cec6cf719b88fadc90aacd79f 100644 (file)
@@ -1265,8 +1265,7 @@ static inline unsigned long mfvtb (void)
 
 #define proc_trap()    asm volatile("trap")
 
-#define __get_SP()     ({unsigned long sp; \
-                       asm volatile("mr %0,1": "=r" (sp)); sp;})
+extern unsigned long current_stack_pointer(void);
 
 extern unsigned long scom970_read(unsigned int address);
 extern void scom970_write(unsigned int address, unsigned long value);
index 6fa2708da15304b7bc3ad10f3480e81a837532f8..6240698fee9a60fbbbf5403c10f710a5c41b861b 100644 (file)
@@ -19,7 +19,7 @@
 
 /* ftrace syscalls requires exporting the sys_call_table */
 #ifdef CONFIG_FTRACE_SYSCALLS
-extern const unsigned long *sys_call_table;
+extern const unsigned long sys_call_table[];
 #endif /* CONFIG_FTRACE_SYSCALLS */
 
 static inline long syscall_get_nr(struct task_struct *task,
index adac9dc54aeed2c748ae62a7a3cd1ad9fad8eb2f..484b2d4462c10cd954aad0a5e9cb7776022b1db1 100644 (file)
@@ -53,9 +53,16 @@ void *dma_direct_alloc_coherent(struct device *dev, size_t size,
 #else
        struct page *page;
        int node = dev_to_node(dev);
+#ifdef CONFIG_FSL_SOC
        u64 pfn = get_pfn_limit(dev);
        int zone;
 
+       /*
+        * This code should be OK on other platforms, but we have drivers that
+        * don't set coherent_dma_mask. As a workaround we just ifdef it. This
+        * whole routine needs some serious cleanup.
+        */
+
        zone = dma_pfn_limit_to_zone(pfn);
        if (zone < 0) {
                dev_err(dev, "%s: No suitable zone for pfn %#llx\n",
@@ -73,6 +80,7 @@ void *dma_direct_alloc_coherent(struct device *dev, size_t size,
                break;
 #endif
        };
+#endif /* CONFIG_FSL_SOC */
 
        /* ignore region specifiers */
        flag  &= ~(__GFP_HIGHMEM);
index d543e4179c18cc7737569c8a0e5ef5e8ebf48e14..2248a1999c64e18d50b5cc6aaae902a37279ad5e 100644 (file)
@@ -257,6 +257,13 @@ static void *eeh_dump_pe_log(void *data, void *flag)
        struct eeh_dev *edev, *tmp;
        size_t *plen = flag;
 
+       /* If the PE's config space is blocked, 0xFF's will be
+        * returned. It's pointless to collect the log in this
+        * case.
+        */
+       if (pe->state & EEH_PE_CFG_BLOCKED)
+               return NULL;
+
        eeh_pe_for_each_dev(pe, edev, tmp)
                *plen += eeh_dump_dev_log(edev, pci_regs_buf + *plen,
                                          EEH_PCI_REGS_LOG_LEN - *plen);
@@ -673,18 +680,18 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state stat
        switch (state) {
        case pcie_deassert_reset:
                eeh_ops->reset(pe, EEH_RESET_DEACTIVATE);
-               eeh_pe_state_clear(pe, EEH_PE_RESET);
+               eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED);
                break;
        case pcie_hot_reset:
-               eeh_pe_state_mark(pe, EEH_PE_RESET);
+               eeh_pe_state_mark(pe, EEH_PE_CFG_BLOCKED);
                eeh_ops->reset(pe, EEH_RESET_HOT);
                break;
        case pcie_warm_reset:
-               eeh_pe_state_mark(pe, EEH_PE_RESET);
+               eeh_pe_state_mark(pe, EEH_PE_CFG_BLOCKED);
                eeh_ops->reset(pe, EEH_RESET_FUNDAMENTAL);
                break;
        default:
-               eeh_pe_state_clear(pe, EEH_PE_RESET);
+               eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED);
                return -EINVAL;
        };
 
@@ -1523,7 +1530,7 @@ int eeh_pe_reset(struct eeh_pe *pe, int option)
        switch (option) {
        case EEH_RESET_DEACTIVATE:
                ret = eeh_ops->reset(pe, option);
-               eeh_pe_state_clear(pe, EEH_PE_RESET);
+               eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED);
                if (ret)
                        break;
 
@@ -1538,7 +1545,7 @@ int eeh_pe_reset(struct eeh_pe *pe, int option)
                 */
                eeh_ops->set_option(pe, EEH_OPT_FREEZE_PE);
 
-               eeh_pe_state_mark(pe, EEH_PE_RESET);
+               eeh_pe_state_mark(pe, EEH_PE_CFG_BLOCKED);
                ret = eeh_ops->reset(pe, option);
                break;
        default:
index 3fd514f8e4b2a8e300b87171378185260dc901b3..6535936bdf27a38c2e535ae63599af23df8ce414 100644 (file)
@@ -528,13 +528,13 @@ int eeh_pe_reset_and_recover(struct eeh_pe *pe)
        eeh_pe_dev_traverse(pe, eeh_report_error, &result);
 
        /* Issue reset */
-       eeh_pe_state_mark(pe, EEH_PE_RESET);
+       eeh_pe_state_mark(pe, EEH_PE_CFG_BLOCKED);
        ret = eeh_reset_pe(pe);
        if (ret) {
-               eeh_pe_state_clear(pe, EEH_PE_RECOVERING | EEH_PE_RESET);
+               eeh_pe_state_clear(pe, EEH_PE_RECOVERING | EEH_PE_CFG_BLOCKED);
                return ret;
        }
-       eeh_pe_state_clear(pe, EEH_PE_RESET);
+       eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED);
 
        /* Unfreeze the PE */
        ret = eeh_clear_pe_frozen_state(pe, true);
@@ -601,10 +601,10 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus)
         * config accesses. So we prefer to block them. However, controlled
         * PCI config accesses initiated from EEH itself are allowed.
         */
-       eeh_pe_state_mark(pe, EEH_PE_RESET);
+       eeh_pe_state_mark(pe, EEH_PE_CFG_BLOCKED);
        rc = eeh_reset_pe(pe);
        if (rc) {
-               eeh_pe_state_clear(pe, EEH_PE_RESET);
+               eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED);
                return rc;
        }
 
@@ -613,7 +613,7 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus)
        /* Restore PE */
        eeh_ops->configure_bridge(pe);
        eeh_pe_restore_bars(pe);
-       eeh_pe_state_clear(pe, EEH_PE_RESET);
+       eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED);
 
        /* Clear frozen state */
        rc = eeh_clear_pe_frozen_state(pe, false);
index 53dd0915e6907165aaed9740575d4c8f7b7a5c5a..5a63e2b0f65b616e3c6f5b066921e25d0f20d384 100644 (file)
@@ -525,7 +525,7 @@ static void *__eeh_pe_state_mark(void *data, void *flag)
        pe->state |= state;
 
        /* Offline PCI devices if applicable */
-       if (state != EEH_PE_ISOLATED)
+       if (!(state & EEH_PE_ISOLATED))
                return NULL;
 
        eeh_pe_for_each_dev(pe, edev, tmp) {
@@ -534,6 +534,10 @@ static void *__eeh_pe_state_mark(void *data, void *flag)
                        pdev->error_state = pci_channel_io_frozen;
        }
 
+       /* Block PCI config access if required */
+       if (pe->state & EEH_PE_CFG_RESTRICTED)
+               pe->state |= EEH_PE_CFG_BLOCKED;
+
        return NULL;
 }
 
@@ -611,6 +615,10 @@ static void *__eeh_pe_state_clear(void *data, void *flag)
                pdev->error_state = pci_channel_io_normal;
        }
 
+       /* Unblock PCI config access if required */
+       if (pe->state & EEH_PE_CFG_RESTRICTED)
+               pe->state &= ~EEH_PE_CFG_BLOCKED;
+
        return NULL;
 }
 
index 050f79a4a168cd16a1c4f22be4046cd06a5e6a85..72e783ea06811fd936fef0d8b5e75e0f3a8b9db1 100644 (file)
@@ -1270,11 +1270,6 @@ hmi_exception_early:
        addi    r3,r1,STACK_FRAME_OVERHEAD
        bl      hmi_exception_realmode
        /* Windup the stack. */
-       /* Clear MSR_RI before setting SRR0 and SRR1. */
-       li      r0,MSR_RI
-       mfmsr   r9                      /* get MSR value */
-       andc    r9,r9,r0
-       mtmsrd  r9,1                    /* Clear MSR_RI */
        /* Move original HSRR0 and HSRR1 into the respective regs */
        ld      r9,_MSR(r1)
        mtspr   SPRN_HSRR1,r9
index 8eb857f216c1ba1404a4e3b153a2077b7f7880c4..c14383575fe8f68ed4224ef097acfbbf93189cc2 100644 (file)
@@ -466,7 +466,7 @@ static inline void check_stack_overflow(void)
 #ifdef CONFIG_DEBUG_STACKOVERFLOW
        long sp;
 
-       sp = __get_SP() & (THREAD_SIZE-1);
+       sp = current_stack_pointer() & (THREAD_SIZE-1);
 
        /* check for stack overflow: is there less than 2KB free? */
        if (unlikely(sp < (sizeof(struct thread_info) + 2048))) {
index 7ce26d45777ef1d5497ab778eff937b11204aef3..0d432194c01825286b4f629ad1637cdbeed32a22 100644 (file)
@@ -114,3 +114,7 @@ _GLOBAL(longjmp)
        mtlr    r0
        mr      r3,r4
        blr
+
+_GLOBAL(current_stack_pointer)
+       PPC_LL  r3,0(r1)
+       blr
index c4dfff6c2719ca5bfc6a17c9faf204fa836cad7f..202963ee013a81c76b62dcbd6bc59c0c8cbc9844 100644 (file)
@@ -41,3 +41,5 @@ EXPORT_SYMBOL(giveup_spe);
 #ifdef CONFIG_EPAPR_PARAVIRT
 EXPORT_SYMBOL(epapr_hypercall_start);
 #endif
+
+EXPORT_SYMBOL(current_stack_pointer);
index aa1df89c8b2a8165411d588af394ea85f833265b..923cd2daba89d88f37299b0a0f19803cdacb2532 100644 (file)
@@ -1545,7 +1545,7 @@ void show_stack(struct task_struct *tsk, unsigned long *stack)
                tsk = current;
        if (sp == 0) {
                if (tsk == current)
-                       asm("mr %0,1" : "=r" (sp));
+                       sp = current_stack_pointer();
                else
                        sp = tsk->thread.ksp;
        }
index c168337aef9dd3ccc48c70a00a41d19f4bc3f92d..7c55b86206b3f7ed4ad2846437e5867f97b21861 100644 (file)
@@ -66,6 +66,11 @@ int rtas_read_config(struct pci_dn *pdn, int where, int size, u32 *val)
                return PCIBIOS_DEVICE_NOT_FOUND;
        if (!config_access_valid(pdn, where))
                return PCIBIOS_BAD_REGISTER_NUMBER;
+#ifdef CONFIG_EEH
+       if (pdn->edev && pdn->edev->pe &&
+           (pdn->edev->pe->state & EEH_PE_CFG_BLOCKED))
+               return PCIBIOS_SET_FAILED;
+#endif
 
        addr = rtas_config_addr(pdn->busno, pdn->devfn, where);
        buid = pdn->phb->buid;
@@ -90,9 +95,6 @@ static int rtas_pci_read_config(struct pci_bus *bus,
        struct device_node *busdn, *dn;
        struct pci_dn *pdn;
        bool found = false;
-#ifdef CONFIG_EEH
-       struct eeh_dev *edev;
-#endif
        int ret;
 
        /* Search only direct children of the bus */
@@ -109,11 +111,6 @@ static int rtas_pci_read_config(struct pci_bus *bus,
 
        if (!found)
                return PCIBIOS_DEVICE_NOT_FOUND;
-#ifdef CONFIG_EEH
-       edev = of_node_to_eeh_dev(dn);
-       if (edev && edev->pe && edev->pe->state & EEH_PE_RESET)
-               return PCIBIOS_DEVICE_NOT_FOUND;
-#endif
 
        ret = rtas_read_config(pdn, where, size, val);
        if (*val == EEH_IO_ERROR_VALUE(size) &&
@@ -132,6 +129,11 @@ int rtas_write_config(struct pci_dn *pdn, int where, int size, u32 val)
                return PCIBIOS_DEVICE_NOT_FOUND;
        if (!config_access_valid(pdn, where))
                return PCIBIOS_BAD_REGISTER_NUMBER;
+#ifdef CONFIG_EEH
+       if (pdn->edev && pdn->edev->pe &&
+           (pdn->edev->pe->state & EEH_PE_CFG_BLOCKED))
+               return PCIBIOS_SET_FAILED;
+#endif
 
        addr = rtas_config_addr(pdn->busno, pdn->devfn, where);
        buid = pdn->phb->buid;
@@ -155,10 +157,6 @@ static int rtas_pci_write_config(struct pci_bus *bus,
        struct device_node *busdn, *dn;
        struct pci_dn *pdn;
        bool found = false;
-#ifdef CONFIG_EEH
-       struct eeh_dev *edev;
-#endif
-       int ret;
 
        /* Search only direct children of the bus */
        busdn = pci_bus_to_OF_node(bus);
@@ -173,14 +171,8 @@ static int rtas_pci_write_config(struct pci_bus *bus,
 
        if (!found)
                return PCIBIOS_DEVICE_NOT_FOUND;
-#ifdef CONFIG_EEH
-       edev = of_node_to_eeh_dev(dn);
-       if (edev && edev->pe && (edev->pe->state & EEH_PE_RESET))
-               return PCIBIOS_DEVICE_NOT_FOUND;
-#endif
-       ret = rtas_write_config(pdn, where, size, val);
 
-       return ret;
+       return rtas_write_config(pdn, where, size, val);
 }
 
 static struct pci_ops rtas_pci_ops = {
index cd07d79ad21cac659d9966fb09e2ac41fa13a374..4f3cfe1b6a336e506fcb114af430a8080f4a949a 100644 (file)
@@ -522,36 +522,36 @@ void __init setup_system(void)
        smp_release_cpus();
 #endif
 
-       printk("Starting Linux PPC64 %s\n", init_utsname()->version);
+       pr_info("Starting Linux PPC64 %s\n", init_utsname()->version);
 
-       printk("-----------------------------------------------------\n");
-       printk("ppc64_pft_size    = 0x%llx\n", ppc64_pft_size);
-       printk("phys_mem_size     = 0x%llx\n", memblock_phys_mem_size());
+       pr_info("-----------------------------------------------------\n");
+       pr_info("ppc64_pft_size    = 0x%llx\n", ppc64_pft_size);
+       pr_info("phys_mem_size     = 0x%llx\n", memblock_phys_mem_size());
 
        if (ppc64_caches.dline_size != 0x80)
-               printk("dcache_line_size  = 0x%x\n", ppc64_caches.dline_size);
+               pr_info("dcache_line_size  = 0x%x\n", ppc64_caches.dline_size);
        if (ppc64_caches.iline_size != 0x80)
-               printk("icache_line_size  = 0x%x\n", ppc64_caches.iline_size);
+               pr_info("icache_line_size  = 0x%x\n", ppc64_caches.iline_size);
 
-       printk("cpu_features      = 0x%016lx\n", cur_cpu_spec->cpu_features);
-       printk("  possible        = 0x%016lx\n", CPU_FTRS_POSSIBLE);
-       printk("  always          = 0x%016lx\n", CPU_FTRS_ALWAYS);
-       printk("cpu_user_features = 0x%08x 0x%08x\n", cur_cpu_spec->cpu_user_features,
+       pr_info("cpu_features      = 0x%016lx\n", cur_cpu_spec->cpu_features);
+       pr_info("  possible        = 0x%016lx\n", CPU_FTRS_POSSIBLE);
+       pr_info("  always          = 0x%016lx\n", CPU_FTRS_ALWAYS);
+       pr_info("cpu_user_features = 0x%08x 0x%08x\n", cur_cpu_spec->cpu_user_features,
                cur_cpu_spec->cpu_user_features2);
-       printk("mmu_features      = 0x%08x\n", cur_cpu_spec->mmu_features);
-       printk("firmware_features = 0x%016lx\n", powerpc_firmware_features);
+       pr_info("mmu_features      = 0x%08x\n", cur_cpu_spec->mmu_features);
+       pr_info("firmware_features = 0x%016lx\n", powerpc_firmware_features);
 
 #ifdef CONFIG_PPC_STD_MMU_64
        if (htab_address)
-               printk("htab_address      = 0x%p\n", htab_address);
+               pr_info("htab_address      = 0x%p\n", htab_address);
 
-       printk("htab_hash_mask    = 0x%lx\n", htab_hash_mask);
+       pr_info("htab_hash_mask    = 0x%lx\n", htab_hash_mask);
 #endif
 
        if (PHYSICAL_START > 0)
-               printk("physical_start    = 0x%llx\n",
+               pr_info("physical_start    = 0x%llx\n",
                       (unsigned long long)PHYSICAL_START);
-       printk("-----------------------------------------------------\n");
+       pr_info("-----------------------------------------------------\n");
 
        DBG(" <- setup_system()\n");
 }
index 3d30ef1038e5e285f1fe43f1d85ace5b1c3463b4..ea43a347a1044c37a800d7f78487e6f238078c94 100644 (file)
@@ -50,7 +50,7 @@ void save_stack_trace(struct stack_trace *trace)
 {
        unsigned long sp;
 
-       asm("mr %0,1" : "=r" (sp));
+       sp = current_stack_pointer();
 
        save_context_stack(trace, sp, current, 1);
 }
index 649666d5d1c20520ed554a3375c11393660871e1..e5236c24dc0766112283618da9a259cf88a61735 100644 (file)
@@ -8,6 +8,8 @@
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
  */
+#define pr_fmt(fmt) "numa: " fmt
+
 #include <linux/threads.h>
 #include <linux/bootmem.h>
 #include <linux/init.h>
@@ -1153,6 +1155,22 @@ static int __init early_numa(char *p)
 }
 early_param("numa", early_numa);
 
+static bool topology_updates_enabled = true;
+
+static int __init early_topology_updates(char *p)
+{
+       if (!p)
+               return 0;
+
+       if (!strcmp(p, "off")) {
+               pr_info("Disabling topology updates\n");
+               topology_updates_enabled = false;
+       }
+
+       return 0;
+}
+early_param("topology_updates", early_topology_updates);
+
 #ifdef CONFIG_MEMORY_HOTPLUG
 /*
  * Find the node associated with a hot added memory section for
@@ -1442,8 +1460,11 @@ static long hcall_vphn(unsigned long cpu, __be32 *associativity)
        long retbuf[PLPAR_HCALL9_BUFSIZE] = {0};
        u64 flags = 1;
        int hwcpu = get_hard_smp_processor_id(cpu);
+       int i;
 
        rc = plpar_hcall9(H_HOME_NODE_ASSOCIATIVITY, retbuf, flags, hwcpu);
+       for (i = 0; i < 6; i++)
+               retbuf[i] = cpu_to_be64(retbuf[i]);
        vphn_unpack_associativity(retbuf, associativity);
 
        return rc;
@@ -1539,6 +1560,9 @@ int arch_update_cpu_topology(void)
        struct device *dev;
        int weight, new_nid, i = 0;
 
+       if (!prrn_enabled && !vphn_enabled)
+               return 0;
+
        weight = cpumask_weight(&cpu_associativity_changes_mask);
        if (!weight)
                return 0;
@@ -1592,6 +1616,15 @@ int arch_update_cpu_topology(void)
                cpu = cpu_last_thread_sibling(cpu);
        }
 
+       pr_debug("Topology update for the following CPUs:\n");
+       if (cpumask_weight(&updated_cpus)) {
+               for (ud = &updates[0]; ud; ud = ud->next) {
+                       pr_debug("cpu %d moving from node %d "
+                                         "to %d\n", ud->cpu,
+                                         ud->old_nid, ud->new_nid);
+               }
+       }
+
        /*
         * In cases where we have nothing to update (because the updates list
         * is too short or because the new topology is same as the old one),
@@ -1800,8 +1833,12 @@ static const struct file_operations topology_ops = {
 
 static int topology_update_init(void)
 {
-       start_topology_update();
-       proc_create("powerpc/topology_updates", 0644, NULL, &topology_ops);
+       /* Do not poll for changes if disabled at boot */
+       if (topology_updates_enabled)
+               start_topology_update();
+
+       if (!proc_create("powerpc/topology_updates", 0644, NULL, &topology_ops))
+               return -ENOMEM;
 
        return 0;
 }
index 426814a2ede34db7f83c6405a123aa4317a3008c..eba9cb10619ceac9108d09036b97528d2a03e45f 100644 (file)
@@ -373,7 +373,7 @@ static int ioda_eeh_get_pe_state(struct eeh_pe *pe)
         * moving forward, we have to return operational
         * state during PE reset.
         */
-       if (pe->state & EEH_PE_RESET) {
+       if (pe->state & EEH_PE_CFG_BLOCKED) {
                result = (EEH_STATE_MMIO_ACTIVE  |
                          EEH_STATE_DMA_ACTIVE   |
                          EEH_STATE_MMIO_ENABLED |
index 3e89cbf5588547660ed9f3543735c6b644ae77e9..1d19e7917d7fc5e59cb2e4945c30a90be8e9e50a 100644 (file)
@@ -168,6 +168,26 @@ static int powernv_eeh_dev_probe(struct pci_dev *dev, void *flag)
                return ret;
        }
 
+       /*
+        * If the PE contains any one of following adapters, the
+        * PCI config space can't be accessed when dumping EEH log.
+        * Otherwise, we will run into fenced PHB caused by shortage
+        * of outbound credits in the adapter. The PCI config access
+        * should be blocked until PE reset. MMIO access is dropped
+        * by hardware certainly. In order to drop PCI config requests,
+        * one more flag (EEH_PE_CFG_RESTRICTED) is introduced, which
+        * will be checked in the backend for PE state retrival. If
+        * the PE becomes frozen for the first time and the flag has
+        * been set for the PE, we will set EEH_PE_CFG_BLOCKED for
+        * that PE to block its config space.
+        *
+        * Broadcom Austin 4-ports NICs (14e4:1657)
+        * Broadcom Shiner 2-ports 10G NICs (14e4:168e)
+        */
+       if ((dev->vendor == PCI_VENDOR_ID_BROADCOM && dev->device == 0x1657) ||
+           (dev->vendor == PCI_VENDOR_ID_BROADCOM && dev->device == 0x168e))
+               edev->pe->state |= EEH_PE_CFG_RESTRICTED;
+
        /*
         * Cache the PE primary bus, which can't be fetched when
         * full hotplug is in progress. In that case, all child
@@ -383,6 +403,39 @@ static int powernv_eeh_err_inject(struct eeh_pe *pe, int type, int func,
        return ret;
 }
 
+static inline bool powernv_eeh_cfg_blocked(struct device_node *dn)
+{
+       struct eeh_dev *edev = of_node_to_eeh_dev(dn);
+
+       if (!edev || !edev->pe)
+               return false;
+
+       if (edev->pe->state & EEH_PE_CFG_BLOCKED)
+               return true;
+
+       return false;
+}
+
+static int powernv_eeh_read_config(struct device_node *dn,
+                                  int where, int size, u32 *val)
+{
+       if (powernv_eeh_cfg_blocked(dn)) {
+               *val = 0xFFFFFFFF;
+               return PCIBIOS_SET_FAILED;
+       }
+
+       return pnv_pci_cfg_read(dn, where, size, val);
+}
+
+static int powernv_eeh_write_config(struct device_node *dn,
+                                   int where, int size, u32 val)
+{
+       if (powernv_eeh_cfg_blocked(dn))
+               return PCIBIOS_SET_FAILED;
+
+       return pnv_pci_cfg_write(dn, where, size, val);
+}
+
 /**
  * powernv_eeh_next_error - Retrieve next EEH error to handle
  * @pe: Affected PE
@@ -440,8 +493,8 @@ static struct eeh_ops powernv_eeh_ops = {
        .get_log                = powernv_eeh_get_log,
        .configure_bridge       = powernv_eeh_configure_bridge,
        .err_inject             = powernv_eeh_err_inject,
-       .read_config            = pnv_pci_cfg_read,
-       .write_config           = pnv_pci_cfg_write,
+       .read_config            = powernv_eeh_read_config,
+       .write_config           = powernv_eeh_write_config,
        .next_error             = powernv_eeh_next_error,
        .restore_config         = powernv_eeh_restore_config
 };
index b642b0562f5aca3e8ecde20d3f86738e621f9092..d019b081df9d846177c76b5c923b7e0a41e12fe8 100644 (file)
@@ -194,6 +194,27 @@ static int __init opal_register_exception_handlers(void)
         * fwnmi area at 0x7000 to provide the glue space to OPAL
         */
        glue = 0x7000;
+
+       /*
+        * Check if we are running on newer firmware that exports
+        * OPAL_HANDLE_HMI token. If yes, then don't ask OPAL to patch
+        * the HMI interrupt and we catch it directly in Linux.
+        *
+        * For older firmware (i.e currently released POWER8 System Firmware
+        * as of today <= SV810_087), we fallback to old behavior and let OPAL
+        * patch the HMI vector and handle it inside OPAL firmware.
+        *
+        * For newer firmware (in development/yet to be released) we will
+        * start catching/handling HMI directly in Linux.
+        */
+       if (!opal_check_token(OPAL_HANDLE_HMI)) {
+               pr_info("opal: Old firmware detected, OPAL handles HMIs.\n");
+               opal_register_exception_handler(
+                               OPAL_HYPERVISOR_MAINTENANCE_HANDLER,
+                               0, glue);
+               glue += 128;
+       }
+
        opal_register_exception_handler(OPAL_SOFTPATCH_HANDLER, 0, glue);
 #endif
 
index b3ca77ddf36dfbd07de81feb5015b27bd675c009..b2187d0068b876e6909376c81d390cbf7b8bad00 100644 (file)
@@ -505,7 +505,7 @@ static bool pnv_pci_cfg_check(struct pci_controller *hose,
        edev = of_node_to_eeh_dev(dn);
        if (edev) {
                if (edev->pe &&
-                   (edev->pe->state & EEH_PE_RESET))
+                   (edev->pe->state & EEH_PE_CFG_BLOCKED))
                        return false;
 
                if (edev->mode & EEH_DEV_REMOVED)
index fdf01b660d5930cd31c4f246c7d4f4659aad6690..6ad83bd11fe21d0aaa22ad0d9cd6e0d399bb945d 100644 (file)
 #include <asm/rtas.h>
 
 struct cc_workarea {
-       u32     drc_index;
-       u32     zero;
-       u32     name_offset;
-       u32     prop_length;
-       u32     prop_offset;
+       __be32  drc_index;
+       __be32  zero;
+       __be32  name_offset;
+       __be32  prop_length;
+       __be32  prop_offset;
 };
 
 void dlpar_free_cc_property(struct property *prop)
@@ -49,11 +49,11 @@ static struct property *dlpar_parse_cc_property(struct cc_workarea *ccwa)
        if (!prop)
                return NULL;
 
-       name = (char *)ccwa + ccwa->name_offset;
+       name = (char *)ccwa + be32_to_cpu(ccwa->name_offset);
        prop->name = kstrdup(name, GFP_KERNEL);
 
-       prop->length = ccwa->prop_length;
-       value = (char *)ccwa + ccwa->prop_offset;
+       prop->length = be32_to_cpu(ccwa->prop_length);
+       value = (char *)ccwa + be32_to_cpu(ccwa->prop_offset);
        prop->value = kmemdup(value, prop->length, GFP_KERNEL);
        if (!prop->value) {
                dlpar_free_cc_property(prop);
@@ -79,7 +79,7 @@ static struct device_node *dlpar_parse_cc_node(struct cc_workarea *ccwa,
        if (!dn)
                return NULL;
 
-       name = (char *)ccwa + ccwa->name_offset;
+       name = (char *)ccwa + be32_to_cpu(ccwa->name_offset);
        dn->full_name = kasprintf(GFP_KERNEL, "%s/%s", path, name);
        if (!dn->full_name) {
                kfree(dn);
@@ -126,7 +126,7 @@ void dlpar_free_cc_nodes(struct device_node *dn)
 #define CALL_AGAIN     -2
 #define ERR_CFG_USE     -9003
 
-struct device_node *dlpar_configure_connector(u32 drc_index,
+struct device_node *dlpar_configure_connector(__be32 drc_index,
                                              struct device_node *parent)
 {
        struct device_node *dn;
@@ -414,7 +414,7 @@ static ssize_t dlpar_cpu_probe(const char *buf, size_t count)
        if (!parent)
                return -ENODEV;
 
-       dn = dlpar_configure_connector(drc_index, parent);
+       dn = dlpar_configure_connector(cpu_to_be32(drc_index), parent);
        if (!dn)
                return -EINVAL;
 
index b174fa751d260bcebd20b0af83cf5e13ba28158a..5c375f93c669cac9cdbc5dc028e72e297f7713de 100644 (file)
@@ -247,7 +247,7 @@ static int pseries_add_processor(struct device_node *np)
        unsigned int cpu;
        cpumask_var_t candidate_mask, tmp;
        int err = -ENOSPC, len, nthreads, i;
-       const u32 *intserv;
+       const __be32 *intserv;
 
        intserv = of_get_property(np, "ibm,ppc-interrupt-server#s", &len);
        if (!intserv)
@@ -293,7 +293,7 @@ static int pseries_add_processor(struct device_node *np)
        for_each_cpu(cpu, tmp) {
                BUG_ON(cpu_present(cpu));
                set_cpu_present(cpu, true);
-               set_hard_smp_processor_id(cpu, *intserv++);
+               set_hard_smp_processor_id(cpu, be32_to_cpu(*intserv++));
        }
        err = 0;
 out_unlock:
index de1ec54a2a57924ac2f3c29a6d43153e773e8aee..e32e00976a949a8a1ed07210f1f7b892595dc499 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/mm.h>
 #include <linux/memblock.h>
 #include <linux/spinlock.h>
-#include <linux/sched.h>       /* for show_stack */
 #include <linux/string.h>
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
@@ -168,7 +167,7 @@ static int tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
                        printk("\tindex   = 0x%llx\n", (u64)tbl->it_index);
                        printk("\ttcenum  = 0x%llx\n", (u64)tcenum);
                        printk("\ttce val = 0x%llx\n", tce );
-                       show_stack(current, (unsigned long *)__get_SP());
+                       dump_stack();
                }
 
                tcenum++;
@@ -257,7 +256,7 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
                printk("\tindex   = 0x%llx\n", (u64)tbl->it_index);
                printk("\tnpages  = 0x%llx\n", (u64)npages);
                printk("\ttce[0] val = 0x%llx\n", tcep[0]);
-               show_stack(current, (unsigned long *)__get_SP());
+               dump_stack();
        }
        return ret;
 }
@@ -273,7 +272,7 @@ static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages
                        printk("tce_free_pSeriesLP: plpar_tce_put failed. rc=%lld\n", rc);
                        printk("\tindex   = 0x%llx\n", (u64)tbl->it_index);
                        printk("\ttcenum  = 0x%llx\n", (u64)tcenum);
-                       show_stack(current, (unsigned long *)__get_SP());
+                       dump_stack();
                }
 
                tcenum++;
@@ -292,7 +291,7 @@ static void tce_freemulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long n
                printk("\trc      = %lld\n", rc);
                printk("\tindex   = 0x%llx\n", (u64)tbl->it_index);
                printk("\tnpages  = 0x%llx\n", (u64)npages);
-               show_stack(current, (unsigned long *)__get_SP());
+               dump_stack();
        }
 }
 
@@ -307,7 +306,7 @@ static unsigned long tce_get_pSeriesLP(struct iommu_table *tbl, long tcenum)
                printk("tce_get_pSeriesLP: plpar_tce_get failed. rc=%lld\n", rc);
                printk("\tindex   = 0x%llx\n", (u64)tbl->it_index);
                printk("\ttcenum  = 0x%llx\n", (u64)tcenum);
-               show_stack(current, (unsigned long *)__get_SP());
+               dump_stack();
        }
 
        return tce_ret;
index 361add62abf1089d4cd65aa28c72264a040de635..1796c5438cc661d22a3e026dae6000891f9773d7 100644 (file)
@@ -56,7 +56,8 @@ extern void hvc_vio_init_early(void);
 /* Dynamic logical Partitioning/Mobility */
 extern void dlpar_free_cc_nodes(struct device_node *);
 extern void dlpar_free_cc_property(struct property *);
-extern struct device_node *dlpar_configure_connector(u32, struct device_node *);
+extern struct device_node *dlpar_configure_connector(__be32,
+                                               struct device_node *);
 extern int dlpar_attach_node(struct device_node *);
 extern int dlpar_detach_node(struct device_node *);
 
index 0c75214b6f9220d433f8ea88776041694f744add..73b64c73505bee493809dccbf886af0108c1129f 100644 (file)
@@ -145,59 +145,64 @@ void msi_bitmap_free(struct msi_bitmap *bmp)
 
 #ifdef CONFIG_MSI_BITMAP_SELFTEST
 
-#define check(x)       \
-       if (!(x)) printk("msi_bitmap: test failed at line %d\n", __LINE__);
-
 static void __init test_basics(void)
 {
        struct msi_bitmap bmp;
-       int i, size = 512;
+       int rc, i, size = 512;
 
        /* Can't allocate a bitmap of 0 irqs */
-       check(msi_bitmap_alloc(&bmp, 0, NULL) != 0);
+       WARN_ON(msi_bitmap_alloc(&bmp, 0, NULL) == 0);
 
        /* of_node may be NULL */
-       check(0 == msi_bitmap_alloc(&bmp, size, NULL));
+       WARN_ON(msi_bitmap_alloc(&bmp, size, NULL));
 
        /* Should all be free by default */
-       check(0 == bitmap_find_free_region(bmp.bitmap, size,
-                                          get_count_order(size)));
+       WARN_ON(bitmap_find_free_region(bmp.bitmap, size, get_count_order(size)));
        bitmap_release_region(bmp.bitmap, 0, get_count_order(size));
 
        /* With no node, there's no msi-available-ranges, so expect > 0 */
-       check(msi_bitmap_reserve_dt_hwirqs(&bmp) > 0);
+       WARN_ON(msi_bitmap_reserve_dt_hwirqs(&bmp) <= 0);
 
        /* Should all still be free */
-       check(0 == bitmap_find_free_region(bmp.bitmap, size,
-                                          get_count_order(size)));
+       WARN_ON(bitmap_find_free_region(bmp.bitmap, size, get_count_order(size)));
        bitmap_release_region(bmp.bitmap, 0, get_count_order(size));
 
        /* Check we can fill it up and then no more */
        for (i = 0; i < size; i++)
-               check(msi_bitmap_alloc_hwirqs(&bmp, 1) >= 0);
+               WARN_ON(msi_bitmap_alloc_hwirqs(&bmp, 1) < 0);
 
-       check(msi_bitmap_alloc_hwirqs(&bmp, 1) < 0);
+       WARN_ON(msi_bitmap_alloc_hwirqs(&bmp, 1) >= 0);
 
        /* Should all be allocated */
-       check(bitmap_find_free_region(bmp.bitmap, size, 0) < 0);
+       WARN_ON(bitmap_find_free_region(bmp.bitmap, size, 0) >= 0);
 
        /* And if we free one we can then allocate another */
        msi_bitmap_free_hwirqs(&bmp, size / 2, 1);
-       check(msi_bitmap_alloc_hwirqs(&bmp, 1) == size / 2);
+       WARN_ON(msi_bitmap_alloc_hwirqs(&bmp, 1) != size / 2);
+
+       /* Free most of them for the alignment tests */
+       msi_bitmap_free_hwirqs(&bmp, 3, size - 3);
 
        /* Check we get a naturally aligned offset */
-       check(msi_bitmap_alloc_hwirqs(&bmp, 2) % 2 == 0);
-       check(msi_bitmap_alloc_hwirqs(&bmp, 4) % 4 == 0);
-       check(msi_bitmap_alloc_hwirqs(&bmp, 8) % 8 == 0);
-       check(msi_bitmap_alloc_hwirqs(&bmp, 9) % 16 == 0);
-       check(msi_bitmap_alloc_hwirqs(&bmp, 3) % 4 == 0);
-       check(msi_bitmap_alloc_hwirqs(&bmp, 7) % 8 == 0);
-       check(msi_bitmap_alloc_hwirqs(&bmp, 121) % 128 == 0);
+       rc = msi_bitmap_alloc_hwirqs(&bmp, 2);
+       WARN_ON(rc < 0 && rc % 2 != 0);
+       rc = msi_bitmap_alloc_hwirqs(&bmp, 4);
+       WARN_ON(rc < 0 && rc % 4 != 0);
+       rc = msi_bitmap_alloc_hwirqs(&bmp, 8);
+       WARN_ON(rc < 0 && rc % 8 != 0);
+       rc = msi_bitmap_alloc_hwirqs(&bmp, 9);
+       WARN_ON(rc < 0 && rc % 16 != 0);
+       rc = msi_bitmap_alloc_hwirqs(&bmp, 3);
+       WARN_ON(rc < 0 && rc % 4 != 0);
+       rc = msi_bitmap_alloc_hwirqs(&bmp, 7);
+       WARN_ON(rc < 0 && rc % 8 != 0);
+       rc = msi_bitmap_alloc_hwirqs(&bmp, 121);
+       WARN_ON(rc < 0 && rc % 128 != 0);
 
        msi_bitmap_free(&bmp);
 
-       /* Clients may check bitmap == NULL for "not-allocated" */
-       check(bmp.bitmap == NULL);
+       /* Clients may WARN_ON bitmap == NULL for "not-allocated" */
+       WARN_ON(bmp.bitmap != NULL);
 
        kfree(bmp.bitmap);
 }
@@ -219,14 +224,13 @@ static void __init test_of_node(void)
        of_node_init(&of_node);
        of_node.full_name = node_name;
 
-       check(0 == msi_bitmap_alloc(&bmp, size, &of_node));
+       WARN_ON(msi_bitmap_alloc(&bmp, size, &of_node));
 
        /* No msi-available-ranges, so expect > 0 */
-       check(msi_bitmap_reserve_dt_hwirqs(&bmp) > 0);
+       WARN_ON(msi_bitmap_reserve_dt_hwirqs(&bmp) <= 0);
 
        /* Should all still be free */
-       check(0 == bitmap_find_free_region(bmp.bitmap, size,
-                                          get_count_order(size)));
+       WARN_ON(bitmap_find_free_region(bmp.bitmap, size, get_count_order(size)));
        bitmap_release_region(bmp.bitmap, 0, get_count_order(size));
 
        /* Now create a fake msi-available-ranges property */
@@ -240,11 +244,11 @@ static void __init test_of_node(void)
        of_node.properties = &prop;
 
        /* msi-available-ranges, so expect == 0 */
-       check(msi_bitmap_reserve_dt_hwirqs(&bmp) == 0);
+       WARN_ON(msi_bitmap_reserve_dt_hwirqs(&bmp));
 
        /* Check we got the expected result */
-       check(0 == bitmap_parselist(expected_str, expected, size));
-       check(bitmap_equal(expected, bmp.bitmap, size));
+       WARN_ON(bitmap_parselist(expected_str, expected, size));
+       WARN_ON(!bitmap_equal(expected, bmp.bitmap, size));
 
        msi_bitmap_free(&bmp);
        kfree(bmp.bitmap);
index 940ac49198db1dd406b99944f51183df869cd420..4197c89c52d4cc3349e2ad0cbe4d2c87d2e51e5b 100644 (file)
 #define __NR_seccomp           348
 #define __NR_getrandom         349
 #define __NR_memfd_create      350
-#define NR_syscalls 351
+#define __NR_bpf               351
+#define NR_syscalls 352
 
 /* 
  * There are some system calls that are not present on 64 bit, some
index faf6caa510dcedb862ad65be7108e1042a754939..c4f7a3d655b8025c78511e43f153a469599a34a5 100644 (file)
@@ -217,3 +217,4 @@ COMPAT_SYSCALL_WRAP5(renameat2, int, olddfd, const char __user *, oldname, int,
 COMPAT_SYSCALL_WRAP3(seccomp, unsigned int, op, unsigned int, flags, const char __user *, uargs)
 COMPAT_SYSCALL_WRAP3(getrandom, char __user *, buf, size_t, count, unsigned int, flags)
 COMPAT_SYSCALL_WRAP2(memfd_create, const char __user *, uname, unsigned int, flags)
+COMPAT_SYSCALL_WRAP3(bpf, int, cmd, union bpf_attr *, attr, unsigned int, size);
index 6fe886ac2db596a81f67a80e69e4f5f54609c45f..9f7087fd58de5f47251fafe7fe6530d6e3fea163 100644 (file)
@@ -359,3 +359,4 @@ SYSCALL(sys_renameat2,sys_renameat2,compat_sys_renameat2)
 SYSCALL(sys_seccomp,sys_seccomp,compat_sys_seccomp)
 SYSCALL(sys_getrandom,sys_getrandom,compat_sys_getrandom)
 SYSCALL(sys_memfd_create,sys_memfd_create,compat_sys_memfd_create) /* 350 */
+SYSCALL(sys_bpf,sys_bpf,compat_sys_bpf)
index 956f4f7a591c18b1cd6f03129e0c0bc46750a7b6..f6b3cd056ec22c1c28b908c4cefc46bc4a4e2099 100644 (file)
@@ -5,13 +5,13 @@
  *    Author(s): Jan Willeke,
  */
 
-#include <linux/kprobes.h>
 #include <linux/uaccess.h>
 #include <linux/uprobes.h>
 #include <linux/compat.h>
 #include <linux/kdebug.h>
 #include <asm/switch_to.h>
 #include <asm/facility.h>
+#include <asm/kprobes.h>
 #include <asm/dis.h>
 #include "entry.h"
 
index c5d64a0997193f77d0cd56ce2e7ac2c62c0b3f28..ae90e1ae3607052c6ac4403f815d33061fcaf604 100644 (file)
@@ -4,7 +4,7 @@
  *    Copyright IBM Corp. 2014
  */
 
-#include <linux/kprobes.h>
+#include <asm/kprobes.h>
 #include <asm/dis.h>
 
 int probe_is_prohibited_opcode(u16 *insn)
index 296b61a4af5974d59cd5692814d907614a7cf6d8..1b79ca67392fdffc2e6dd7328717267d16d87650 100644 (file)
@@ -656,7 +656,7 @@ void __gmap_zap(struct gmap *gmap, unsigned long gaddr)
        }
        pgste_set_unlock(ptep, pgste);
 out_pte:
-       pte_unmap_unlock(*ptep, ptl);
+       pte_unmap_unlock(ptep, ptl);
 }
 EXPORT_SYMBOL_GPL(__gmap_zap);
 
@@ -943,7 +943,7 @@ retry:
        }
        if (!(pte_val(*ptep) & _PAGE_INVALID) &&
             (pte_val(*ptep) & _PAGE_PROTECT)) {
-               pte_unmap_unlock(*ptep, ptl);
+               pte_unmap_unlock(ptep, ptl);
                if (fixup_user_fault(current, mm, addr, FAULT_FLAG_WRITE)) {
                        up_read(&mm->mmap_sem);
                        return -EFAULT;
@@ -974,7 +974,7 @@ retry:
                pgste_val(new) |= PGSTE_UC_BIT;
 
        pgste_set_unlock(ptep, new);
-       pte_unmap_unlock(*ptep, ptl);
+       pte_unmap_unlock(ptep, ptl);
        up_read(&mm->mmap_sem);
        return 0;
 }
index de8eebd6f67c825b3f013f7bc20a228b807c181f..1acf605a646dd87830f22694991142415c6ff351 100644 (file)
@@ -330,8 +330,10 @@ __setup_efi_pci32(efi_pci_io_protocol_32 *pci, struct pci_setup_rom **__rom)
        size = pci->romsize + sizeof(*rom);
 
        status = efi_call_early(allocate_pool, EFI_LOADER_DATA, size, &rom);
-       if (status != EFI_SUCCESS)
+       if (status != EFI_SUCCESS) {
+               efi_printk(sys_table, "Failed to alloc mem for rom\n");
                return status;
+       }
 
        memset(rom, 0, sizeof(*rom));
 
@@ -344,14 +346,18 @@ __setup_efi_pci32(efi_pci_io_protocol_32 *pci, struct pci_setup_rom **__rom)
        status = efi_early->call(pci->pci.read, pci, EfiPciIoWidthUint16,
                                 PCI_VENDOR_ID, 1, &(rom->vendor));
 
-       if (status != EFI_SUCCESS)
+       if (status != EFI_SUCCESS) {
+               efi_printk(sys_table, "Failed to read rom->vendor\n");
                goto free_struct;
+       }
 
        status = efi_early->call(pci->pci.read, pci, EfiPciIoWidthUint16,
                                 PCI_DEVICE_ID, 1, &(rom->devid));
 
-       if (status != EFI_SUCCESS)
+       if (status != EFI_SUCCESS) {
+               efi_printk(sys_table, "Failed to read rom->devid\n");
                goto free_struct;
+       }
 
        status = efi_early->call(pci->get_location, pci, &(rom->segment),
                                 &(rom->bus), &(rom->device), &(rom->function));
@@ -432,8 +438,10 @@ __setup_efi_pci64(efi_pci_io_protocol_64 *pci, struct pci_setup_rom **__rom)
        size = pci->romsize + sizeof(*rom);
 
        status = efi_call_early(allocate_pool, EFI_LOADER_DATA, size, &rom);
-       if (status != EFI_SUCCESS)
+       if (status != EFI_SUCCESS) {
+               efi_printk(sys_table, "Failed to alloc mem for rom\n");
                return status;
+       }
 
        rom->data.type = SETUP_PCI;
        rom->data.len = size - sizeof(struct setup_data);
@@ -444,14 +452,18 @@ __setup_efi_pci64(efi_pci_io_protocol_64 *pci, struct pci_setup_rom **__rom)
        status = efi_early->call(pci->pci.read, pci, EfiPciIoWidthUint16,
                                 PCI_VENDOR_ID, 1, &(rom->vendor));
 
-       if (status != EFI_SUCCESS)
+       if (status != EFI_SUCCESS) {
+               efi_printk(sys_table, "Failed to read rom->vendor\n");
                goto free_struct;
+       }
 
        status = efi_early->call(pci->pci.read, pci, EfiPciIoWidthUint16,
                                 PCI_DEVICE_ID, 1, &(rom->devid));
 
-       if (status != EFI_SUCCESS)
+       if (status != EFI_SUCCESS) {
+               efi_printk(sys_table, "Failed to read rom->devid\n");
                goto free_struct;
+       }
 
        status = efi_early->call(pci->get_location, pci, &(rom->segment),
                                 &(rom->bus), &(rom->device), &(rom->function));
@@ -538,8 +550,10 @@ static void setup_efi_pci(struct boot_params *params)
                                        EFI_LOADER_DATA,
                                        size, (void **)&pci_handle);
 
-               if (status != EFI_SUCCESS)
+               if (status != EFI_SUCCESS) {
+                       efi_printk(sys_table, "Failed to alloc mem for pci_handle\n");
                        return;
+               }
 
                status = efi_call_early(locate_handle,
                                        EFI_LOCATE_BY_PROTOCOL, &pci_proto,
@@ -1105,6 +1119,10 @@ struct boot_params *make_boot_params(struct efi_config *c)
 
        memset(sdt, 0, sizeof(*sdt));
 
+       status = efi_parse_options(cmdline_ptr);
+       if (status != EFI_SUCCESS)
+               goto fail2;
+
        status = handle_cmdline_files(sys_table, image,
                                      (char *)(unsigned long)hdr->cmd_line_ptr,
                                      "initrd=", hdr->initrd_addr_max,
index 0ec241ede5a256327f9a578ac2d61d0def83b2c5..9b11757975d025045b747097e95ad0009293a8a2 100644 (file)
@@ -81,24 +81,23 @@ extern u64 asmlinkage efi_call(void *fp, ...);
  */
 #define __efi_call_virt(f, args...) efi_call_virt(f, args)
 
-extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size,
-                                u32 type, u64 attribute);
+extern void __iomem *__init efi_ioremap(unsigned long addr, unsigned long size,
+                                       u32 type, u64 attribute);
 
 #endif /* CONFIG_X86_32 */
 
-extern int add_efi_memmap;
 extern struct efi_scratch efi_scratch;
-extern void efi_set_executable(efi_memory_desc_t *md, bool executable);
-extern int efi_memblock_x86_reserve_range(void);
-extern void efi_call_phys_prelog(void);
-extern void efi_call_phys_epilog(void);
-extern void efi_unmap_memmap(void);
-extern void efi_memory_uc(u64 addr, unsigned long size);
+extern void __init efi_set_executable(efi_memory_desc_t *md, bool executable);
+extern int __init efi_memblock_x86_reserve_range(void);
+extern void __init efi_call_phys_prolog(void);
+extern void __init efi_call_phys_epilog(void);
+extern void __init efi_unmap_memmap(void);
+extern void __init efi_memory_uc(u64 addr, unsigned long size);
 extern void __init efi_map_region(efi_memory_desc_t *md);
 extern void __init efi_map_region_fixed(efi_memory_desc_t *md);
 extern void efi_sync_low_kernel_mappings(void);
-extern int efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages);
-extern void efi_cleanup_page_tables(unsigned long pa_memmap, unsigned num_pages);
+extern int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages);
+extern void __init efi_cleanup_page_tables(unsigned long pa_memmap, unsigned num_pages);
 extern void __init old_map_region(efi_memory_desc_t *md);
 extern void __init runtime_code_page_mkexec(void);
 extern void __init efi_runtime_mkexec(void);
@@ -162,16 +161,6 @@ static inline efi_status_t efi_thunk_set_virtual_address_map(
 extern bool efi_reboot_required(void);
 
 #else
-/*
- * IF EFI is not configured, have the EFI calls return -ENOSYS.
- */
-#define efi_call0(_f)                                  (-ENOSYS)
-#define efi_call1(_f, _a1)                             (-ENOSYS)
-#define efi_call2(_f, _a1, _a2)                                (-ENOSYS)
-#define efi_call3(_f, _a1, _a2, _a3)                   (-ENOSYS)
-#define efi_call4(_f, _a1, _a2, _a3, _a4)              (-ENOSYS)
-#define efi_call5(_f, _a1, _a2, _a3, _a4, _a5)         (-ENOSYS)
-#define efi_call6(_f, _a1, _a2, _a3, _a4, _a5, _a6)    (-ENOSYS)
 static inline void parse_efi_setup(u64 phys_addr, u32 data_len) {}
 static inline bool efi_reboot_required(void)
 {
index f15103dff4b43f04e16ff8bbd59354435aec4cb7..d143d216d52bec69b912128d88c3283cd0122c6c 100644 (file)
@@ -40,20 +40,40 @@ void __init efi_bgrt_init(void)
        if (ACPI_FAILURE(status))
                return;
 
-       if (bgrt_tab->header.length < sizeof(*bgrt_tab))
+       if (bgrt_tab->header.length < sizeof(*bgrt_tab)) {
+               pr_err("Ignoring BGRT: invalid length %u (expected %zu)\n",
+                      bgrt_tab->header.length, sizeof(*bgrt_tab));
                return;
-       if (bgrt_tab->version != 1 || bgrt_tab->status != 1)
+       }
+       if (bgrt_tab->version != 1) {
+               pr_err("Ignoring BGRT: invalid version %u (expected 1)\n",
+                      bgrt_tab->version);
+               return;
+       }
+       if (bgrt_tab->status != 1) {
+               pr_err("Ignoring BGRT: invalid status %u (expected 1)\n",
+                      bgrt_tab->status);
+               return;
+       }
+       if (bgrt_tab->image_type != 0) {
+               pr_err("Ignoring BGRT: invalid image type %u (expected 0)\n",
+                      bgrt_tab->image_type);
                return;
-       if (bgrt_tab->image_type != 0 || !bgrt_tab->image_address)
+       }
+       if (!bgrt_tab->image_address) {
+               pr_err("Ignoring BGRT: null image address\n");
                return;
+       }
 
        image = efi_lookup_mapped_addr(bgrt_tab->image_address);
        if (!image) {
                image = early_memremap(bgrt_tab->image_address,
                                       sizeof(bmp_header));
                ioremapped = true;
-               if (!image)
+               if (!image) {
+                       pr_err("Ignoring BGRT: failed to map image header memory\n");
                        return;
+               }
        }
 
        memcpy_fromio(&bmp_header, image, sizeof(bmp_header));
@@ -61,14 +81,18 @@ void __init efi_bgrt_init(void)
                early_iounmap(image, sizeof(bmp_header));
        bgrt_image_size = bmp_header.size;
 
-       bgrt_image = kmalloc(bgrt_image_size, GFP_KERNEL);
-       if (!bgrt_image)
+       bgrt_image = kmalloc(bgrt_image_size, GFP_KERNEL | __GFP_NOWARN);
+       if (!bgrt_image) {
+               pr_err("Ignoring BGRT: failed to allocate memory for image (wanted %zu bytes)\n",
+                      bgrt_image_size);
                return;
+       }
 
        if (ioremapped) {
                image = early_memremap(bgrt_tab->image_address,
                                       bmp_header.size);
                if (!image) {
+                       pr_err("Ignoring BGRT: failed to map image memory\n");
                        kfree(bgrt_image);
                        bgrt_image = NULL;
                        return;
index 850da94fef305f65e20bdb52370cc75c1420fd5c..dbc8627a5cdf6d569a5f69cbea05ebac924d2279 100644 (file)
@@ -70,17 +70,7 @@ static efi_config_table_type_t arch_tables[] __initdata = {
 
 u64 efi_setup;         /* efi setup_data physical address */
 
-static bool disable_runtime __initdata = false;
-static int __init setup_noefi(char *arg)
-{
-       disable_runtime = true;
-       return 0;
-}
-early_param("noefi", setup_noefi);
-
-int add_efi_memmap;
-EXPORT_SYMBOL(add_efi_memmap);
-
+static int add_efi_memmap __initdata;
 static int __init setup_add_efi_memmap(char *arg)
 {
        add_efi_memmap = 1;
@@ -96,7 +86,7 @@ static efi_status_t __init phys_efi_set_virtual_address_map(
 {
        efi_status_t status;
 
-       efi_call_phys_prelog();
+       efi_call_phys_prolog();
        status = efi_call_phys(efi_phys.set_virtual_address_map,
                               memory_map_size, descriptor_size,
                               descriptor_version, virtual_map);
@@ -210,9 +200,12 @@ static void __init print_efi_memmap(void)
        for (p = memmap.map, i = 0;
             p < memmap.map_end;
             p += memmap.desc_size, i++) {
+               char buf[64];
+
                md = p;
-               pr_info("mem%02u: type=%u, attr=0x%llx, range=[0x%016llx-0x%016llx) (%lluMB)\n",
-                       i, md->type, md->attribute, md->phys_addr,
+               pr_info("mem%02u: %s range=[0x%016llx-0x%016llx) (%lluMB)\n",
+                       i, efi_md_typeattr_format(buf, sizeof(buf), md),
+                       md->phys_addr,
                        md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT),
                        (md->num_pages >> (20 - EFI_PAGE_SHIFT)));
        }
@@ -344,9 +337,9 @@ static int __init efi_runtime_init32(void)
        }
 
        /*
-        * We will only need *early* access to the following two
-        * EFI runtime services before set_virtual_address_map
-        * is invoked.
+        * We will only need *early* access to the SetVirtualAddressMap
+        * EFI runtime service. All other runtime services will be called
+        * via the virtual mapping.
         */
        efi_phys.set_virtual_address_map =
                        (efi_set_virtual_address_map_t *)
@@ -368,9 +361,9 @@ static int __init efi_runtime_init64(void)
        }
 
        /*
-        * We will only need *early* access to the following two
-        * EFI runtime services before set_virtual_address_map
-        * is invoked.
+        * We will only need *early* access to the SetVirtualAddressMap
+        * EFI runtime service. All other runtime services will be called
+        * via the virtual mapping.
         */
        efi_phys.set_virtual_address_map =
                        (efi_set_virtual_address_map_t *)
@@ -492,7 +485,7 @@ void __init efi_init(void)
        if (!efi_runtime_supported())
                pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n");
        else {
-               if (disable_runtime || efi_runtime_init())
+               if (efi_runtime_disabled() || efi_runtime_init())
                        return;
        }
        if (efi_memmap_init())
@@ -537,7 +530,7 @@ void __init runtime_code_page_mkexec(void)
        }
 }
 
-void efi_memory_uc(u64 addr, unsigned long size)
+void __init efi_memory_uc(u64 addr, unsigned long size)
 {
        unsigned long page_shift = 1UL << EFI_PAGE_SHIFT;
        u64 npages;
@@ -732,6 +725,7 @@ static void __init kexec_enter_virtual_mode(void)
         */
        if (!efi_is_native()) {
                efi_unmap_memmap();
+               clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
                return;
        }
 
@@ -805,6 +799,7 @@ static void __init __efi_enter_virtual_mode(void)
        new_memmap = efi_map_regions(&count, &pg_shift);
        if (!new_memmap) {
                pr_err("Error reallocating memory, EFI runtime non-functional!\n");
+               clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
                return;
        }
 
@@ -812,8 +807,10 @@ static void __init __efi_enter_virtual_mode(void)
 
        BUG_ON(!efi.systab);
 
-       if (efi_setup_page_tables(__pa(new_memmap), 1 << pg_shift))
+       if (efi_setup_page_tables(__pa(new_memmap), 1 << pg_shift)) {
+               clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
                return;
+       }
 
        efi_sync_low_kernel_mappings();
        efi_dump_pagetable();
@@ -938,14 +935,11 @@ u64 efi_mem_attributes(unsigned long phys_addr)
        return 0;
 }
 
-static int __init parse_efi_cmdline(char *str)
+static int __init arch_parse_efi_cmdline(char *str)
 {
-       if (*str == '=')
-               str++;
-
-       if (!strncmp(str, "old_map", 7))
+       if (parse_option_str(str, "old_map"))
                set_bit(EFI_OLD_MEMMAP, &efi.flags);
 
        return 0;
 }
-early_param("efi", parse_efi_cmdline);
+early_param("efi", arch_parse_efi_cmdline);
index 9ee3491e31fbab7f6643462395d31c6f9f36f1b4..40e7cda529365133b50bab8745d9995c47557d53 100644 (file)
@@ -33,7 +33,7 @@
 
 /*
  * To make EFI call EFI runtime service in physical addressing mode we need
- * prelog/epilog before/after the invocation to disable interrupt, to
+ * prolog/epilog before/after the invocation to disable interrupt, to
  * claim EFI runtime service handler exclusively and to duplicate a memory in
  * low memory space say 0 - 3G.
  */
@@ -41,11 +41,13 @@ static unsigned long efi_rt_eflags;
 
 void efi_sync_low_kernel_mappings(void) {}
 void __init efi_dump_pagetable(void) {}
-int efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
+int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
 {
        return 0;
 }
-void efi_cleanup_page_tables(unsigned long pa_memmap, unsigned num_pages) {}
+void __init efi_cleanup_page_tables(unsigned long pa_memmap, unsigned num_pages)
+{
+}
 
 void __init efi_map_region(efi_memory_desc_t *md)
 {
@@ -55,7 +57,7 @@ void __init efi_map_region(efi_memory_desc_t *md)
 void __init efi_map_region_fixed(efi_memory_desc_t *md) {}
 void __init parse_efi_setup(u64 phys_addr, u32 data_len) {}
 
-void efi_call_phys_prelog(void)
+void __init efi_call_phys_prolog(void)
 {
        struct desc_ptr gdt_descr;
 
@@ -69,7 +71,7 @@ void efi_call_phys_prelog(void)
        load_gdt(&gdt_descr);
 }
 
-void efi_call_phys_epilog(void)
+void __init efi_call_phys_epilog(void)
 {
        struct desc_ptr gdt_descr;
 
index 290d397e1dd9125e408a1ee140fe4d3ced51a33d..35aecb6042fbc1dcf938e8779a0f60961d76aeb6 100644 (file)
@@ -79,7 +79,7 @@ static void __init early_code_mapping_set_exec(int executable)
        }
 }
 
-void __init efi_call_phys_prelog(void)
+void __init efi_call_phys_prolog(void)
 {
        unsigned long vaddress;
        int pgd;
@@ -139,7 +139,7 @@ void efi_sync_low_kernel_mappings(void)
                sizeof(pgd_t) * num_pgds);
 }
 
-int efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
+int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
 {
        unsigned long text;
        struct page *page;
@@ -192,7 +192,7 @@ int efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
        return 0;
 }
 
-void efi_cleanup_page_tables(unsigned long pa_memmap, unsigned num_pages)
+void __init efi_cleanup_page_tables(unsigned long pa_memmap, unsigned num_pages)
 {
        pgd_t *pgd = (pgd_t *)__va(real_mode_header->trampoline_pgd);
 
index fbe66e626c09f437da6110bec5c080ef39e6bf95..040192b50d0209b46b64e2607b0e41fe2bb0123b 100644 (file)
@@ -27,13 +27,13 @@ ENTRY(efi_call_phys)
         * set to 0x0010, DS and SS have been set to 0x0018. In EFI, I found
         * the values of these registers are the same. And, the corresponding
         * GDT entries are identical. So I will do nothing about segment reg
-        * and GDT, but change GDT base register in prelog and epilog.
+        * and GDT, but change GDT base register in prolog and epilog.
         */
 
        /*
         * 1. Now I am running with EIP = <physical address> + PAGE_OFFSET.
         * But to make it smoothly switch from virtual mode to flat mode.
-        * The mapping of lower virtual memory has been created in prelog and
+        * The mapping of lower virtual memory has been created in prolog and
         * epilog.
         */
        movl    $1f, %edx
index 46aa25c8ce06c3366b15357d110111de2bd004fc..3c1c3866d82b683334951d9151dcbfd522189388 100644 (file)
  */
 
 
-/* __attribute__((weak)) makes these declarations overridable */
 /* For every CPU addition a new get_<cpuname>_ops interface needs
  * to be added.
  */
-extern void *get_penwell_ops(void) __attribute__((weak));
-extern void *get_cloverview_ops(void) __attribute__((weak));
-extern void *get_tangier_ops(void) __attribute__((weak));
+extern void *get_penwell_ops(void);
+extern void *get_cloverview_ops(void);
+extern void *get_tangier_ops(void);
index d0f3265fb85d5a1f24646db40cc911364e62bfdf..b23fe37f67c02e563875b0227562ba917150a0d5 100644 (file)
@@ -144,7 +144,7 @@ config ACPI_VIDEO
 
 config ACPI_FAN
        tristate "Fan"
-       select THERMAL
+       depends on THERMAL
        default y
        help
          This driver supports ACPI fan devices, allowing user-mode
index 505d4d79fe3e4ce74a631f487ce243e6ae7decb3..c3b2fcb729f30ffc29482774d1656373526e66e5 100644 (file)
@@ -43,6 +43,7 @@ acpi-y                                += pci_root.o pci_link.o pci_irq.o
 acpi-y                         += acpi_lpss.o
 acpi-y                         += acpi_platform.o
 acpi-y                         += acpi_pnp.o
+acpi-y                         += int340x_thermal.o
 acpi-y                         += power.o
 acpi-y                         += event.o
 acpi-y                         += sysfs.o
index 8d099e636b15ffa5a5a0f92f274e00468dfc3845..6ba8beb6b9d2a515828c3987393dc75fa8b6bc2c 100644 (file)
@@ -115,3 +115,4 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
        kfree(resources);
        return pdev;
 }
+EXPORT_SYMBOL_GPL(acpi_create_platform_device);
index 85bb3d80a11c33adc55cb16c7ebea67d34494f23..143ec6ea1468109a745bce176b2f15d3aaaced19 100644 (file)
@@ -343,6 +343,7 @@ int acpi_device_update_power(struct acpi_device *device, int *state_p)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(acpi_device_update_power);
 
 int acpi_bus_update_power(acpi_handle handle, int *state_p)
 {
index 5328b1090e08681dc4905585470fcd43b2b514f1..caf9b76b7ef83f08bca8d7ba1aac487224d68143 100644 (file)
 #include <linux/uaccess.h>
 #include <linux/thermal.h>
 #include <linux/acpi.h>
-
-#define ACPI_FAN_CLASS                 "fan"
-#define ACPI_FAN_FILE_STATE            "state"
-
-#define _COMPONENT             ACPI_FAN_COMPONENT
-ACPI_MODULE_NAME("fan");
+#include <linux/platform_device.h>
+#include <linux/sort.h>
 
 MODULE_AUTHOR("Paul Diefenbaugh");
 MODULE_DESCRIPTION("ACPI Fan Driver");
 MODULE_LICENSE("GPL");
 
-static int acpi_fan_add(struct acpi_device *device);
-static int acpi_fan_remove(struct acpi_device *device);
+static int acpi_fan_probe(struct platform_device *pdev);
+static int acpi_fan_remove(struct platform_device *pdev);
 
 static const struct acpi_device_id fan_device_ids[] = {
        {"PNP0C0B", 0},
+       {"INT3404", 0},
        {"", 0},
 };
 MODULE_DEVICE_TABLE(acpi, fan_device_ids);
@@ -64,37 +61,100 @@ static struct dev_pm_ops acpi_fan_pm = {
 #define FAN_PM_OPS_PTR NULL
 #endif
 
-static struct acpi_driver acpi_fan_driver = {
-       .name = "fan",
-       .class = ACPI_FAN_CLASS,
-       .ids = fan_device_ids,
-       .ops = {
-               .add = acpi_fan_add,
-               .remove = acpi_fan_remove,
-               },
-       .drv.pm = FAN_PM_OPS_PTR,
+struct acpi_fan_fps {
+       u64 control;
+       u64 trip_point;
+       u64 speed;
+       u64 noise_level;
+       u64 power;
+};
+
+struct acpi_fan_fif {
+       u64 revision;
+       u64 fine_grain_ctrl;
+       u64 step_size;
+       u64 low_speed_notification;
+};
+
+struct acpi_fan {
+       bool acpi4;
+       struct acpi_fan_fif fif;
+       struct acpi_fan_fps *fps;
+       int fps_count;
+       struct thermal_cooling_device *cdev;
+};
+
+static struct platform_driver acpi_fan_driver = {
+       .probe = acpi_fan_probe,
+       .remove = acpi_fan_remove,
+       .driver = {
+               .name = "acpi-fan",
+               .acpi_match_table = fan_device_ids,
+               .pm = FAN_PM_OPS_PTR,
+       },
 };
 
 /* thermal cooling device callbacks */
 static int fan_get_max_state(struct thermal_cooling_device *cdev, unsigned long
                             *state)
 {
-       /* ACPI fan device only support two states: ON/OFF */
-       *state = 1;
+       struct acpi_device *device = cdev->devdata;
+       struct acpi_fan *fan = acpi_driver_data(device);
+
+       if (fan->acpi4)
+               *state = fan->fps_count - 1;
+       else
+               *state = 1;
        return 0;
 }
 
-static int fan_get_cur_state(struct thermal_cooling_device *cdev, unsigned long
-                            *state)
+static int fan_get_state_acpi4(struct acpi_device *device, unsigned long *state)
+{
+       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+       struct acpi_fan *fan = acpi_driver_data(device);
+       union acpi_object *obj;
+       acpi_status status;
+       int control, i;
+
+       status = acpi_evaluate_object(device->handle, "_FST", NULL, &buffer);
+       if (ACPI_FAILURE(status)) {
+               dev_err(&device->dev, "Get fan state failed\n");
+               return status;
+       }
+
+       obj = buffer.pointer;
+       if (!obj || obj->type != ACPI_TYPE_PACKAGE ||
+           obj->package.count != 3 ||
+           obj->package.elements[1].type != ACPI_TYPE_INTEGER) {
+               dev_err(&device->dev, "Invalid _FST data\n");
+               status = -EINVAL;
+               goto err;
+       }
+
+       control = obj->package.elements[1].integer.value;
+       for (i = 0; i < fan->fps_count; i++) {
+               if (control == fan->fps[i].control)
+                       break;
+       }
+       if (i == fan->fps_count) {
+               dev_dbg(&device->dev, "Invalid control value returned\n");
+               status = -EINVAL;
+               goto err;
+       }
+
+       *state = i;
+
+err:
+       kfree(obj);
+       return status;
+}
+
+static int fan_get_state(struct acpi_device *device, unsigned long *state)
 {
-       struct acpi_device *device = cdev->devdata;
        int result;
        int acpi_state = ACPI_STATE_D0;
 
-       if (!device)
-               return -EINVAL;
-
-       result = acpi_bus_update_power(device->handle, &acpi_state);
+       result = acpi_device_update_power(device, &acpi_state);
        if (result)
                return result;
 
@@ -103,21 +163,57 @@ static int fan_get_cur_state(struct thermal_cooling_device *cdev, unsigned long
        return 0;
 }
 
-static int
-fan_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state)
+static int fan_get_cur_state(struct thermal_cooling_device *cdev, unsigned long
+                            *state)
 {
        struct acpi_device *device = cdev->devdata;
-       int result;
+       struct acpi_fan *fan = acpi_driver_data(device);
 
-       if (!device || (state != 0 && state != 1))
+       if (fan->acpi4)
+               return fan_get_state_acpi4(device, state);
+       else
+               return fan_get_state(device, state);
+}
+
+static int fan_set_state(struct acpi_device *device, unsigned long state)
+{
+       if (state != 0 && state != 1)
                return -EINVAL;
 
-       result = acpi_bus_set_power(device->handle,
-                               state ? ACPI_STATE_D0 : ACPI_STATE_D3_COLD);
+       return acpi_device_set_power(device,
+                                    state ? ACPI_STATE_D0 : ACPI_STATE_D3_COLD);
+}
 
-       return result;
+static int fan_set_state_acpi4(struct acpi_device *device, unsigned long state)
+{
+       struct acpi_fan *fan = acpi_driver_data(device);
+       acpi_status status;
+
+       if (state >= fan->fps_count)
+               return -EINVAL;
+
+       status = acpi_execute_simple_method(device->handle, "_FSL",
+                                           fan->fps[state].control);
+       if (ACPI_FAILURE(status)) {
+               dev_dbg(&device->dev, "Failed to set state by _FSL\n");
+               return status;
+       }
+
+       return 0;
 }
 
+static int
+fan_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state)
+{
+       struct acpi_device *device = cdev->devdata;
+       struct acpi_fan *fan = acpi_driver_data(device);
+
+       if (fan->acpi4)
+               return fan_set_state_acpi4(device, state);
+       else
+               return fan_set_state(device, state);
+ }
+
 static const struct thermal_cooling_device_ops fan_cooling_ops = {
        .get_max_state = fan_get_max_state,
        .get_cur_state = fan_get_cur_state,
@@ -129,21 +225,125 @@ static const struct thermal_cooling_device_ops fan_cooling_ops = {
  * --------------------------------------------------------------------------
 */
 
-static int acpi_fan_add(struct acpi_device *device)
+static bool acpi_fan_is_acpi4(struct acpi_device *device)
 {
-       int result = 0;
-       struct thermal_cooling_device *cdev;
+       return acpi_has_method(device->handle, "_FIF") &&
+              acpi_has_method(device->handle, "_FPS") &&
+              acpi_has_method(device->handle, "_FSL") &&
+              acpi_has_method(device->handle, "_FST");
+}
 
-       if (!device)
-               return -EINVAL;
+static int acpi_fan_get_fif(struct acpi_device *device)
+{
+       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+       struct acpi_fan *fan = acpi_driver_data(device);
+       struct acpi_buffer format = { sizeof("NNNN"), "NNNN" };
+       struct acpi_buffer fif = { sizeof(fan->fif), &fan->fif };
+       union acpi_object *obj;
+       acpi_status status;
+
+       status = acpi_evaluate_object(device->handle, "_FIF", NULL, &buffer);
+       if (ACPI_FAILURE(status))
+               return status;
+
+       obj = buffer.pointer;
+       if (!obj || obj->type != ACPI_TYPE_PACKAGE) {
+               dev_err(&device->dev, "Invalid _FIF data\n");
+               status = -EINVAL;
+               goto err;
+       }
 
-       strcpy(acpi_device_name(device), "Fan");
-       strcpy(acpi_device_class(device), ACPI_FAN_CLASS);
+       status = acpi_extract_package(obj, &format, &fif);
+       if (ACPI_FAILURE(status)) {
+               dev_err(&device->dev, "Invalid _FIF element\n");
+               status = -EINVAL;
+       }
 
-       result = acpi_bus_update_power(device->handle, NULL);
-       if (result) {
-               dev_err(&device->dev, "Setting initial power state\n");
-               goto end;
+err:
+       kfree(obj);
+       return status;
+}
+
+static int acpi_fan_speed_cmp(const void *a, const void *b)
+{
+       const struct acpi_fan_fps *fps1 = a;
+       const struct acpi_fan_fps *fps2 = b;
+       return fps1->speed - fps2->speed;
+}
+
+static int acpi_fan_get_fps(struct acpi_device *device)
+{
+       struct acpi_fan *fan = acpi_driver_data(device);
+       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+       union acpi_object *obj;
+       acpi_status status;
+       int i;
+
+       status = acpi_evaluate_object(device->handle, "_FPS", NULL, &buffer);
+       if (ACPI_FAILURE(status))
+               return status;
+
+       obj = buffer.pointer;
+       if (!obj || obj->type != ACPI_TYPE_PACKAGE || obj->package.count < 2) {
+               dev_err(&device->dev, "Invalid _FPS data\n");
+               status = -EINVAL;
+               goto err;
+       }
+
+       fan->fps_count = obj->package.count - 1; /* minus revision field */
+       fan->fps = devm_kzalloc(&device->dev,
+                               fan->fps_count * sizeof(struct acpi_fan_fps),
+                               GFP_KERNEL);
+       if (!fan->fps) {
+               dev_err(&device->dev, "Not enough memory\n");
+               status = -ENOMEM;
+               goto err;
+       }
+       for (i = 0; i < fan->fps_count; i++) {
+               struct acpi_buffer format = { sizeof("NNNNN"), "NNNNN" };
+               struct acpi_buffer fps = { sizeof(fan->fps[i]), &fan->fps[i] };
+               status = acpi_extract_package(&obj->package.elements[i + 1],
+                                             &format, &fps);
+               if (ACPI_FAILURE(status)) {
+                       dev_err(&device->dev, "Invalid _FPS element\n");
+                       break;
+               }
+       }
+
+       /* sort the state array according to fan speed in increase order */
+       sort(fan->fps, fan->fps_count, sizeof(*fan->fps),
+            acpi_fan_speed_cmp, NULL);
+
+err:
+       kfree(obj);
+       return status;
+}
+
+static int acpi_fan_probe(struct platform_device *pdev)
+{
+       int result = 0;
+       struct thermal_cooling_device *cdev;
+       struct acpi_fan *fan;
+       struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
+
+       fan = devm_kzalloc(&pdev->dev, sizeof(*fan), GFP_KERNEL);
+       if (!fan) {
+               dev_err(&device->dev, "No memory for fan\n");
+               return -ENOMEM;
+       }
+       device->driver_data = fan;
+       platform_set_drvdata(pdev, fan);
+
+       if (acpi_fan_is_acpi4(device)) {
+               if (acpi_fan_get_fif(device) || acpi_fan_get_fps(device))
+                       goto end;
+               fan->acpi4 = true;
+       } else {
+               result = acpi_device_update_power(device, NULL);
+               if (result) {
+                       dev_err(&device->dev, "Setting initial power state\n");
+                       goto end;
+               }
        }
 
        cdev = thermal_cooling_device_register("Fan", device,
@@ -153,44 +353,32 @@ static int acpi_fan_add(struct acpi_device *device)
                goto end;
        }
 
-       dev_dbg(&device->dev, "registered as cooling_device%d\n", cdev->id);
+       dev_dbg(&pdev->dev, "registered as cooling_device%d\n", cdev->id);
 
-       device->driver_data = cdev;
-       result = sysfs_create_link(&device->dev.kobj,
+       fan->cdev = cdev;
+       result = sysfs_create_link(&pdev->dev.kobj,
                                   &cdev->device.kobj,
                                   "thermal_cooling");
        if (result)
-               dev_err(&device->dev, "Failed to create sysfs link "
-                       "'thermal_cooling'\n");
+               dev_err(&pdev->dev, "Failed to create sysfs link 'thermal_cooling'\n");
 
        result = sysfs_create_link(&cdev->device.kobj,
-                                  &device->dev.kobj,
+                                  &pdev->dev.kobj,
                                   "device");
        if (result)
-               dev_err(&device->dev, "Failed to create sysfs link 'device'\n");
-
-       dev_info(&device->dev, "ACPI: %s [%s] (%s)\n",
-              acpi_device_name(device), acpi_device_bid(device),
-              !device->power.state ? "on" : "off");
+               dev_err(&pdev->dev, "Failed to create sysfs link 'device'\n");
 
 end:
        return result;
 }
 
-static int acpi_fan_remove(struct acpi_device *device)
+static int acpi_fan_remove(struct platform_device *pdev)
 {
-       struct thermal_cooling_device *cdev;
-
-       if (!device)
-               return -EINVAL;
-
-       cdev =  acpi_driver_data(device);
-       if (!cdev)
-               return -EINVAL;
+       struct acpi_fan *fan = platform_get_drvdata(pdev);
 
-       sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
-       sysfs_remove_link(&cdev->device.kobj, "device");
-       thermal_cooling_device_unregister(cdev);
+       sysfs_remove_link(&pdev->dev.kobj, "thermal_cooling");
+       sysfs_remove_link(&fan->cdev->device.kobj, "device");
+       thermal_cooling_device_unregister(fan->cdev);
 
        return 0;
 }
@@ -198,10 +386,11 @@ static int acpi_fan_remove(struct acpi_device *device)
 #ifdef CONFIG_PM_SLEEP
 static int acpi_fan_suspend(struct device *dev)
 {
-       if (!dev)
-               return -EINVAL;
+       struct acpi_fan *fan = dev_get_drvdata(dev);
+       if (fan->acpi4)
+               return 0;
 
-       acpi_bus_set_power(to_acpi_device(dev)->handle, ACPI_STATE_D0);
+       acpi_device_set_power(ACPI_COMPANION(dev), ACPI_STATE_D0);
 
        return AE_OK;
 }
@@ -209,11 +398,12 @@ static int acpi_fan_suspend(struct device *dev)
 static int acpi_fan_resume(struct device *dev)
 {
        int result;
+       struct acpi_fan *fan = dev_get_drvdata(dev);
 
-       if (!dev)
-               return -EINVAL;
+       if (fan->acpi4)
+               return 0;
 
-       result = acpi_bus_update_power(to_acpi_device(dev)->handle, NULL);
+       result = acpi_device_update_power(ACPI_COMPANION(dev), NULL);
        if (result)
                dev_err(dev, "Error updating fan power state\n");
 
@@ -221,4 +411,4 @@ static int acpi_fan_resume(struct device *dev)
 }
 #endif
 
-module_acpi_driver(acpi_fan_driver);
+module_platform_driver(acpi_fan_driver);
diff --git a/drivers/acpi/int340x_thermal.c b/drivers/acpi/int340x_thermal.c
new file mode 100644 (file)
index 0000000..a27d31d
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * ACPI support for int340x thermal drivers
+ *
+ * Copyright (C) 2014, Intel Corporation
+ * Authors: Zhang Rui <rui.zhang@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 <linux/acpi.h>
+#include <linux/module.h>
+
+#include "internal.h"
+
+#define DO_ENUMERATION 0x01
+static const struct acpi_device_id int340x_thermal_device_ids[] = {
+       {"INT3400", DO_ENUMERATION },
+       {"INT3401"},
+       {"INT3402"},
+       {"INT3403"},
+       {"INT3404"},
+       {"INT3406"},
+       {"INT3407"},
+       {"INT3408"},
+       {"INT3409"},
+       {"INT340A"},
+       {"INT340B"},
+       {""},
+};
+
+static int int340x_thermal_handler_attach(struct acpi_device *adev,
+                                       const struct acpi_device_id *id)
+{
+#if defined(CONFIG_INT340X_THERMAL) || defined(CONFIG_INT340X_THERMAL_MODULE)
+       if (id->driver_data == DO_ENUMERATION)
+               acpi_create_platform_device(adev);
+#endif
+       return 1;
+}
+
+static struct acpi_scan_handler int340x_thermal_handler = {
+       .ids = int340x_thermal_device_ids,
+       .attach = int340x_thermal_handler_attach,
+};
+
+void __init acpi_int340x_thermal_init(void)
+{
+       acpi_scan_add_handler(&int340x_thermal_handler);
+}
index 4c5cf77e7576ea10b9e11a07b7fc5a9adbb60214..447f6d679b29ad7e35ffb8223e58d95266f31dde 100644 (file)
@@ -31,6 +31,7 @@ void acpi_pci_link_init(void);
 void acpi_processor_init(void);
 void acpi_platform_init(void);
 void acpi_pnp_init(void);
+void acpi_int340x_thermal_init(void);
 int acpi_sysfs_init(void);
 void acpi_container_init(void);
 void acpi_memory_hotplug_init(void);
@@ -103,8 +104,6 @@ int acpi_power_get_inferred_state(struct acpi_device *device, int *state);
 int acpi_power_on_resources(struct acpi_device *device, int state);
 int acpi_power_transition(struct acpi_device *device, int state);
 
-int acpi_device_update_power(struct acpi_device *device, int *state_p);
-
 int acpi_wakeup_device_init(void);
 
 #ifdef CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC
@@ -167,13 +166,6 @@ static inline int suspend_nvs_save(void) { return 0; }
 static inline void suspend_nvs_restore(void) {}
 #endif
 
-/*--------------------------------------------------------------------------
-                               Platform bus support
-  -------------------------------------------------------------------------- */
-struct platform_device;
-
-struct platform_device *acpi_create_platform_device(struct acpi_device *adev);
-
 /*--------------------------------------------------------------------------
                                        Video
   -------------------------------------------------------------------------- */
index f1d96e7519cb1c03c3270b9c7920a1400bb44ebd..d670158a26c5b3dcc4789e446a145545479d96b1 100644 (file)
@@ -2315,6 +2315,7 @@ int __init acpi_scan_init(void)
        acpi_container_init();
        acpi_memory_hotplug_init();
        acpi_pnp_init();
+       acpi_int340x_thermal_init();
 
        mutex_lock(&acpi_scan_lock);
        /*
index 112817e963e05f01ab11fe9234ef46ec56cc9886..d24fa1964eb8ff1e6195610f9e258cdd00f22b6c 100644 (file)
@@ -528,7 +528,6 @@ static void acpi_thermal_check(void *data)
 }
 
 /* sys I/F for generic thermal sysfs support */
-#define KELVIN_TO_MILLICELSIUS(t, off) (((t) - (off)) * 100)
 
 static int thermal_get_temp(struct thermal_zone_device *thermal,
                            unsigned long *temp)
@@ -543,7 +542,8 @@ static int thermal_get_temp(struct thermal_zone_device *thermal,
        if (result)
                return result;
 
-       *temp = KELVIN_TO_MILLICELSIUS(tz->temperature, tz->kelvin_offset);
+       *temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(tz->temperature,
+                                                       tz->kelvin_offset);
        return 0;
 }
 
@@ -647,7 +647,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
 
        if (tz->trips.critical.flags.valid) {
                if (!trip) {
-                       *temp = KELVIN_TO_MILLICELSIUS(
+                       *temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(
                                tz->trips.critical.temperature,
                                tz->kelvin_offset);
                        return 0;
@@ -657,7 +657,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
 
        if (tz->trips.hot.flags.valid) {
                if (!trip) {
-                       *temp = KELVIN_TO_MILLICELSIUS(
+                       *temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(
                                tz->trips.hot.temperature,
                                tz->kelvin_offset);
                        return 0;
@@ -667,7 +667,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
 
        if (tz->trips.passive.flags.valid) {
                if (!trip) {
-                       *temp = KELVIN_TO_MILLICELSIUS(
+                       *temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(
                                tz->trips.passive.temperature,
                                tz->kelvin_offset);
                        return 0;
@@ -678,7 +678,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
        for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
                tz->trips.active[i].flags.valid; i++) {
                if (!trip) {
-                       *temp = KELVIN_TO_MILLICELSIUS(
+                       *temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(
                                tz->trips.active[i].temperature,
                                tz->kelvin_offset);
                        return 0;
@@ -694,7 +694,7 @@ static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
        struct acpi_thermal *tz = thermal->devdata;
 
        if (tz->trips.critical.flags.valid) {
-               *temperature = KELVIN_TO_MILLICELSIUS(
+               *temperature = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(
                                tz->trips.critical.temperature,
                                tz->kelvin_offset);
                return 0;
@@ -714,8 +714,8 @@ static int thermal_get_trend(struct thermal_zone_device *thermal,
 
        if (type == THERMAL_TRIP_ACTIVE) {
                unsigned long trip_temp;
-               unsigned long temp = KELVIN_TO_MILLICELSIUS(tz->temperature,
-                                                       tz->kelvin_offset);
+               unsigned long temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(
+                                       tz->temperature, tz->kelvin_offset);
                if (thermal_get_trip_temp(thermal, trip, &trip_temp))
                        return -EINVAL;
 
index 834f35c4bf8d50061e1cae9f0b581cdad9467369..371ac12d25b16ee4c651649a147c7e3e9f9fdc87 100644 (file)
@@ -149,6 +149,21 @@ acpi_extract_package(union acpi_object *package,
                                break;
                        }
                        break;
+               case ACPI_TYPE_LOCAL_REFERENCE:
+                       switch (format_string[i]) {
+                       case 'R':
+                               size_required += sizeof(void *);
+                               tail_offset += sizeof(void *);
+                               break;
+                       default:
+                               printk(KERN_WARNING PREFIX "Invalid package element"
+                                             " [%d] got reference,"
+                                             " expecting [%c]\n",
+                                             i, format_string[i]);
+                               return AE_BAD_DATA;
+                               break;
+                       }
+                       break;
 
                case ACPI_TYPE_PACKAGE:
                default:
@@ -247,7 +262,18 @@ acpi_extract_package(union acpi_object *package,
                                break;
                        }
                        break;
-
+               case ACPI_TYPE_LOCAL_REFERENCE:
+                       switch (format_string[i]) {
+                       case 'R':
+                               *(void **)head =
+                                   (void *)element->reference.handle;
+                               head += sizeof(void *);
+                               break;
+                       default:
+                               /* Should never get here */
+                               break;
+                       }
+                       break;
                case ACPI_TYPE_PACKAGE:
                        /* TBD: handle nested packages... */
                default:
index ec399ad2f059379891a4d384e5b24dc3b9c3ab59..1608f7105c9f882c9e787b34a3aa270d9ace75e5 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/cpu.h>
 #include <linux/err.h>
 #include <linux/of.h>
-#include <linux/mailbox.h>
+#include <linux/pl320-ipc.h>
 #include <linux/platform_device.h>
 
 #define HB_CPUFREQ_CHANGE_NOTE 0x80000001
index 64ecbb501c5080df5e36b90dd73501b7dac881d4..8590099ac148aa767484236cbdd576b421c85303 100644 (file)
@@ -41,6 +41,28 @@ struct efi __read_mostly efi = {
 };
 EXPORT_SYMBOL(efi);
 
+static bool disable_runtime;
+static int __init setup_noefi(char *arg)
+{
+       disable_runtime = true;
+       return 0;
+}
+early_param("noefi", setup_noefi);
+
+bool efi_runtime_disabled(void)
+{
+       return disable_runtime;
+}
+
+static int __init parse_efi_cmdline(char *str)
+{
+       if (parse_option_str(str, "noruntime"))
+               disable_runtime = true;
+
+       return 0;
+}
+early_param("efi", parse_efi_cmdline);
+
 static struct kobject *efi_kobj;
 static struct kobject *efivars_kobj;
 
@@ -423,3 +445,60 @@ int __init efi_get_fdt_params(struct efi_fdt_params *params, int verbose)
        return ret;
 }
 #endif /* CONFIG_EFI_PARAMS_FROM_FDT */
+
+static __initdata char memory_type_name[][20] = {
+       "Reserved",
+       "Loader Code",
+       "Loader Data",
+       "Boot Code",
+       "Boot Data",
+       "Runtime Code",
+       "Runtime Data",
+       "Conventional Memory",
+       "Unusable Memory",
+       "ACPI Reclaim Memory",
+       "ACPI Memory NVS",
+       "Memory Mapped I/O",
+       "MMIO Port Space",
+       "PAL Code"
+};
+
+char * __init efi_md_typeattr_format(char *buf, size_t size,
+                                    const efi_memory_desc_t *md)
+{
+       char *pos;
+       int type_len;
+       u64 attr;
+
+       pos = buf;
+       if (md->type >= ARRAY_SIZE(memory_type_name))
+               type_len = snprintf(pos, size, "[type=%u", md->type);
+       else
+               type_len = snprintf(pos, size, "[%-*s",
+                                   (int)(sizeof(memory_type_name[0]) - 1),
+                                   memory_type_name[md->type]);
+       if (type_len >= size)
+               return buf;
+
+       pos += type_len;
+       size -= type_len;
+
+       attr = md->attribute;
+       if (attr & ~(EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMORY_WT |
+                    EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_WP |
+                    EFI_MEMORY_RP | EFI_MEMORY_XP | EFI_MEMORY_RUNTIME))
+               snprintf(pos, size, "|attr=0x%016llx]",
+                        (unsigned long long)attr);
+       else
+               snprintf(pos, size, "|%3s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s]",
+                        attr & EFI_MEMORY_RUNTIME ? "RUN" : "",
+                        attr & EFI_MEMORY_XP      ? "XP"  : "",
+                        attr & EFI_MEMORY_RP      ? "RP"  : "",
+                        attr & EFI_MEMORY_WP      ? "WP"  : "",
+                        attr & EFI_MEMORY_UCE     ? "UCE" : "",
+                        attr & EFI_MEMORY_WB      ? "WB"  : "",
+                        attr & EFI_MEMORY_WT      ? "WT"  : "",
+                        attr & EFI_MEMORY_WC      ? "WC"  : "",
+                        attr & EFI_MEMORY_UC      ? "UC"  : "");
+       return buf;
+}
index 480339b6b110db047848d33c010c7c217ddd04b2..75ee05964cbc460fc0b6686a50a1f664fac8c0e7 100644 (file)
@@ -226,6 +226,10 @@ unsigned long __init efi_entry(void *handle, efi_system_table_t *sys_table,
                goto fail_free_image;
        }
 
+       status = efi_parse_options(cmdline_ptr);
+       if (status != EFI_SUCCESS)
+               pr_efi_err(sys_table, "Failed to parse EFI cmdline options\n");
+
        /*
         * Unauthenticated device tree data is a security hazard, so
         * ignore 'dtb=' unless UEFI Secure Boot is disabled.
index 32d5cca30f496d88594de5f74d0d1de9bce5057d..a920fec8fe8856132191e5b08b95c227310078f8 100644 (file)
 
 #include "efistub.h"
 
+/*
+ * Some firmware implementations have problems reading files in one go.
+ * A read chunk size of 1MB seems to work for most platforms.
+ *
+ * Unfortunately, reading files in chunks triggers *other* bugs on some
+ * platforms, so we provide a way to disable this workaround, which can
+ * be done by passing "efi=nochunk" on the EFI boot stub command line.
+ *
+ * If you experience issues with initrd images being corrupt it's worth
+ * trying efi=nochunk, but chunking is enabled by default because there
+ * are far more machines that require the workaround than those that
+ * break with it enabled.
+ */
 #define EFI_READ_CHUNK_SIZE    (1024 * 1024)
 
+static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE;
+
 struct file_info {
        efi_file_handle_t *handle;
        u64 size;
@@ -281,6 +296,49 @@ void efi_free(efi_system_table_t *sys_table_arg, unsigned long size,
        efi_call_early(free_pages, addr, nr_pages);
 }
 
+/*
+ * Parse the ASCII string 'cmdline' for EFI options, denoted by the efi=
+ * option, e.g. efi=nochunk.
+ *
+ * It should be noted that efi= is parsed in two very different
+ * environments, first in the early boot environment of the EFI boot
+ * stub, and subsequently during the kernel boot.
+ */
+efi_status_t efi_parse_options(char *cmdline)
+{
+       char *str;
+
+       /*
+        * If no EFI parameters were specified on the cmdline we've got
+        * nothing to do.
+        */
+       str = strstr(cmdline, "efi=");
+       if (!str)
+               return EFI_SUCCESS;
+
+       /* Skip ahead to first argument */
+       str += strlen("efi=");
+
+       /*
+        * Remember, because efi= is also used by the kernel we need to
+        * skip over arguments we don't understand.
+        */
+       while (*str) {
+               if (!strncmp(str, "nochunk", 7)) {
+                       str += strlen("nochunk");
+                       __chunk_size = -1UL;
+               }
+
+               /* Group words together, delimited by "," */
+               while (*str && *str != ',')
+                       str++;
+
+               if (*str == ',')
+                       str++;
+       }
+
+       return EFI_SUCCESS;
+}
 
 /*
  * Check the cmdline for a LILO-style file= arguments.
@@ -423,8 +481,8 @@ efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
                        size = files[j].size;
                        while (size) {
                                unsigned long chunksize;
-                               if (size > EFI_READ_CHUNK_SIZE)
-                                       chunksize = EFI_READ_CHUNK_SIZE;
+                               if (size > __chunk_size)
+                                       chunksize = __chunk_size;
                                else
                                        chunksize = size;
 
index 10daa4bbb25833321ffa15ed72e11b327100aa3c..228bbf91046137de619a4f8f89825e8ccc34b5ab 100644 (file)
  * This file is released under the GPLv2.
  */
 
+#include <linux/bug.h>
 #include <linux/efi.h>
-#include <linux/spinlock.h>             /* spinlock_t */
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
 #include <asm/efi.h>
 
+/*
+ * According to section 7.1 of the UEFI spec, Runtime Services are not fully
+ * reentrant, and there are particular combinations of calls that need to be
+ * serialized. (source: UEFI Specification v2.4A)
+ *
+ * Table 31. Rules for Reentry Into Runtime Services
+ * +------------------------------------+-------------------------------+
+ * | If previous call is busy in       | Forbidden to call             |
+ * +------------------------------------+-------------------------------+
+ * | Any                               | SetVirtualAddressMap()        |
+ * +------------------------------------+-------------------------------+
+ * | ConvertPointer()                  | ConvertPointer()              |
+ * +------------------------------------+-------------------------------+
+ * | SetVariable()                     | ResetSystem()                 |
+ * | UpdateCapsule()                   |                               |
+ * | SetTime()                         |                               |
+ * | SetWakeupTime()                   |                               |
+ * | GetNextHighMonotonicCount()       |                               |
+ * +------------------------------------+-------------------------------+
+ * | GetVariable()                     | GetVariable()                 |
+ * | GetNextVariableName()             | GetNextVariableName()         |
+ * | SetVariable()                     | SetVariable()                 |
+ * | QueryVariableInfo()               | QueryVariableInfo()           |
+ * | UpdateCapsule()                   | UpdateCapsule()               |
+ * | QueryCapsuleCapabilities()                | QueryCapsuleCapabilities()    |
+ * | GetNextHighMonotonicCount()       | GetNextHighMonotonicCount()   |
+ * +------------------------------------+-------------------------------+
+ * | GetTime()                         | GetTime()                     |
+ * | SetTime()                         | SetTime()                     |
+ * | GetWakeupTime()                   | GetWakeupTime()               |
+ * | SetWakeupTime()                   | SetWakeupTime()               |
+ * +------------------------------------+-------------------------------+
+ *
+ * Due to the fact that the EFI pstore may write to the variable store in
+ * interrupt context, we need to use a spinlock for at least the groups that
+ * contain SetVariable() and QueryVariableInfo(). That leaves little else, as
+ * none of the remaining functions are actually ever called at runtime.
+ * So let's just use a single spinlock to serialize all Runtime Services calls.
+ */
+static DEFINE_SPINLOCK(efi_runtime_lock);
+
+/*
+ * Some runtime services calls can be reentrant under NMI, even if the table
+ * above says they are not. (source: UEFI Specification v2.4A)
+ *
+ * Table 32. Functions that may be called after Machine Check, INIT and NMI
+ * +----------------------------+------------------------------------------+
+ * | Function                  | Called after Machine Check, INIT and NMI |
+ * +----------------------------+------------------------------------------+
+ * | GetTime()                 | Yes, even if previously busy.            |
+ * | GetVariable()             | Yes, even if previously busy             |
+ * | GetNextVariableName()     | Yes, even if previously busy             |
+ * | QueryVariableInfo()       | Yes, even if previously busy             |
+ * | SetVariable()             | Yes, even if previously busy             |
+ * | UpdateCapsule()           | Yes, even if previously busy             |
+ * | QueryCapsuleCapabilities()        | Yes, even if previously busy             |
+ * | ResetSystem()             | Yes, even if previously busy             |
+ * +----------------------------+------------------------------------------+
+ *
+ * In order to prevent deadlocks under NMI, the wrappers for these functions
+ * may only grab the efi_runtime_lock or rtc_lock spinlocks if !efi_in_nmi().
+ * However, not all of the services listed are reachable through NMI code paths,
+ * so the the special handling as suggested by the UEFI spec is only implemented
+ * for QueryVariableInfo() and SetVariable(), as these can be reached in NMI
+ * context through efi_pstore_write().
+ */
+
 /*
  * As per commit ef68c8f87ed1 ("x86: Serialize EFI time accesses on rtc_lock"),
  * the EFI specification requires that callers of the time related runtime
@@ -32,7 +101,9 @@ static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
        efi_status_t status;
 
        spin_lock_irqsave(&rtc_lock, flags);
+       spin_lock(&efi_runtime_lock);
        status = efi_call_virt(get_time, tm, tc);
+       spin_unlock(&efi_runtime_lock);
        spin_unlock_irqrestore(&rtc_lock, flags);
        return status;
 }
@@ -43,7 +114,9 @@ static efi_status_t virt_efi_set_time(efi_time_t *tm)
        efi_status_t status;
 
        spin_lock_irqsave(&rtc_lock, flags);
+       spin_lock(&efi_runtime_lock);
        status = efi_call_virt(set_time, tm);
+       spin_unlock(&efi_runtime_lock);
        spin_unlock_irqrestore(&rtc_lock, flags);
        return status;
 }
@@ -56,7 +129,9 @@ static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled,
        efi_status_t status;
 
        spin_lock_irqsave(&rtc_lock, flags);
+       spin_lock(&efi_runtime_lock);
        status = efi_call_virt(get_wakeup_time, enabled, pending, tm);
+       spin_unlock(&efi_runtime_lock);
        spin_unlock_irqrestore(&rtc_lock, flags);
        return status;
 }
@@ -67,7 +142,9 @@ static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
        efi_status_t status;
 
        spin_lock_irqsave(&rtc_lock, flags);
+       spin_lock(&efi_runtime_lock);
        status = efi_call_virt(set_wakeup_time, enabled, tm);
+       spin_unlock(&efi_runtime_lock);
        spin_unlock_irqrestore(&rtc_lock, flags);
        return status;
 }
@@ -78,14 +155,27 @@ static efi_status_t virt_efi_get_variable(efi_char16_t *name,
                                          unsigned long *data_size,
                                          void *data)
 {
-       return efi_call_virt(get_variable, name, vendor, attr, data_size, data);
+       unsigned long flags;
+       efi_status_t status;
+
+       spin_lock_irqsave(&efi_runtime_lock, flags);
+       status = efi_call_virt(get_variable, name, vendor, attr, data_size,
+                              data);
+       spin_unlock_irqrestore(&efi_runtime_lock, flags);
+       return status;
 }
 
 static efi_status_t virt_efi_get_next_variable(unsigned long *name_size,
                                               efi_char16_t *name,
                                               efi_guid_t *vendor)
 {
-       return efi_call_virt(get_next_variable, name_size, name, vendor);
+       unsigned long flags;
+       efi_status_t status;
+
+       spin_lock_irqsave(&efi_runtime_lock, flags);
+       status = efi_call_virt(get_next_variable, name_size, name, vendor);
+       spin_unlock_irqrestore(&efi_runtime_lock, flags);
+       return status;
 }
 
 static efi_status_t virt_efi_set_variable(efi_char16_t *name,
@@ -94,24 +184,61 @@ static efi_status_t virt_efi_set_variable(efi_char16_t *name,
                                          unsigned long data_size,
                                          void *data)
 {
-       return efi_call_virt(set_variable, name, vendor, attr, data_size, data);
+       unsigned long flags;
+       efi_status_t status;
+
+       spin_lock_irqsave(&efi_runtime_lock, flags);
+       status = efi_call_virt(set_variable, name, vendor, attr, data_size,
+                              data);
+       spin_unlock_irqrestore(&efi_runtime_lock, flags);
+       return status;
 }
 
+static efi_status_t
+virt_efi_set_variable_nonblocking(efi_char16_t *name, efi_guid_t *vendor,
+                                 u32 attr, unsigned long data_size,
+                                 void *data)
+{
+       unsigned long flags;
+       efi_status_t status;
+
+       if (!spin_trylock_irqsave(&efi_runtime_lock, flags))
+               return EFI_NOT_READY;
+
+       status = efi_call_virt(set_variable, name, vendor, attr, data_size,
+                              data);
+       spin_unlock_irqrestore(&efi_runtime_lock, flags);
+       return status;
+}
+
+
 static efi_status_t virt_efi_query_variable_info(u32 attr,
                                                 u64 *storage_space,
                                                 u64 *remaining_space,
                                                 u64 *max_variable_size)
 {
+       unsigned long flags;
+       efi_status_t status;
+
        if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
                return EFI_UNSUPPORTED;
 
-       return efi_call_virt(query_variable_info, attr, storage_space,
-                            remaining_space, max_variable_size);
+       spin_lock_irqsave(&efi_runtime_lock, flags);
+       status = efi_call_virt(query_variable_info, attr, storage_space,
+                              remaining_space, max_variable_size);
+       spin_unlock_irqrestore(&efi_runtime_lock, flags);
+       return status;
 }
 
 static efi_status_t virt_efi_get_next_high_mono_count(u32 *count)
 {
-       return efi_call_virt(get_next_high_mono_count, count);
+       unsigned long flags;
+       efi_status_t status;
+
+       spin_lock_irqsave(&efi_runtime_lock, flags);
+       status = efi_call_virt(get_next_high_mono_count, count);
+       spin_unlock_irqrestore(&efi_runtime_lock, flags);
+       return status;
 }
 
 static void virt_efi_reset_system(int reset_type,
@@ -119,17 +246,27 @@ static void virt_efi_reset_system(int reset_type,
                                  unsigned long data_size,
                                  efi_char16_t *data)
 {
+       unsigned long flags;
+
+       spin_lock_irqsave(&efi_runtime_lock, flags);
        __efi_call_virt(reset_system, reset_type, status, data_size, data);
+       spin_unlock_irqrestore(&efi_runtime_lock, flags);
 }
 
 static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules,
                                            unsigned long count,
                                            unsigned long sg_list)
 {
+       unsigned long flags;
+       efi_status_t status;
+
        if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
                return EFI_UNSUPPORTED;
 
-       return efi_call_virt(update_capsule, capsules, count, sg_list);
+       spin_lock_irqsave(&efi_runtime_lock, flags);
+       status = efi_call_virt(update_capsule, capsules, count, sg_list);
+       spin_unlock_irqrestore(&efi_runtime_lock, flags);
+       return status;
 }
 
 static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules,
@@ -137,11 +274,17 @@ static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules,
                                                u64 *max_size,
                                                int *reset_type)
 {
+       unsigned long flags;
+       efi_status_t status;
+
        if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
                return EFI_UNSUPPORTED;
 
-       return efi_call_virt(query_capsule_caps, capsules, count, max_size,
-                            reset_type);
+       spin_lock_irqsave(&efi_runtime_lock, flags);
+       status = efi_call_virt(query_capsule_caps, capsules, count, max_size,
+                              reset_type);
+       spin_unlock_irqrestore(&efi_runtime_lock, flags);
+       return status;
 }
 
 void efi_native_runtime_setup(void)
@@ -153,6 +296,7 @@ void efi_native_runtime_setup(void)
        efi.get_variable = virt_efi_get_variable;
        efi.get_next_variable = virt_efi_get_next_variable;
        efi.set_variable = virt_efi_set_variable;
+       efi.set_variable_nonblocking = virt_efi_set_variable_nonblocking;
        efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count;
        efi.reset_system = virt_efi_reset_system;
        efi.query_variable_info = virt_efi_query_variable_info;
index 5abe943e34042df45d8d1f643b0334e6ceb19748..70a0fb10517f94ea5b28bada280d9935f0693cc7 100644 (file)
@@ -321,11 +321,11 @@ static unsigned long var_name_strnsize(efi_char16_t *variable_name,
  * Print a warning when duplicate EFI variables are encountered and
  * disable the sysfs workqueue since the firmware is buggy.
  */
-static void dup_variable_bug(efi_char16_t *s16, efi_guid_t *vendor_guid,
+static void dup_variable_bug(efi_char16_t *str16, efi_guid_t *vendor_guid,
                             unsigned long len16)
 {
        size_t i, len8 = len16 / sizeof(efi_char16_t);
-       char *s8;
+       char *str8;
 
        /*
         * Disable the workqueue since the algorithm it uses for
@@ -334,16 +334,16 @@ static void dup_variable_bug(efi_char16_t *s16, efi_guid_t *vendor_guid,
         */
        efivar_wq_enabled = false;
 
-       s8 = kzalloc(len8, GFP_KERNEL);
-       if (!s8)
+       str8 = kzalloc(len8, GFP_KERNEL);
+       if (!str8)
                return;
 
        for (i = 0; i < len8; i++)
-               s8[i] = s16[i];
+               str8[i] = str16[i];
 
        printk(KERN_WARNING "efivars: duplicate variable: %s-%pUl\n",
-              s8, vendor_guid);
-       kfree(s8);
+              str8, vendor_guid);
+       kfree(str8);
 }
 
 /**
@@ -595,6 +595,39 @@ int efivar_entry_set(struct efivar_entry *entry, u32 attributes,
 }
 EXPORT_SYMBOL_GPL(efivar_entry_set);
 
+/*
+ * efivar_entry_set_nonblocking - call set_variable_nonblocking()
+ *
+ * This function is guaranteed to not block and is suitable for calling
+ * from crash/panic handlers.
+ *
+ * Crucially, this function will not block if it cannot acquire
+ * __efivars->lock. Instead, it returns -EBUSY.
+ */
+static int
+efivar_entry_set_nonblocking(efi_char16_t *name, efi_guid_t vendor,
+                            u32 attributes, unsigned long size, void *data)
+{
+       const struct efivar_operations *ops = __efivars->ops;
+       unsigned long flags;
+       efi_status_t status;
+
+       if (!spin_trylock_irqsave(&__efivars->lock, flags))
+               return -EBUSY;
+
+       status = check_var_size(attributes, size + ucs2_strsize(name, 1024));
+       if (status != EFI_SUCCESS) {
+               spin_unlock_irqrestore(&__efivars->lock, flags);
+               return -ENOSPC;
+       }
+
+       status = ops->set_variable_nonblocking(name, &vendor, attributes,
+                                              size, data);
+
+       spin_unlock_irqrestore(&__efivars->lock, flags);
+       return efi_status_to_err(status);
+}
+
 /**
  * efivar_entry_set_safe - call set_variable() if enough space in firmware
  * @name: buffer containing the variable name
@@ -622,6 +655,20 @@ int efivar_entry_set_safe(efi_char16_t *name, efi_guid_t vendor, u32 attributes,
        if (!ops->query_variable_store)
                return -ENOSYS;
 
+       /*
+        * If the EFI variable backend provides a non-blocking
+        * ->set_variable() operation and we're in a context where we
+        * cannot block, then we need to use it to avoid live-locks,
+        * since the implication is that the regular ->set_variable()
+        * will block.
+        *
+        * If no ->set_variable_nonblocking() is provided then
+        * ->set_variable() is assumed to be non-blocking.
+        */
+       if (!block && ops->set_variable_nonblocking)
+               return efivar_entry_set_nonblocking(name, vendor, attributes,
+                                                   size,&n