diff options
| author | Srinivasarao P <spathi@codeaurora.org> | 2019-09-09 11:06:27 +0530 |
|---|---|---|
| committer | Srinivasarao P <spathi@codeaurora.org> | 2019-09-09 11:30:20 +0530 |
| commit | 4bd32b7ba749e007b5e2962e12c13afadee1e193 (patch) | |
| tree | a362fef6427fe59b24c27b3daac86ee276a21280 /arch/x86/power/cpu.c | |
| parent | 9c59fb632e3585fe24af1eb2420bafc5884c010d (diff) | |
| parent | 6da3fbc3ec1e59c2aa5420597785b13c134edf6e (diff) | |
Merge android-4.4.191 (6da3fbc) into msm-4.4
* refs/heads/tmp-6da3fbc
Linux 4.4.191
x86/ptrace: fix up botched merge of spectrev1 fix
mac80211: fix possible sta leak
Revert "cfg80211: fix processing world regdomain when non modular"
VMCI: Release resource if the work is already queued
stm class: Fix a double free of stm_source_device
mmc: core: Fix init of SD cards reporting an invalid VDD range
mmc: sdhci-of-at91: add quirk for broken HS200
uprobes/x86: Fix detection of 32-bit user mode
ptrace,x86: Make user_64bit_mode() available to 32-bit builds
USB: storage: ums-realtek: Whitelist auto-delink support
USB: storage: ums-realtek: Update module parameter description for auto_delink_en
usb: host: ohci: fix a race condition between shutdown and irq
USB: cdc-wdm: fix race between write and disconnect due to flag abuse
usb-storage: Add new JMS567 revision to unusual_devs
x86/apic: Include the LDR when clearing out APIC registers
x86/apic: Do not initialize LDR and DFR for bigsmp
KVM: x86: Don't update RIP or do single-step on faulting emulation
ALSA: seq: Fix potential concurrent access to the deleted pool
tcp: make sure EPOLLOUT wont be missed
ALSA: usb-audio: Fix an OOB bug in parse_audio_mixer_unit
ALSA: usb-audio: Fix a stack buffer overflow bug in check_input_term
tcp: fix tcp_rtx_queue_tail in case of empty retransmit queue
watchdog: bcm2835_wdt: Fix module autoload
tools: hv: fix KVP and VSS daemons exit code
usb: host: fotg2: restart hcd after port reset
usb: gadget: composite: Clear "suspended" on reset/disconnect
dmaengine: ste_dma40: fix unneeded variable warning
scsi: ufs: Fix NULL pointer dereference in ufshcd_config_vreg_hpm()
x86/CPU/AMD: Clear RDRAND CPUID bit on AMD family 15h/16h
x86/pm: Introduce quirk framework to save/restore extra MSR registers around suspend/resume
Revert "perf test 6: Fix missing kvm module load for s390"
netfilter: conntrack: Use consistent ct id hash calculation
netfilter: ctnetlink: don't use conntrack/expect object addresses as id
inet: switch IP ID generator to siphash
siphash: implement HalfSipHash1-3 for hash tables
siphash: add cryptographically secure PRF
vhost: scsi: add weight support
vhost_net: fix possible infinite loop
vhost: introduce vhost_exceeds_weight()
vhost_net: introduce vhost_exceeds_weight()
vhost_net: use packet weight for rx handler, too
vhost-net: set packet weight of tx polling to 2 * vq size
net: arc_emac: fix koops caused by sk_buff free
GFS2: don't set rgrp gl_object until it's inserted into rgrp tree
cgroup: Disable IRQs while holding css_set_lock
dm table: fix invalid memory accesses with too high sector number
dm space map metadata: fix missing store of apply_bops() return value
dm btree: fix order of block initialization in btree_split_beneath
x86/boot: Fix boot regression caused by bootparam sanitizing
x86/boot: Save fields explicitly, zero out everything else
x86/apic: Handle missing global clockevent gracefully
x86/retpoline: Don't clobber RFLAGS during CALL_NOSPEC on i386
userfaultfd_release: always remove uffd flags and clear vm_userfaultfd_ctx
Revert "dm bufio: fix deadlock with loop device"
HID: wacom: correct misreported EKR ring values
selftests: kvm: Adding config fragments
libata: add SG safety checks in SFF pio transfers
net: hisilicon: Fix dma_map_single failed on arm64
net: hisilicon: fix hip04-xmit never return TX_BUSY
net: hisilicon: make hip04_tx_reclaim non-reentrant
net: cxgb3_main: Fix a resource leak in a error path in 'init_one()'
NFSv4: Fix a potential sleep while atomic in nfs4_do_reclaim()
can: peak_usb: force the string buffer NULL-terminated
can: sja1000: force the string buffer NULL-terminated
perf bench numa: Fix cpu0 binding
isdn: hfcsusb: Fix mISDN driver crash caused by transfer buffer on the stack
isdn: mISDN: hfcsusb: Fix possible null-pointer dereferences in start_isoc_chain()
net: usb: qmi_wwan: Add the BroadMobi BM818 card
ASoC: ti: davinci-mcasp: Correct slot_width posed constraint
st_nci_hci_connectivity_event_received: null check the allocation
st21nfca_connectivity_event_received: null check the allocation
can: dev: call netif_carrier_off() in register_candev()
bonding: Force slave speed check after link state recovery for 802.3ad
netfilter: ebtables: fix a memory leak bug in compat
MIPS: kernel: only use i8253 clocksource with periodic clockevent
HID: Add 044f:b320 ThrustMaster, Inc. 2 in 1 DT
ANDROID: sched: Disallow WALT with CFS bandwidth control
ANDROID: fiq_debugger: remove
ANDROID: Add a tracepoint for mapping inode to full path
Conflicts:
drivers/scsi/ufs/ufshcd.c
drivers/staging/android/fiq_debugger/fiq_debugger.c
sound/usb/mixer.c
Change-Id: I95d42e2ce37dd5d32e1737f701976079c43b7501
Signed-off-by: Srinivasarao P <spathi@codeaurora.org>
Diffstat (limited to 'arch/x86/power/cpu.c')
| -rw-r--r-- | arch/x86/power/cpu.c | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c index 9ab52791fed5..2e5052b2d238 100644 --- a/arch/x86/power/cpu.c +++ b/arch/x86/power/cpu.c @@ -12,6 +12,7 @@ #include <linux/export.h> #include <linux/smp.h> #include <linux/perf_event.h> +#include <linux/dmi.h> #include <asm/pgtable.h> #include <asm/proto.h> @@ -23,6 +24,7 @@ #include <asm/debugreg.h> #include <asm/cpu.h> #include <asm/mmu_context.h> +#include <asm/cpu_device_id.h> #ifdef CONFIG_X86_32 __visible unsigned long saved_context_ebx; @@ -32,6 +34,29 @@ __visible unsigned long saved_context_eflags; #endif struct saved_context saved_context; +static void msr_save_context(struct saved_context *ctxt) +{ + struct saved_msr *msr = ctxt->saved_msrs.array; + struct saved_msr *end = msr + ctxt->saved_msrs.num; + + while (msr < end) { + msr->valid = !rdmsrl_safe(msr->info.msr_no, &msr->info.reg.q); + msr++; + } +} + +static void msr_restore_context(struct saved_context *ctxt) +{ + struct saved_msr *msr = ctxt->saved_msrs.array; + struct saved_msr *end = msr + ctxt->saved_msrs.num; + + while (msr < end) { + if (msr->valid) + wrmsrl(msr->info.msr_no, msr->info.reg.q); + msr++; + } +} + /** * __save_processor_state - save CPU registers before creating a * hibernation image and before restoring the memory state from it @@ -111,6 +136,7 @@ static void __save_processor_state(struct saved_context *ctxt) #endif ctxt->misc_enable_saved = !rdmsrl_safe(MSR_IA32_MISC_ENABLE, &ctxt->misc_enable); + msr_save_context(ctxt); } /* Needed by apm.c */ @@ -229,6 +255,7 @@ static void notrace __restore_processor_state(struct saved_context *ctxt) x86_platform.restore_sched_clock_state(); mtrr_bp_restore(); perf_restore_debug_store(); + msr_restore_context(ctxt); } /* Needed by apm.c */ @@ -320,3 +347,128 @@ static int __init bsp_pm_check_init(void) } core_initcall(bsp_pm_check_init); + +static int msr_build_context(const u32 *msr_id, const int num) +{ + struct saved_msrs *saved_msrs = &saved_context.saved_msrs; + struct saved_msr *msr_array; + int total_num; + int i, j; + + total_num = saved_msrs->num + num; + + msr_array = kmalloc_array(total_num, sizeof(struct saved_msr), GFP_KERNEL); + if (!msr_array) { + pr_err("x86/pm: Can not allocate memory to save/restore MSRs during suspend.\n"); + return -ENOMEM; + } + + if (saved_msrs->array) { + /* + * Multiple callbacks can invoke this function, so copy any + * MSR save requests from previous invocations. + */ + memcpy(msr_array, saved_msrs->array, + sizeof(struct saved_msr) * saved_msrs->num); + + kfree(saved_msrs->array); + } + + for (i = saved_msrs->num, j = 0; i < total_num; i++, j++) { + msr_array[i].info.msr_no = msr_id[j]; + msr_array[i].valid = false; + msr_array[i].info.reg.q = 0; + } + saved_msrs->num = total_num; + saved_msrs->array = msr_array; + + return 0; +} + +/* + * The following sections are a quirk framework for problematic BIOSen: + * Sometimes MSRs are modified by the BIOSen after suspended to + * RAM, this might cause unexpected behavior after wakeup. + * Thus we save/restore these specified MSRs across suspend/resume + * in order to work around it. + * + * For any further problematic BIOSen/platforms, + * please add your own function similar to msr_initialize_bdw. + */ +static int msr_initialize_bdw(const struct dmi_system_id *d) +{ + /* Add any extra MSR ids into this array. */ + u32 bdw_msr_id[] = { MSR_IA32_THERM_CONTROL }; + + pr_info("x86/pm: %s detected, MSR saving is needed during suspending.\n", d->ident); + return msr_build_context(bdw_msr_id, ARRAY_SIZE(bdw_msr_id)); +} + +static struct dmi_system_id msr_save_dmi_table[] = { + { + .callback = msr_initialize_bdw, + .ident = "BROADWELL BDX_EP", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "GRANTLEY"), + DMI_MATCH(DMI_PRODUCT_VERSION, "E63448-400"), + }, + }, + {} +}; + +static int msr_save_cpuid_features(const struct x86_cpu_id *c) +{ + u32 cpuid_msr_id[] = { + MSR_AMD64_CPUID_FN_1, + }; + + pr_info("x86/pm: family %#hx cpu detected, MSR saving is needed during suspending.\n", + c->family); + + return msr_build_context(cpuid_msr_id, ARRAY_SIZE(cpuid_msr_id)); +} + +static const struct x86_cpu_id msr_save_cpu_table[] = { + { + .vendor = X86_VENDOR_AMD, + .family = 0x15, + .model = X86_MODEL_ANY, + .feature = X86_FEATURE_ANY, + .driver_data = (kernel_ulong_t)msr_save_cpuid_features, + }, + { + .vendor = X86_VENDOR_AMD, + .family = 0x16, + .model = X86_MODEL_ANY, + .feature = X86_FEATURE_ANY, + .driver_data = (kernel_ulong_t)msr_save_cpuid_features, + }, + {} +}; + +typedef int (*pm_cpu_match_t)(const struct x86_cpu_id *); +static int pm_cpu_check(const struct x86_cpu_id *c) +{ + const struct x86_cpu_id *m; + int ret = 0; + + m = x86_match_cpu(msr_save_cpu_table); + if (m) { + pm_cpu_match_t fn; + + fn = (pm_cpu_match_t)m->driver_data; + ret = fn(m); + } + + return ret; +} + +static int pm_check_save_msr(void) +{ + dmi_check_system(msr_save_dmi_table); + pm_cpu_check(msr_save_cpu_table); + + return 0; +} + +device_initcall(pm_check_save_msr); |
