msm-4.14/drivers/power/reset/msm-poweroff.c

740 lines
18 KiB
C
Raw Normal View History

/* Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/reboot.h>
#include <linux/pm.h>
#include <linux/delay.h>
#include <linux/input/qpnp-power-on.h>
#include <linux/of_address.h>
#include <linux/syscore_ops.h>
#include <linux/crash_dump.h>
#include <asm/cacheflush.h>
#include <asm/system_misc.h>
#include <asm/memory.h>
#include <soc/qcom/scm.h>
#include <soc/qcom/restart.h>
#include <soc/qcom/watchdog.h>
#include <soc/qcom/minidump.h>
#define EMERGENCY_DLOAD_MAGIC1 0x322A4F99
#define EMERGENCY_DLOAD_MAGIC2 0xC67E4350
#define EMERGENCY_DLOAD_MAGIC3 0x77777777
#define EMMC_DLOAD_TYPE 0x2
#define SCM_IO_DISABLE_PMIC_ARBITER 1
#define SCM_IO_DEASSERT_PS_HOLD 2
#define SCM_WDOG_DEBUG_BOOT_PART 0x9
#define SCM_DLOAD_FULLDUMP 0X10
#define SCM_EDLOAD_MODE 0X01
#define SCM_DLOAD_CMD 0x10
#define SCM_DLOAD_MINIDUMP 0X20
#define SCM_DLOAD_BOTHDUMPS (SCM_DLOAD_MINIDUMP | SCM_DLOAD_FULLDUMP)
static int restart_mode;
static void *restart_reason;
static bool scm_pmic_arbiter_disable_supported;
static bool scm_deassert_ps_hold_supported;
/* Download mode master kill-switch */
static void __iomem *msm_ps_hold;
static phys_addr_t tcsr_boot_misc_detect;
static void scm_disable_sdi(void);
/*
* Runtime could be only changed value once.
* There is no API from TZ to re-enable the registers.
* So the SDI cannot be re-enabled when it already by-passed.
*/
static int download_mode = 1;
static bool force_warm_reboot;
static int in_panic;
static int panic_prep_restart(struct notifier_block *this,
unsigned long event, void *ptr)
{
in_panic = 1;
return NOTIFY_DONE;
}
static struct notifier_block panic_blk = {
.notifier_call = panic_prep_restart,
};
#ifdef CONFIG_QCOM_DLOAD_MODE
#define EDL_MODE_PROP "qcom,msm-imem-emergency_download_mode"
#define DL_MODE_PROP "qcom,msm-imem-download_mode"
#ifdef CONFIG_RANDOMIZE_BASE
#define KASLR_OFFSET_PROP "qcom,msm-imem-kaslr_offset"
#endif
static struct kobject dload_kobj;
static int dload_type = SCM_DLOAD_FULLDUMP;
static void *dload_mode_addr;
static void *dload_type_addr;
static bool dload_mode_enabled;
static void *emergency_dload_mode_addr;
#ifdef CONFIG_RANDOMIZE_BASE
static void __iomem *kaslr_imem_addr;
#endif
static bool scm_dload_supported;
Merge remote-tracking branch 'remotes/origin/tmp-bb60f28' into msm-4.14 * remotes/origin/tmp-bb60f28: Linux 4.14.37 mac80211_hwsim: fix use-after-free bug in hwsim_exit_net Revert "KVM: X86: Fix SMRAM accessing even if VM is shutdown" RDMA/mlx5: Fix NULL dereference while accessing XRC_TGT QPs perf: Return proper values for user stack errors perf: Fix sample_max_stack maximum check netfilter: x_tables: limit allocation requests for blob rule heads netfilter: compat: reject huge allocation requests netfilter: compat: prepare xt_compat_init_offsets to return errors netfilter: x_tables: add counters allocation wrapper netfilter: x_tables: cap allocations at 512 mbyte alarmtimer: Init nanosleep alarm timer on stack RDMA/core: Reduce poll batch for direct cq polling irqchip/gic-v3: Change pr_debug message to pr_devel cpumask: Make for_each_cpu_wrap() available on UP as well irqchip/gic-v3: Ignore disabled ITS nodes perf test: Fix test trace+probe_libc_inet_pton.sh for s390x powerpc/powernv: IMC fix out of bounds memory access at shutdown locking/qspinlock: Ensure node->count is updated before initialising node x86/platform/UV: Fix GAM Range Table entries less than 1GB powerpc/mm/hash64: Zero PGD pages on allocation vfs/proc/kcore, x86/mm/kcore: Fix SMAP fault when dumping vsyscall user page PM / wakeirq: Fix unbalanced IRQ enable for wakeirq ACPI / EC: Restore polling during noirq suspend/resume phases bpf: fix rlimit in reuseport net selftest net: stmmac: discard disabled flags in interrupt status register SUNRPC: Don't call __UDPX_INC_STATS() from a preemptible context KVM: PPC: Book3S HV: Fix handling of secondary HPTEG in HPT resizing code tools/libbpf: handle issues with bpf ELF objects containing .eh_frames net: Extra '_get' in declaration of arch_get_platform_mac_address svcrdma: Fix Read chunk round-up rxrpc: Don't put crypto buffers on the stack selftests/ftrace: Add some missing glob checks cpufreq: intel_pstate: Enable HWP during system resume on CPU0 bcache: return attach error when no cache set exist bcache: fix for data collapse after re-attaching an attached device bcache: fix for allocator and register thread race bcache: properly set task state in bch_writeback_thread() cifs: silence compiler warnings showing up with gcc-8.0.0 PM / domains: Fix up domain-idle-states OF parsing proc: fix /proc/*/map_files lookup arm64: spinlock: Fix theoretical trylock() A-B-A with LSE atomics RDS: IB: Fix null pointer issue bpf: sockmap, fix leaking maps with attached but not detached progs xen/grant-table: Use put_page instead of free_page xen-netfront: Fix race between device setup and open perf evsel: Fix period/freq terms setup MIPS: Generic: Support GIC in EIC mode perf record: Fix period option handling MIPS: TXx9: use IS_BUILTIN() for CONFIG_LEDS_CLASS bpf: fix selftests/bpf test_kmod.sh failure when CONFIG_BPF_JIT_ALWAYS_ON=y ACPI / scan: Use acpi_bus_get_status() to initialize ACPI_TYPE_DEVICE devs ACPI / bus: Do not call _STA on battery devices with unmet dependencies ACPI: processor_perflib: Do not send _PPC change notification if not ready firmware: dmi_scan: Fix handling of empty DMI strings x86/dumpstack: Avoid uninitlized variable x86/power: Fix swsusp_arch_resume prototype netfilter: ipv6: nf_defrag: Kill frag queue on RFC2460 failure s390/eadm: fix CONFIG_BLOCK include dependency drm/nouveau/pmu/fuc: don't use movw directly anymore IB/core: Map iWarp AH type to undefined in rdma_ah_find_type IB/ipoib: Fix for potential no-carrier state IB/hfi1: Fix for potential refcount leak in hfi1_open_file() IB/hfi1: Re-order IRQ cleanup to address driver cleanup race blk-mq: fix discard merge with scheduler attached openvswitch: Remove padding from packet before L3+ conntrack processing mm/fadvise: discard partial page if endbyte is also EOF mm: pin address_space before dereferencing it while isolating an LRU page mm: thp: use down_read_trylock() in khugepaged to avoid long block sparc64: update pmdp_invalidate() to return old pmd value asm-generic: provide generic_pmdp_establish() mm/mempolicy: add nodes_empty check in SYSC_migrate_pages mm/mempolicy: fix the check of nodemask from user ocfs2: return error when we attempt to access a dirty bh in jbd2 ocfs2/acl: use 'ip_xattr_sem' to protect getting extended attribute ocfs2: return -EROFS to mount.ocfs2 if inode block is invalid fs/dax.c: release PMD lock even when there is no PMD support in DAX x86/kvm/vmx: do not use vm-exit instruction length for fast MMIO when running nested kvm: Map PFN-type memory regions as writable (if possible) tcp_nv: fix potential integer overflow in tcpnv_acked netfilter: x_tables: fix pointer leaks to userspace x86/hyperv: Check for required priviliges in hyperv_init() gianfar: prevent integer wrapping in the rx handler ntb_transport: Fix bug with max_mw_size parameter RDMA/mlx5: Avoid memory leak in case of XRCD dealloc failure powerpc/numa: Ensure nodes initialized for hotplug powerpc/numa: Use ibm,max-associativity-domains to discover possible nodes samples/bpf: Partially fixes the bpf.o build i40e: fix reported mask for ntuple filters i40e: program fragmented IPv4 filter input set ixgbe: don't set RXDCTL.RLPML for 82599 jffs2: Fix use-after-free bug in jffs2_iget()'s error handling path RDMA/uverbs: Use an unambiguous errno for method not supported crypto: artpec6 - remove select on non-existing CRYPTO_SHA384 device property: Define type of PROPERTY_ENRTY_*() macros tty: serial: exar: Relocate sleep wake-up handling x86/hyperv: Stop suppressing X86_FEATURE_PCID fm10k: fix "failed to kill vid" message for VF igb: Clear TXSTMP when ptp_tx_work() is timeout igb: Allow to remove administratively set MAC on VFs ASoC: rockchip: Use dummy_dai for rt5514 dsp dailink blk-mq-debugfs: don't allow write on attributes with seq_operations set KVM: s390: vsie: use READ_ONCE to access some SCB fields platform/x86: thinkpad_acpi: suppress warning about palm detection i40evf: ignore link up if not running i40evf: Don't schedule reset_task when device is being removed bpf: test_maps: cleanup sockmaps when test ends block: Set BIO_TRACE_COMPLETION on new bio during split nfp: fix error return code in nfp_pci_probe() HID: roccat: prevent an out of bounds read in kovaplus_profile_activated() Input: stmfts - set IRQ_NOAUTOEN to the irq flag scsi: fas216: fix sense buffer initialization scsi: devinfo: fix format of the device list f2fs: avoid hungtask when GC encrypted block if io_bits is set RDMA/cma: Check existence of netdevice during port validation Btrfs: raid56: fix race between merge_bio and rbio_orig_end_io Btrfs: fix unexpected EEXIST from btrfs_get_extent btrfs: fail mount when sb flag is not in BTRFS_SUPER_FLAG_SUPP Btrfs: fix scrub to repair raid6 corruption btrfs: Fix out of bounds access in btrfs_search_slot Btrfs: set plug for fsync ipmi/powernv: Fix error return code in ipmi_powernv_probe() mac80211_hwsim: fix possible memory leak in hwsim_new_radio_nl() kconfig: Fix expr_free() E_NOT leak kconfig: Fix automatic menu creation mem leak kconfig: Don't leak main menus during parsing watchdog: sp5100_tco: Fix watchdog disable bit PCI: Add dummy pci_irqd_intx_xlate() for CONFIG_PCI=n build MIPS: Fix clean of vmlinuz.{32,ecoff,bin,srec} nfs: Do not convert nfs_idmap_cache_timeout to jiffies IB/cq: Don't force IB_POLL_DIRECT poll context for ib_process_cq_direct spi: a3700: Clear DATA_OUT when performing a read net: stmmac: dwmac-meson8b: propagate rate changes to the parent clock net: stmmac: dwmac-meson8b: fix setting the RGMII TX clock on Meson8b ubifs: Fix uninitialized variable in search_dh_cookie() blk-mq: turn WARN_ON in __blk_mq_run_hw_queue into printk dm mpath: return DM_MAPIO_REQUEUE on blk-mq rq allocation failure dm thin: fix documentation relative to low water mark threshold iommu/vt-d: Use domain instead of cache fetching powerpc: System reset avoid interleaving oops using die synchronisation iommu/exynos: Don't unconditionally steal bus ops perf record: Fix failed memory allocation for get_cpuid_str tools lib traceevent: Fix get_field_str() for dynamic strings perf callchain: Fix attr.sample_max_stack setting tools lib traceevent: Simplify pointer print logic and fix %pF perf unwind: Do not look just at the global callchain_param.record_mode scsi: qla2xxx: Fix warning in qla2x00_async_iocb_timeout() i40iw: Zero-out consumer key on allocate stag for FMR i40iw: Free IEQ resources Input: synaptics - reset the ABS_X/Y fuzz after initializing MT axes libbpf: Makefile set specified permission mode Input: psmouse - fix Synaptics detection when protocol is disabled PCI: Add function 1 DMA alias quirk for Marvell 9128 selftest: ftrace: Fix to pick text symbols for kprobes xprtrdma: Fix backchannel allocation of extra rpcrdma_reps platform/x86: dell-laptop: Filter out spurious keyboard backlight change events KVM: s390: use created_vcpus in more places tracing/hrtimer: Fix tracing bugs by taking all clock bases and modes into account netfilter: ipv6: nf_defrag: Pass on packets to stack per RFC2460 KVM: PPC: Book3S HV: Enable migration of decrementer register RDMA/core: Clarify rdma_ah_find_type kvm: x86: fix KVM_XEN_HVM_CONFIG ioctl ASoC: au1x: Fix timeout tests in au1xac97c_ac97_read() ALSA: hda - Use IS_REACHABLE() for dependency on input ACPI / LPSS: Do not instiate platform_dev for devs without MMIO resources NFSv4: always set NFS_LOCK_LOST when a lock is lost. x86/tsc: Allow TSC calibration without PIT firewire-ohci: work around oversized DMA reads on JMicron controllers usb: musb: Fix external abort in musb_remove on omap2430 usb: musb: call pm_runtime_{get,put}_sync before reading vbus registers usb: musb: fix enumeration after resume drm/i915/bxt, glk: Increase PCODE timeouts during CDCLK freq changing drm/i915: Fix LSPCON TMDS output buffer enabling from low-power state drm/i915: Do no use kfree() to free a kmem_cache_alloc() return value drm/i915/audio: Fix audio detection issue on GLK drm/i915/gvt: throw error on unhandled vfio ioctls drm/vc4: Fix memory leak during BO teardown x86/tsc: Prevent 32bit truncation in calc_hpet_ref() clocksource/imx-tpm: Correct -ETIME return condition check x86/acpi: Prevent X2APIC id 0xffffffff from being accounted btrfs: fix unaligned access in readdir cifs: do not allow creating sockets except with SMB1 posix exensions UPSTREAM: module: Do not paper over type mismatches in module_param_call() UPSTREAM: treewide: Fix function prototypes for module_param_call() UPSTREAM: module: Prepare to convert all module_param_call() prototypes UPSTREAM: kbuild: add clang-version.sh UPSTREAM: console: Expand dummy functions for CFI UPSTREAM: console: SisUSB2VGA: Drop dummy con_font_get() ANDROID: sdcardfs: Set s_root to NULL after putting ANDROID: sdcardfs: d_make_root calls iput ANDROID: sdcardfs: Check for private data earlier ANDROID: sched: Remove duplicate const specifier Conflicts: kernel/sched/sched.h Change in module_param_call() definition requires alignment in: drivers/hwtracing/coresight/coresight-event.c drivers/power/reset/msm-poweroff.c Change-Id: I0114d2226301af0b1775b37d79db5529653b135d Signed-off-by: Isaac J. Manjarres <isaacm@codeaurora.org>
2018-04-26 09:55:15 -07:00
static int dload_set(const char *val, const struct kernel_param *kp);
/* interface for exporting attributes */
struct reset_attribute {
struct attribute attr;
ssize_t (*show)(struct kobject *kobj, struct attribute *attr,
char *buf);
size_t (*store)(struct kobject *kobj, struct attribute *attr,
const char *buf, size_t count);
};
#define to_reset_attr(_attr) \
container_of(_attr, struct reset_attribute, attr)
#define RESET_ATTR(_name, _mode, _show, _store) \
static struct reset_attribute reset_attr_##_name = \
__ATTR(_name, _mode, _show, _store)
module_param_call(download_mode, dload_set, param_get_int,
&download_mode, 0644);
int scm_set_dload_mode(int arg1, int arg2)
{
struct scm_desc desc = {
.args[0] = arg1,
.args[1] = arg2,
.arginfo = SCM_ARGS(2),
};
if (!scm_dload_supported) {
if (tcsr_boot_misc_detect)
return scm_io_write(tcsr_boot_misc_detect, arg1);
return 0;
}
if (!is_scm_armv8())
return scm_call_atomic2(SCM_SVC_BOOT, SCM_DLOAD_CMD, arg1,
arg2);
return scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_BOOT, SCM_DLOAD_CMD),
&desc);
}
static void set_dload_mode(int on)
{
int ret;
if (dload_mode_addr) {
__raw_writel(on ? 0xE47B337D : 0, dload_mode_addr);
__raw_writel(on ? 0xCE14091A : 0,
dload_mode_addr + sizeof(unsigned int));
/* Make sure the download cookie is updated */
mb();
}
ret = scm_set_dload_mode(on ? dload_type : 0, 0);
if (ret)
pr_err("Failed to set secure DLOAD mode: %d\n", ret);
dload_mode_enabled = on;
}
static bool get_dload_mode(void)
{
return dload_mode_enabled;
}
static void enable_emergency_dload_mode(void)
{
int ret;
if (emergency_dload_mode_addr) {
__raw_writel(EMERGENCY_DLOAD_MAGIC1,
emergency_dload_mode_addr);
__raw_writel(EMERGENCY_DLOAD_MAGIC2,
emergency_dload_mode_addr +
sizeof(unsigned int));
__raw_writel(EMERGENCY_DLOAD_MAGIC3,
emergency_dload_mode_addr +
(2 * sizeof(unsigned int)));
/* Need disable the pmic wdt, then the emergency dload mode
* will not auto reset.
*/
qpnp_pon_wd_config(0);
/* Make sure all the cookied are flushed to memory */
mb();
}
ret = scm_set_dload_mode(SCM_EDLOAD_MODE, 0);
if (ret)
pr_err("Failed to set secure EDLOAD mode: %d\n", ret);
}
Merge remote-tracking branch 'remotes/origin/tmp-bb60f28' into msm-4.14 * remotes/origin/tmp-bb60f28: Linux 4.14.37 mac80211_hwsim: fix use-after-free bug in hwsim_exit_net Revert "KVM: X86: Fix SMRAM accessing even if VM is shutdown" RDMA/mlx5: Fix NULL dereference while accessing XRC_TGT QPs perf: Return proper values for user stack errors perf: Fix sample_max_stack maximum check netfilter: x_tables: limit allocation requests for blob rule heads netfilter: compat: reject huge allocation requests netfilter: compat: prepare xt_compat_init_offsets to return errors netfilter: x_tables: add counters allocation wrapper netfilter: x_tables: cap allocations at 512 mbyte alarmtimer: Init nanosleep alarm timer on stack RDMA/core: Reduce poll batch for direct cq polling irqchip/gic-v3: Change pr_debug message to pr_devel cpumask: Make for_each_cpu_wrap() available on UP as well irqchip/gic-v3: Ignore disabled ITS nodes perf test: Fix test trace+probe_libc_inet_pton.sh for s390x powerpc/powernv: IMC fix out of bounds memory access at shutdown locking/qspinlock: Ensure node->count is updated before initialising node x86/platform/UV: Fix GAM Range Table entries less than 1GB powerpc/mm/hash64: Zero PGD pages on allocation vfs/proc/kcore, x86/mm/kcore: Fix SMAP fault when dumping vsyscall user page PM / wakeirq: Fix unbalanced IRQ enable for wakeirq ACPI / EC: Restore polling during noirq suspend/resume phases bpf: fix rlimit in reuseport net selftest net: stmmac: discard disabled flags in interrupt status register SUNRPC: Don't call __UDPX_INC_STATS() from a preemptible context KVM: PPC: Book3S HV: Fix handling of secondary HPTEG in HPT resizing code tools/libbpf: handle issues with bpf ELF objects containing .eh_frames net: Extra '_get' in declaration of arch_get_platform_mac_address svcrdma: Fix Read chunk round-up rxrpc: Don't put crypto buffers on the stack selftests/ftrace: Add some missing glob checks cpufreq: intel_pstate: Enable HWP during system resume on CPU0 bcache: return attach error when no cache set exist bcache: fix for data collapse after re-attaching an attached device bcache: fix for allocator and register thread race bcache: properly set task state in bch_writeback_thread() cifs: silence compiler warnings showing up with gcc-8.0.0 PM / domains: Fix up domain-idle-states OF parsing proc: fix /proc/*/map_files lookup arm64: spinlock: Fix theoretical trylock() A-B-A with LSE atomics RDS: IB: Fix null pointer issue bpf: sockmap, fix leaking maps with attached but not detached progs xen/grant-table: Use put_page instead of free_page xen-netfront: Fix race between device setup and open perf evsel: Fix period/freq terms setup MIPS: Generic: Support GIC in EIC mode perf record: Fix period option handling MIPS: TXx9: use IS_BUILTIN() for CONFIG_LEDS_CLASS bpf: fix selftests/bpf test_kmod.sh failure when CONFIG_BPF_JIT_ALWAYS_ON=y ACPI / scan: Use acpi_bus_get_status() to initialize ACPI_TYPE_DEVICE devs ACPI / bus: Do not call _STA on battery devices with unmet dependencies ACPI: processor_perflib: Do not send _PPC change notification if not ready firmware: dmi_scan: Fix handling of empty DMI strings x86/dumpstack: Avoid uninitlized variable x86/power: Fix swsusp_arch_resume prototype netfilter: ipv6: nf_defrag: Kill frag queue on RFC2460 failure s390/eadm: fix CONFIG_BLOCK include dependency drm/nouveau/pmu/fuc: don't use movw directly anymore IB/core: Map iWarp AH type to undefined in rdma_ah_find_type IB/ipoib: Fix for potential no-carrier state IB/hfi1: Fix for potential refcount leak in hfi1_open_file() IB/hfi1: Re-order IRQ cleanup to address driver cleanup race blk-mq: fix discard merge with scheduler attached openvswitch: Remove padding from packet before L3+ conntrack processing mm/fadvise: discard partial page if endbyte is also EOF mm: pin address_space before dereferencing it while isolating an LRU page mm: thp: use down_read_trylock() in khugepaged to avoid long block sparc64: update pmdp_invalidate() to return old pmd value asm-generic: provide generic_pmdp_establish() mm/mempolicy: add nodes_empty check in SYSC_migrate_pages mm/mempolicy: fix the check of nodemask from user ocfs2: return error when we attempt to access a dirty bh in jbd2 ocfs2/acl: use 'ip_xattr_sem' to protect getting extended attribute ocfs2: return -EROFS to mount.ocfs2 if inode block is invalid fs/dax.c: release PMD lock even when there is no PMD support in DAX x86/kvm/vmx: do not use vm-exit instruction length for fast MMIO when running nested kvm: Map PFN-type memory regions as writable (if possible) tcp_nv: fix potential integer overflow in tcpnv_acked netfilter: x_tables: fix pointer leaks to userspace x86/hyperv: Check for required priviliges in hyperv_init() gianfar: prevent integer wrapping in the rx handler ntb_transport: Fix bug with max_mw_size parameter RDMA/mlx5: Avoid memory leak in case of XRCD dealloc failure powerpc/numa: Ensure nodes initialized for hotplug powerpc/numa: Use ibm,max-associativity-domains to discover possible nodes samples/bpf: Partially fixes the bpf.o build i40e: fix reported mask for ntuple filters i40e: program fragmented IPv4 filter input set ixgbe: don't set RXDCTL.RLPML for 82599 jffs2: Fix use-after-free bug in jffs2_iget()'s error handling path RDMA/uverbs: Use an unambiguous errno for method not supported crypto: artpec6 - remove select on non-existing CRYPTO_SHA384 device property: Define type of PROPERTY_ENRTY_*() macros tty: serial: exar: Relocate sleep wake-up handling x86/hyperv: Stop suppressing X86_FEATURE_PCID fm10k: fix "failed to kill vid" message for VF igb: Clear TXSTMP when ptp_tx_work() is timeout igb: Allow to remove administratively set MAC on VFs ASoC: rockchip: Use dummy_dai for rt5514 dsp dailink blk-mq-debugfs: don't allow write on attributes with seq_operations set KVM: s390: vsie: use READ_ONCE to access some SCB fields platform/x86: thinkpad_acpi: suppress warning about palm detection i40evf: ignore link up if not running i40evf: Don't schedule reset_task when device is being removed bpf: test_maps: cleanup sockmaps when test ends block: Set BIO_TRACE_COMPLETION on new bio during split nfp: fix error return code in nfp_pci_probe() HID: roccat: prevent an out of bounds read in kovaplus_profile_activated() Input: stmfts - set IRQ_NOAUTOEN to the irq flag scsi: fas216: fix sense buffer initialization scsi: devinfo: fix format of the device list f2fs: avoid hungtask when GC encrypted block if io_bits is set RDMA/cma: Check existence of netdevice during port validation Btrfs: raid56: fix race between merge_bio and rbio_orig_end_io Btrfs: fix unexpected EEXIST from btrfs_get_extent btrfs: fail mount when sb flag is not in BTRFS_SUPER_FLAG_SUPP Btrfs: fix scrub to repair raid6 corruption btrfs: Fix out of bounds access in btrfs_search_slot Btrfs: set plug for fsync ipmi/powernv: Fix error return code in ipmi_powernv_probe() mac80211_hwsim: fix possible memory leak in hwsim_new_radio_nl() kconfig: Fix expr_free() E_NOT leak kconfig: Fix automatic menu creation mem leak kconfig: Don't leak main menus during parsing watchdog: sp5100_tco: Fix watchdog disable bit PCI: Add dummy pci_irqd_intx_xlate() for CONFIG_PCI=n build MIPS: Fix clean of vmlinuz.{32,ecoff,bin,srec} nfs: Do not convert nfs_idmap_cache_timeout to jiffies IB/cq: Don't force IB_POLL_DIRECT poll context for ib_process_cq_direct spi: a3700: Clear DATA_OUT when performing a read net: stmmac: dwmac-meson8b: propagate rate changes to the parent clock net: stmmac: dwmac-meson8b: fix setting the RGMII TX clock on Meson8b ubifs: Fix uninitialized variable in search_dh_cookie() blk-mq: turn WARN_ON in __blk_mq_run_hw_queue into printk dm mpath: return DM_MAPIO_REQUEUE on blk-mq rq allocation failure dm thin: fix documentation relative to low water mark threshold iommu/vt-d: Use domain instead of cache fetching powerpc: System reset avoid interleaving oops using die synchronisation iommu/exynos: Don't unconditionally steal bus ops perf record: Fix failed memory allocation for get_cpuid_str tools lib traceevent: Fix get_field_str() for dynamic strings perf callchain: Fix attr.sample_max_stack setting tools lib traceevent: Simplify pointer print logic and fix %pF perf unwind: Do not look just at the global callchain_param.record_mode scsi: qla2xxx: Fix warning in qla2x00_async_iocb_timeout() i40iw: Zero-out consumer key on allocate stag for FMR i40iw: Free IEQ resources Input: synaptics - reset the ABS_X/Y fuzz after initializing MT axes libbpf: Makefile set specified permission mode Input: psmouse - fix Synaptics detection when protocol is disabled PCI: Add function 1 DMA alias quirk for Marvell 9128 selftest: ftrace: Fix to pick text symbols for kprobes xprtrdma: Fix backchannel allocation of extra rpcrdma_reps platform/x86: dell-laptop: Filter out spurious keyboard backlight change events KVM: s390: use created_vcpus in more places tracing/hrtimer: Fix tracing bugs by taking all clock bases and modes into account netfilter: ipv6: nf_defrag: Pass on packets to stack per RFC2460 KVM: PPC: Book3S HV: Enable migration of decrementer register RDMA/core: Clarify rdma_ah_find_type kvm: x86: fix KVM_XEN_HVM_CONFIG ioctl ASoC: au1x: Fix timeout tests in au1xac97c_ac97_read() ALSA: hda - Use IS_REACHABLE() for dependency on input ACPI / LPSS: Do not instiate platform_dev for devs without MMIO resources NFSv4: always set NFS_LOCK_LOST when a lock is lost. x86/tsc: Allow TSC calibration without PIT firewire-ohci: work around oversized DMA reads on JMicron controllers usb: musb: Fix external abort in musb_remove on omap2430 usb: musb: call pm_runtime_{get,put}_sync before reading vbus registers usb: musb: fix enumeration after resume drm/i915/bxt, glk: Increase PCODE timeouts during CDCLK freq changing drm/i915: Fix LSPCON TMDS output buffer enabling from low-power state drm/i915: Do no use kfree() to free a kmem_cache_alloc() return value drm/i915/audio: Fix audio detection issue on GLK drm/i915/gvt: throw error on unhandled vfio ioctls drm/vc4: Fix memory leak during BO teardown x86/tsc: Prevent 32bit truncation in calc_hpet_ref() clocksource/imx-tpm: Correct -ETIME return condition check x86/acpi: Prevent X2APIC id 0xffffffff from being accounted btrfs: fix unaligned access in readdir cifs: do not allow creating sockets except with SMB1 posix exensions UPSTREAM: module: Do not paper over type mismatches in module_param_call() UPSTREAM: treewide: Fix function prototypes for module_param_call() UPSTREAM: module: Prepare to convert all module_param_call() prototypes UPSTREAM: kbuild: add clang-version.sh UPSTREAM: console: Expand dummy functions for CFI UPSTREAM: console: SisUSB2VGA: Drop dummy con_font_get() ANDROID: sdcardfs: Set s_root to NULL after putting ANDROID: sdcardfs: d_make_root calls iput ANDROID: sdcardfs: Check for private data earlier ANDROID: sched: Remove duplicate const specifier Conflicts: kernel/sched/sched.h Change in module_param_call() definition requires alignment in: drivers/hwtracing/coresight/coresight-event.c drivers/power/reset/msm-poweroff.c Change-Id: I0114d2226301af0b1775b37d79db5529653b135d Signed-off-by: Isaac J. Manjarres <isaacm@codeaurora.org>
2018-04-26 09:55:15 -07:00
static int dload_set(const char *val, const struct kernel_param *kp)
{
int ret;
int old_val = download_mode;
if (!download_mode) {
pr_err("Error: SDI dynamic enablement is not supported\n");
return -EINVAL;
}
ret = param_set_int(val, kp);
if (ret)
return ret;
/* If download_mode is not zero or one, ignore. */
if (download_mode >> 1) {
download_mode = old_val;
return -EINVAL;
}
set_dload_mode(download_mode);
if (!download_mode)
scm_disable_sdi();
return 0;
}
#else
static void set_dload_mode(int on)
{
return;
}
static void enable_emergency_dload_mode(void)
{
pr_err("dload mode is not enabled on target\n");
}
static bool get_dload_mode(void)
{
return false;
}
#endif
static void scm_disable_sdi(void)
{
int ret;
struct scm_desc desc = {
.args[0] = 1,
.args[1] = 0,
.arginfo = SCM_ARGS(2),
};
/* Needed to bypass debug image on some chips */
if (!is_scm_armv8())
ret = scm_call_atomic2(SCM_SVC_BOOT,
SCM_WDOG_DEBUG_BOOT_PART, 1, 0);
else
ret = scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_BOOT,
SCM_WDOG_DEBUG_BOOT_PART), &desc);
if (ret)
pr_err("Failed to disable secure wdog debug: %d\n", ret);
}
void msm_set_restart_mode(int mode)
{
restart_mode = mode;
}
EXPORT_SYMBOL(msm_set_restart_mode);
/*
* Force the SPMI PMIC arbiter to shutdown so that no more SPMI transactions
* are sent from the MSM to the PMIC. This is required in order to avoid an
* SPMI lockup on certain PMIC chips if PS_HOLD is lowered in the middle of
* an SPMI transaction.
*/
static void halt_spmi_pmic_arbiter(void)
{
struct scm_desc desc = {
.args[0] = 0,
.arginfo = SCM_ARGS(1),
};
if (scm_pmic_arbiter_disable_supported) {
pr_crit("Calling SCM to disable SPMI PMIC arbiter\n");
if (!is_scm_armv8())
scm_call_atomic1(SCM_SVC_PWR,
SCM_IO_DISABLE_PMIC_ARBITER, 0);
else
scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_PWR,
SCM_IO_DISABLE_PMIC_ARBITER), &desc);
}
}
static void msm_restart_prepare(const char *cmd)
{
bool need_warm_reset = false;
#ifdef CONFIG_QCOM_DLOAD_MODE
/* Write download mode flags if we're panic'ing
* Write download mode flags if restart_mode says so
* Kill download mode if master-kill switch is set
*/
if (!is_kdump_kernel())
set_dload_mode(download_mode &&
(in_panic || restart_mode == RESTART_DLOAD));
#endif
if (qpnp_pon_check_hard_reset_stored()) {
/* Set warm reset as true when device is in dload mode */
if (get_dload_mode() ||
((cmd != NULL && cmd[0] != '\0') &&
!strcmp(cmd, "edl")))
need_warm_reset = true;
} else {
need_warm_reset = (get_dload_mode() ||
(cmd != NULL && cmd[0] != '\0'));
}
if (force_warm_reboot)
pr_info("Forcing a warm reset of the system\n");
/* Hard reset the PMIC unless memory contents must be maintained. */
if (force_warm_reboot || need_warm_reset)
qpnp_pon_system_pwr_off(PON_POWER_OFF_WARM_RESET);
else
qpnp_pon_system_pwr_off(PON_POWER_OFF_HARD_RESET);
if (cmd != NULL) {
if (!strncmp(cmd, "bootloader", 10)) {
qpnp_pon_set_restart_reason(
PON_RESTART_REASON_BOOTLOADER);
__raw_writel(0x77665500, restart_reason);
} else if (!strncmp(cmd, "recovery", 8)) {
qpnp_pon_set_restart_reason(
PON_RESTART_REASON_RECOVERY);
__raw_writel(0x77665502, restart_reason);
} else if (!strcmp(cmd, "rtc")) {
qpnp_pon_set_restart_reason(
PON_RESTART_REASON_RTC);
__raw_writel(0x77665503, restart_reason);
} else if (!strcmp(cmd, "dm-verity device corrupted")) {
qpnp_pon_set_restart_reason(
PON_RESTART_REASON_DMVERITY_CORRUPTED);
__raw_writel(0x77665508, restart_reason);
} else if (!strcmp(cmd, "dm-verity enforcing")) {
qpnp_pon_set_restart_reason(
PON_RESTART_REASON_DMVERITY_ENFORCE);
__raw_writel(0x77665509, restart_reason);
} else if (!strcmp(cmd, "keys clear")) {
qpnp_pon_set_restart_reason(
PON_RESTART_REASON_KEYS_CLEAR);
__raw_writel(0x7766550a, restart_reason);
} else if (!strncmp(cmd, "oem-", 4)) {
unsigned long code;
int ret;
ret = kstrtoul(cmd + 4, 16, &code);
if (!ret)
__raw_writel(0x6f656d00 | (code & 0xff),
restart_reason);
} else if (!strncmp(cmd, "edl", 3)) {
enable_emergency_dload_mode();
} else {
__raw_writel(0x77665501, restart_reason);
}
}
flush_cache_all();
/*outer_flush_all is not supported by 64bit kernel*/
#ifndef CONFIG_ARM64
outer_flush_all();
#endif
}
/*
* Deassert PS_HOLD to signal the PMIC that we are ready to power down or reset.
* Do this by calling into the secure environment, if available, or by directly
* writing to a hardware register.
*
* This function should never return.
*/
static void deassert_ps_hold(void)
{
struct scm_desc desc = {
.args[0] = 0,
.arginfo = SCM_ARGS(1),
};
if (scm_deassert_ps_hold_supported) {
/* This call will be available on ARMv8 only */
scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_PWR,
SCM_IO_DEASSERT_PS_HOLD), &desc);
}
/* Fall-through to the direct write in case the scm_call "returns" */
__raw_writel(0, msm_ps_hold);
}
static void do_msm_restart(enum reboot_mode reboot_mode, const char *cmd)
{
pr_notice("Going down for restart now\n");
msm_restart_prepare(cmd);
#ifdef CONFIG_QCOM_DLOAD_MODE
/*
* Trigger a watchdog bite here and if this fails,
* device will take the usual restart path.
*/
if (WDOG_BITE_ON_PANIC && in_panic)
msm_trigger_wdog_bite();
#endif
scm_disable_sdi();
halt_spmi_pmic_arbiter();
deassert_ps_hold();
msleep(10000);
}
static void do_msm_poweroff(void)
{
pr_notice("Powering off the SoC\n");
set_dload_mode(0);
scm_disable_sdi();
qpnp_pon_system_pwr_off(PON_POWER_OFF_SHUTDOWN);
halt_spmi_pmic_arbiter();
deassert_ps_hold();
msleep(10000);
pr_err("Powering off has failed\n");
}
#ifdef CONFIG_QCOM_DLOAD_MODE
static ssize_t attr_show(struct kobject *kobj, struct attribute *attr,
char *buf)
{
struct reset_attribute *reset_attr = to_reset_attr(attr);
ssize_t ret = -EIO;
if (reset_attr->show)
ret = reset_attr->show(kobj, attr, buf);
return ret;
}
static ssize_t attr_store(struct kobject *kobj, struct attribute *attr,
const char *buf, size_t count)
{
struct reset_attribute *reset_attr = to_reset_attr(attr);
ssize_t ret = -EIO;
if (reset_attr->store)
ret = reset_attr->store(kobj, attr, buf, count);
return ret;
}
static const struct sysfs_ops reset_sysfs_ops = {
.show = attr_show,
.store = attr_store,
};
static struct kobj_type reset_ktype = {
.sysfs_ops = &reset_sysfs_ops,
};
static ssize_t show_emmc_dload(struct kobject *kobj, struct attribute *attr,
char *buf)
{
uint32_t read_val, show_val;
if (!dload_type_addr)
return -ENODEV;
read_val = __raw_readl(dload_type_addr);
if (read_val == EMMC_DLOAD_TYPE)
show_val = 1;
else
show_val = 0;
return snprintf(buf, sizeof(show_val), "%u\n", show_val);
}
static size_t store_emmc_dload(struct kobject *kobj, struct attribute *attr,
const char *buf, size_t count)
{
uint32_t enabled;
int ret;
if (!dload_type_addr)
return -ENODEV;
ret = kstrtouint(buf, 0, &enabled);
if (ret < 0)
return ret;
if (!((enabled == 0) || (enabled == 1)))
return -EINVAL;
if (enabled == 1)
__raw_writel(EMMC_DLOAD_TYPE, dload_type_addr);
else
__raw_writel(0, dload_type_addr);
return count;
}
#ifdef CONFIG_QCOM_MINIDUMP
static DEFINE_MUTEX(tcsr_lock);
static ssize_t show_dload_mode(struct kobject *kobj, struct attribute *attr,
char *buf)
{
return scnprintf(buf, PAGE_SIZE, "DLOAD dump type: %s\n",
(dload_type == SCM_DLOAD_BOTHDUMPS) ? "both" :
((dload_type == SCM_DLOAD_MINIDUMP) ? "mini" : "full"));
}
static size_t store_dload_mode(struct kobject *kobj, struct attribute *attr,
const char *buf, size_t count)
{
if (sysfs_streq(buf, "full")) {
dload_type = SCM_DLOAD_FULLDUMP;
} else if (sysfs_streq(buf, "mini")) {
if (!msm_minidump_enabled()) {
pr_err("Minidump is not enabled\n");
return -ENODEV;
}
dload_type = SCM_DLOAD_MINIDUMP;
} else if (sysfs_streq(buf, "both")) {
if (!msm_minidump_enabled()) {
pr_err("Minidump not enabled, setting fulldump only\n");
dload_type = SCM_DLOAD_FULLDUMP;
return count;
}
dload_type = SCM_DLOAD_BOTHDUMPS;
} else{
pr_err("Invalid Dump setup request..\n");
pr_err("Supported dumps:'full', 'mini', or 'both'\n");
return -EINVAL;
}
mutex_lock(&tcsr_lock);
/*Overwrite TCSR reg*/
set_dload_mode(dload_type);
mutex_unlock(&tcsr_lock);
return count;
}
RESET_ATTR(dload_mode, 0644, show_dload_mode, store_dload_mode);
#endif
RESET_ATTR(emmc_dload, 0644, show_emmc_dload, store_emmc_dload);
static struct attribute *reset_attrs[] = {
&reset_attr_emmc_dload.attr,
#ifdef CONFIG_QCOM_MINIDUMP
&reset_attr_dload_mode.attr,
#endif
NULL
};
static struct attribute_group reset_attr_group = {
.attrs = reset_attrs,
};
#endif
#if defined(CONFIG_RANDOMIZE_BASE) && defined(CONFIG_HIBERNATION)
static void msm_poweroff_syscore_resume(void)
{
#define KASLR_OFFSET_BIT_MASK 0x00000000FFFFFFFF
if (kaslr_imem_addr) {
__raw_writel(0xdead4ead, kaslr_imem_addr);
__raw_writel(KASLR_OFFSET_BIT_MASK &
(kimage_vaddr - KIMAGE_VADDR), kaslr_imem_addr + 4);
__raw_writel(KASLR_OFFSET_BIT_MASK &
((kimage_vaddr - KIMAGE_VADDR) >> 32),
kaslr_imem_addr + 8);
}
}
static struct syscore_ops msm_poweroff_syscore_ops = {
.resume = msm_poweroff_syscore_resume,
};
#endif
static int msm_restart_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct resource *mem;
struct device_node *np;
int ret = 0;
atomic_notifier_chain_register(&panic_notifier_list, &panic_blk);
#ifdef CONFIG_QCOM_DLOAD_MODE
if (scm_is_call_available(SCM_SVC_BOOT, SCM_DLOAD_CMD) > 0)
scm_dload_supported = true;
np = of_find_compatible_node(NULL, NULL, DL_MODE_PROP);
if (!np) {
pr_err("unable to find DT imem DLOAD mode node\n");
} else {
dload_mode_addr = of_iomap(np, 0);
if (!dload_mode_addr)
pr_err("unable to map imem DLOAD offset\n");
}
np = of_find_compatible_node(NULL, NULL, EDL_MODE_PROP);
if (!np) {
pr_err("unable to find DT imem EDLOAD mode node\n");
} else {
emergency_dload_mode_addr = of_iomap(np, 0);
if (!emergency_dload_mode_addr)
pr_err("unable to map imem EDLOAD mode offset\n");
}
#ifdef CONFIG_RANDOMIZE_BASE
#define KASLR_OFFSET_BIT_MASK 0x00000000FFFFFFFF
np = of_find_compatible_node(NULL, NULL, KASLR_OFFSET_PROP);
if (!np) {
pr_err("unable to find DT imem KASLR_OFFSET node\n");
} else {
kaslr_imem_addr = of_iomap(np, 0);
if (!kaslr_imem_addr)
pr_err("unable to map imem KASLR offset\n");
}
if (kaslr_imem_addr) {
__raw_writel(0xdead4ead, kaslr_imem_addr);
__raw_writel(KASLR_OFFSET_BIT_MASK &
(kimage_vaddr - KIMAGE_VADDR), kaslr_imem_addr + 4);
__raw_writel(KASLR_OFFSET_BIT_MASK &
((kimage_vaddr - KIMAGE_VADDR) >> 32),
kaslr_imem_addr + 8);
}
#ifdef CONFIG_HIBERNATION
register_syscore_ops(&msm_poweroff_syscore_ops);
#endif
#endif
np = of_find_compatible_node(NULL, NULL,
"qcom,msm-imem-dload-type");
if (!np) {
pr_err("unable to find DT imem dload-type node\n");
goto skip_sysfs_create;
} else {
dload_type_addr = of_iomap(np, 0);
if (!dload_type_addr) {
pr_err("unable to map imem dload-type offset\n");
goto skip_sysfs_create;
}
}
ret = kobject_init_and_add(&dload_kobj, &reset_ktype,
kernel_kobj, "%s", "dload");
if (ret) {
pr_err("%s:Error in creation kobject_add\n", __func__);
kobject_put(&dload_kobj);
goto skip_sysfs_create;
}
ret = sysfs_create_group(&dload_kobj, &reset_attr_group);
if (ret) {
pr_err("%s:Error in creation sysfs_create_group\n", __func__);
kobject_del(&dload_kobj);
}
skip_sysfs_create:
#endif
np = of_find_compatible_node(NULL, NULL,
"qcom,msm-imem-restart_reason");
if (!np) {
pr_err("unable to find DT imem restart reason node\n");
} else {
restart_reason = of_iomap(np, 0);
if (!restart_reason) {
pr_err("unable to map imem restart reason offset\n");
ret = -ENOMEM;
goto err_restart_reason;
}
}
mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pshold-base");
msm_ps_hold = devm_ioremap_resource(dev, mem);
if (IS_ERR(msm_ps_hold))
return PTR_ERR(msm_ps_hold);
mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"tcsr-boot-misc-detect");
if (mem)
tcsr_boot_misc_detect = mem->start;
pm_power_off = do_msm_poweroff;
arm_pm_restart = do_msm_restart;
if (scm_is_call_available(SCM_SVC_PWR, SCM_IO_DISABLE_PMIC_ARBITER) > 0)
scm_pmic_arbiter_disable_supported = true;
if (scm_is_call_available(SCM_SVC_PWR, SCM_IO_DEASSERT_PS_HOLD) > 0)
scm_deassert_ps_hold_supported = true;
if (!is_kdump_kernel())
set_dload_mode(download_mode);
if (!download_mode)
scm_disable_sdi();
force_warm_reboot = of_property_read_bool(dev->of_node,
"qcom,force-warm-reboot");
return 0;
err_restart_reason:
#ifdef CONFIG_QCOM_DLOAD_MODE
iounmap(emergency_dload_mode_addr);
iounmap(dload_mode_addr);
#ifdef CONFIG_RANDOMIZE_BASE
iounmap(kaslr_imem_addr);
#endif
#endif
return ret;
}
static const struct of_device_id of_msm_restart_match[] = {
{ .compatible = "qcom,pshold", },
{},
};
MODULE_DEVICE_TABLE(of, of_msm_restart_match);
static struct platform_driver msm_restart_driver = {
.probe = msm_restart_probe,
.driver = {
.name = "msm-restart",
.of_match_table = of_match_ptr(of_msm_restart_match),
},
};
static int __init msm_restart_init(void)
{
return platform_driver_register(&msm_restart_driver);
}
pure_initcall(msm_restart_init);