From b65ce83f2a607ad478c5492812f5f218e8d57a6b Mon Sep 17 00:00:00 2001 From: Len Brown Date: Fri, 18 Nov 2016 01:23:17 -0500 Subject: i7300_idle: Remove this driver In preparation for removing the idle_notifier, remove its only user, the i7300_idle driver. i7300_idle was deployed in 2008 to reduce idle memory power on systems using the i7300 chipset. The driver worked by throttling the fully-buffered DIMMs during idle periods using the IOAT DMA engine. The driver ran only on the i7300 chip-set, and no other hardware has used this mechanism. The driver no longer has a maintainer. Removing this driver will increase idle power on i7300 systems when they run the new kernel without the driver. Signed-off-by: Len Brown Acked-by: Ingo Molnar Acked-by: Peter Zijlstra (Intel) Link: http://lkml.kernel.org/r/ad6a044e57cc75f44cc8621abe846e58f7882243.1479449716.git.len.brown@intel.com Signed-off-by: Thomas Gleixner --- MAINTAINERS | 6 - drivers/dma/ioat/registers.h | 2 - drivers/idle/Kconfig | 17 -- drivers/idle/Makefile | 1 - drivers/idle/i7300_idle.c | 612 ------------------------------------------- 5 files changed, 638 deletions(-) delete mode 100644 drivers/idle/i7300_idle.c diff --git a/MAINTAINERS b/MAINTAINERS index 851b89b9edcb..80db20008488 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6087,12 +6087,6 @@ S: Maintained F: Documentation/cdrom/ide-cd F: drivers/ide/ide-cd* -IDLE-I7300 -M: Andy Henroid -L: linux-pm@vger.kernel.org -S: Supported -F: drivers/idle/i7300_idle.c - IEEE 802.15.4 SUBSYSTEM M: Alexander Aring L: linux-wpan@vger.kernel.org diff --git a/drivers/dma/ioat/registers.h b/drivers/dma/ioat/registers.h index 48fa4cf9f64a..2f3bbc88ff2a 100644 --- a/drivers/dma/ioat/registers.h +++ b/drivers/dma/ioat/registers.h @@ -106,8 +106,6 @@ #define IOAT_DMA_COMP_V1 0x0001 /* Compatibility with DMA version 1 */ #define IOAT_DMA_COMP_V2 0x0002 /* Compatibility with DMA version 2 */ -/* IOAT1 define left for i7300_idle driver to not fail compiling */ -#define IOAT1_CHANSTS_OFFSET 0x04 #define IOAT_CHANSTS_OFFSET 0x08 /* 64-bit Channel Status Register */ #define IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR (~0x3fULL) #define IOAT_CHANSTS_SOFT_ERR 0x10ULL diff --git a/drivers/idle/Kconfig b/drivers/idle/Kconfig index 4732dfc15447..55bcf803841e 100644 --- a/drivers/idle/Kconfig +++ b/drivers/idle/Kconfig @@ -8,20 +8,3 @@ config INTEL_IDLE native Intel hardware idle features. The acpi_idle driver can be configured at the same time, in order to handle processors intel_idle does not support. - -menu "Memory power savings" -depends on X86_64 - -config I7300_IDLE_IOAT_CHANNEL - bool - -config I7300_IDLE - tristate "Intel chipset idle memory power saving driver" - select I7300_IDLE_IOAT_CHANNEL - help - Enable memory power savings when idle with certain Intel server - chipsets. The chipset must have I/O AT support, such as the - Intel 7300. The power savings depends on the type and quantity of - DRAM devices. - -endmenu diff --git a/drivers/idle/Makefile b/drivers/idle/Makefile index 23d295cf10f2..0007111d73e9 100644 --- a/drivers/idle/Makefile +++ b/drivers/idle/Makefile @@ -1,3 +1,2 @@ -obj-$(CONFIG_I7300_IDLE) += i7300_idle.o obj-$(CONFIG_INTEL_IDLE) += intel_idle.o diff --git a/drivers/idle/i7300_idle.c b/drivers/idle/i7300_idle.c deleted file mode 100644 index ffeebc7e9f1c..000000000000 --- a/drivers/idle/i7300_idle.c +++ /dev/null @@ -1,612 +0,0 @@ -/* - * (C) Copyright 2008 Intel Corporation - * Authors: - * Andy Henroid - * Venkatesh Pallipadi - */ - -/* - * Save DIMM power on Intel 7300-based platforms when all CPUs/cores - * are idle, using the DIMM thermal throttling capability. - * - * This driver depends on the Intel integrated DMA controller (I/O AT). - * If the driver for I/O AT (drivers/dma/ioatdma*) is also enabled, - * this driver should work cooperatively. - */ - -/* #define DEBUG */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "../dma/ioat/hw.h" -#include "../dma/ioat/registers.h" - -#define I7300_IDLE_DRIVER_VERSION "1.55" -#define I7300_PRINT "i7300_idle:" - -#define MAX_STOP_RETRIES 10 - -static int debug; -module_param_named(debug, debug, uint, 0644); -MODULE_PARM_DESC(debug, "Enable debug printks in this driver"); - -static int forceload; -module_param_named(forceload, forceload, uint, 0644); -MODULE_PARM_DESC(debug, "Enable driver testing on unvalidated i5000"); - -#define dprintk(fmt, arg...) \ - do { if (debug) printk(KERN_INFO I7300_PRINT fmt, ##arg); } while (0) - -/* - * Value to set THRTLOW to when initiating throttling - * 0 = No throttling - * 1 = Throttle when > 4 activations per eval window (Maximum throttling) - * 2 = Throttle when > 8 activations - * 168 = Throttle when > 672 activations (Minimum throttling) - */ -#define MAX_THROTTLE_LOW_LIMIT 168 -static uint throttle_low_limit = 1; -module_param_named(throttle_low_limit, throttle_low_limit, uint, 0644); -MODULE_PARM_DESC(throttle_low_limit, - "Value for THRTLOWLM activation field " - "(0 = disable throttle, 1 = Max throttle, 168 = Min throttle)"); - -/* - * simple invocation and duration statistics - */ -static unsigned long total_starts; -static unsigned long total_us; - -#ifdef DEBUG -static unsigned long past_skip; -#endif - -static struct pci_dev *fbd_dev; - -static raw_spinlock_t i7300_idle_lock; -static int i7300_idle_active; - -static u8 i7300_idle_thrtctl_saved; -static u8 i7300_idle_thrtlow_saved; -static u32 i7300_idle_mc_saved; - -static cpumask_var_t idle_cpumask; -static ktime_t start_ktime; -static unsigned long avg_idle_us; - -static struct dentry *debugfs_dir; - -/* Begin: I/O AT Helper routines */ - -#define IOAT_CHANBASE(ioat_ctl, chan) (ioat_ctl + 0x80 + 0x80 * chan) -/* Snoop control (disable snoops when coherency is not important) */ -#define IOAT_DESC_SADDR_SNP_CTL (1UL << 1) -#define IOAT_DESC_DADDR_SNP_CTL (1UL << 2) - -static struct pci_dev *ioat_dev; -static struct ioat_dma_descriptor *ioat_desc; /* I/O AT desc & data (1 page) */ -static unsigned long ioat_desc_phys; -static u8 *ioat_iomap; /* I/O AT memory-mapped control regs (aka CB_BAR) */ -static u8 *ioat_chanbase; - -/* Start I/O AT memory copy */ -static int i7300_idle_ioat_start(void) -{ - u32 err; - /* Clear error (due to circular descriptor pointer) */ - err = readl(ioat_chanbase + IOAT_CHANERR_OFFSET); - if (err) - writel(err, ioat_chanbase + IOAT_CHANERR_OFFSET); - - writeb(IOAT_CHANCMD_START, ioat_chanbase + IOAT1_CHANCMD_OFFSET); - return 0; -} - -/* Stop I/O AT memory copy */ -static void i7300_idle_ioat_stop(void) -{ - int i; - u64 sts; - - for (i = 0; i < MAX_STOP_RETRIES; i++) { - writeb(IOAT_CHANCMD_RESET, - ioat_chanbase + IOAT1_CHANCMD_OFFSET); - - udelay(10); - - sts = readq(ioat_chanbase + IOAT1_CHANSTS_OFFSET) & - IOAT_CHANSTS_STATUS; - - if (sts != IOAT_CHANSTS_ACTIVE) - break; - - } - - if (i == MAX_STOP_RETRIES) { - dprintk("failed to stop I/O AT after %d retries\n", - MAX_STOP_RETRIES); - } -} - -/* Test I/O AT by copying 1024 byte from 2k to 1k */ -static int __init i7300_idle_ioat_selftest(u8 *ctl, - struct ioat_dma_descriptor *desc, unsigned long desc_phys) -{ - u64 chan_sts; - - memset(desc, 0, 2048); - memset((u8 *) desc + 2048, 0xab, 1024); - - desc[0].size = 1024; - desc[0].ctl = 0; - desc[0].src_addr = desc_phys + 2048; - desc[0].dst_addr = desc_phys + 1024; - desc[0].next = 0; - - writeb(IOAT_CHANCMD_RESET, ioat_chanbase + IOAT1_CHANCMD_OFFSET); - writeb(IOAT_CHANCMD_START, ioat_chanbase + IOAT1_CHANCMD_OFFSET); - - udelay(1000); - - chan_sts = readq(ioat_chanbase + IOAT1_CHANSTS_OFFSET) & - IOAT_CHANSTS_STATUS; - - if (chan_sts != IOAT_CHANSTS_DONE) { - /* Not complete, reset the channel */ - writeb(IOAT_CHANCMD_RESET, - ioat_chanbase + IOAT1_CHANCMD_OFFSET); - return -1; - } - - if (*(u32 *) ((u8 *) desc + 3068) != 0xabababab || - *(u32 *) ((u8 *) desc + 2044) != 0xabababab) { - dprintk("Data values src 0x%x, dest 0x%x, memset 0x%x\n", - *(u32 *) ((u8 *) desc + 2048), - *(u32 *) ((u8 *) desc + 1024), - *(u32 *) ((u8 *) desc + 3072)); - return -1; - } - return 0; -} - -static struct device dummy_dma_dev = { - .init_name = "fallback device", - .coherent_dma_mask = DMA_BIT_MASK(64), - .dma_mask = &dummy_dma_dev.coherent_dma_mask, -}; - -/* Setup and initialize I/O AT */ -/* This driver needs I/O AT as the throttling takes effect only when there is - * some memory activity. We use I/O AT to set up a dummy copy, while all CPUs - * go idle and memory is throttled. - */ -static int __init i7300_idle_ioat_init(void) -{ - u8 ver, chan_count, ioat_chan; - u16 chan_ctl; - - ioat_iomap = (u8 *) ioremap_nocache(pci_resource_start(ioat_dev, 0), - pci_resource_len(ioat_dev, 0)); - - if (!ioat_iomap) { - printk(KERN_ERR I7300_PRINT "failed to map I/O AT registers\n"); - goto err_ret; - } - - ver = readb(ioat_iomap + IOAT_VER_OFFSET); - if (ver != IOAT_VER_1_2) { - printk(KERN_ERR I7300_PRINT "unknown I/O AT version (%u.%u)\n", - ver >> 4, ver & 0xf); - goto err_unmap; - } - - chan_count = readb(ioat_iomap + IOAT_CHANCNT_OFFSET); - if (!chan_count) { - printk(KERN_ERR I7300_PRINT "unexpected # of I/O AT channels " - "(%u)\n", - chan_count); - goto err_unmap; - } - - ioat_chan = chan_count - 1; - ioat_chanbase = IOAT_CHANBASE(ioat_iomap, ioat_chan); - - chan_ctl = readw(ioat_chanbase + IOAT_CHANCTRL_OFFSET); - if (chan_ctl & IOAT_CHANCTRL_CHANNEL_IN_USE) { - printk(KERN_ERR I7300_PRINT "channel %d in use\n", ioat_chan); - goto err_unmap; - } - - writew(IOAT_CHANCTRL_CHANNEL_IN_USE, - ioat_chanbase + IOAT_CHANCTRL_OFFSET); - - ioat_desc = (struct ioat_dma_descriptor *)dma_alloc_coherent( - &dummy_dma_dev, 4096, - (dma_addr_t *)&ioat_desc_phys, GFP_KERNEL); - if (!ioat_desc) { - printk(KERN_ERR I7300_PRINT "failed to allocate I/O AT desc\n"); - goto err_mark_unused; - } - - writel(ioat_desc_phys & 0xffffffffUL, - ioat_chanbase + IOAT1_CHAINADDR_OFFSET_LOW); - writel(ioat_desc_phys >> 32, - ioat_chanbase + IOAT1_CHAINADDR_OFFSET_HIGH); - - if (i7300_idle_ioat_selftest(ioat_iomap, ioat_desc, ioat_desc_phys)) { - printk(KERN_ERR I7300_PRINT "I/O AT self-test failed\n"); - goto err_free; - } - - /* Setup circular I/O AT descriptor chain */ - ioat_desc[0].ctl = IOAT_DESC_SADDR_SNP_CTL | IOAT_DESC_DADDR_SNP_CTL; - ioat_desc[0].src_addr = ioat_desc_phys + 2048; - ioat_desc[0].dst_addr = ioat_desc_phys + 3072; - ioat_desc[0].size = 128; - ioat_desc[0].next = ioat_desc_phys + sizeof(struct ioat_dma_descriptor); - - ioat_desc[1].ctl = ioat_desc[0].ctl; - ioat_desc[1].src_addr = ioat_desc[0].src_addr; - ioat_desc[1].dst_addr = ioat_desc[0].dst_addr; - ioat_desc[1].size = ioat_desc[0].size; - ioat_desc[1].next = ioat_desc_phys; - - return 0; - -err_free: - dma_free_coherent(&dummy_dma_dev, 4096, (void *)ioat_desc, 0); -err_mark_unused: - writew(0, ioat_chanbase + IOAT_CHANCTRL_OFFSET); -err_unmap: - iounmap(ioat_iomap); -err_ret: - return -ENODEV; -} - -/* Cleanup I/O AT */ -static void __exit i7300_idle_ioat_exit(void) -{ - int i; - u64 chan_sts; - - i7300_idle_ioat_stop(); - - /* Wait for a while for the channel to halt before releasing */ - for (i = 0; i < MAX_STOP_RETRIES; i++) { - writeb(IOAT_CHANCMD_RESET, - ioat_chanbase + IOAT1_CHANCMD_OFFSET); - - chan_sts = readq(ioat_chanbase + IOAT1_CHANSTS_OFFSET) & - IOAT_CHANSTS_STATUS; - - if (chan_sts != IOAT_CHANSTS_ACTIVE) { - writew(0, ioat_chanbase + IOAT_CHANCTRL_OFFSET); - break; - } - udelay(1000); - } - - chan_sts = readq(ioat_chanbase + IOAT1_CHANSTS_OFFSET) & - IOAT_CHANSTS_STATUS; - - /* - * We tried to reset multiple times. If IO A/T channel is still active - * flag an error and return without cleanup. Memory leak is better - * than random corruption in that extreme error situation. - */ - if (chan_sts == IOAT_CHANSTS_ACTIVE) { - printk(KERN_ERR I7300_PRINT "Unable to stop IO A/T channels." - " Not freeing resources\n"); - return; - } - - dma_free_coherent(&dummy_dma_dev, 4096, (void *)ioat_desc, 0); - iounmap(ioat_iomap); -} - -/* End: I/O AT Helper routines */ - -#define DIMM_THRTLOW 0x64 -#define DIMM_THRTCTL 0x67 -#define DIMM_THRTCTL_THRMHUNT (1UL << 0) -#define DIMM_MC 0x40 -#define DIMM_GTW_MODE (1UL << 17) -#define DIMM_GBLACT 0x60 - -/* - * Keep track of an exponential-decaying average of recent idle durations. - * The latest duration gets DURATION_WEIGHT_PCT percentage weight - * in this average, with the old average getting the remaining weight. - * - * High weights emphasize recent history, low weights include long history. - */ -#define DURATION_WEIGHT_PCT 55 - -/* - * When the decaying average of recent durations or the predicted duration - * of the next timer interrupt is shorter than duration_threshold, the - * driver will decline to throttle. - */ -#define DURATION_THRESHOLD_US 100 - - -/* Store DIMM thermal throttle configuration */ -static int i7300_idle_thrt_save(void) -{ - u32 new_mc_val; - u8 gblactlm; - - pci_read_config_byte(fbd_dev, DIMM_THRTCTL, &i7300_idle_thrtctl_saved); - pci_read_config_byte(fbd_dev, DIMM_THRTLOW, &i7300_idle_thrtlow_saved); - pci_read_config_dword(fbd_dev, DIMM_MC, &i7300_idle_mc_saved); - /* - * Make sure we have Global Throttling Window Mode set to have a - * "short" window. This (mostly) works around an issue where - * throttling persists until the end of the global throttling window - * size. On the tested system, this was resulting in a maximum of - * 64 ms to exit throttling (average 32 ms). The actual numbers - * depends on system frequencies. Setting the short window reduces - * this by a factor of 4096. - * - * We will only do this only if the system is set for - * unlimited-activations while in open-loop throttling (i.e., when - * Global Activation Throttle Limit is zero). - */ - pci_read_config_byte(fbd_dev, DIMM_GBLACT, &gblactlm); - dprintk("thrtctl_saved = 0x%02x, thrtlow_saved = 0x%02x\n", - i7300_idle_thrtctl_saved, - i7300_idle_thrtlow_saved); - dprintk("mc_saved = 0x%08x, gblactlm = 0x%02x\n", - i7300_idle_mc_saved, - gblactlm); - if (gblactlm == 0) { - new_mc_val = i7300_idle_mc_saved | DIMM_GTW_MODE; - pci_write_config_dword(fbd_dev, DIMM_MC, new_mc_val); - return 0; - } else { - dprintk("could not set GTW_MODE = 1 (OLTT enabled)\n"); - return -ENODEV; - } -} - -/* Restore DIMM thermal throttle configuration */ -static void i7300_idle_thrt_restore(void) -{ - pci_write_config_dword(fbd_dev, DIMM_MC, i7300_idle_mc_saved); - pci_write_config_byte(fbd_dev, DIMM_THRTLOW, i7300_idle_thrtlow_saved); - pci_write_config_byte(fbd_dev, DIMM_THRTCTL, i7300_idle_thrtctl_saved); -} - -/* Enable DIMM thermal throttling */ -static void i7300_idle_start(void) -{ - u8 new_ctl; - u8 limit; - - new_ctl = i7300_idle_thrtctl_saved & ~DIMM_THRTCTL_THRMHUNT; - pci_write_config_byte(fbd_dev, DIMM_THRTCTL, new_ctl); - - limit = throttle_low_limit; - if (unlikely(limit > MAX_THROTTLE_LOW_LIMIT)) - limit = MAX_THROTTLE_LOW_LIMIT; - - pci_write_config_byte(fbd_dev, DIMM_THRTLOW, limit); - - new_ctl = i7300_idle_thrtctl_saved | DIMM_THRTCTL_THRMHUNT; - pci_write_config_byte(fbd_dev, DIMM_THRTCTL, new_ctl); -} - -/* Disable DIMM thermal throttling */ -static void i7300_idle_stop(void) -{ - u8 new_ctl; - u8 got_ctl; - - new_ctl = i7300_idle_thrtctl_saved & ~DIMM_THRTCTL_THRMHUNT; - pci_write_config_byte(fbd_dev, DIMM_THRTCTL, new_ctl); - - pci_write_config_byte(fbd_dev, DIMM_THRTLOW, i7300_idle_thrtlow_saved); - pci_write_config_byte(fbd_dev, DIMM_THRTCTL, i7300_idle_thrtctl_saved); - pci_read_config_byte(fbd_dev, DIMM_THRTCTL, &got_ctl); - WARN_ON_ONCE(got_ctl != i7300_idle_thrtctl_saved); -} - - -/* - * i7300_avg_duration_check() - * return 0 if the decaying average of recent idle durations is - * more than DURATION_THRESHOLD_US - */ -static int i7300_avg_duration_check(void) -{ - if (avg_idle_us >= DURATION_THRESHOLD_US) - return 0; - -#ifdef DEBUG - past_skip++; -#endif - return 1; -} - -/* Idle notifier to look at idle CPUs */ -static int i7300_idle_notifier(struct notifier_block *nb, unsigned long val, - void *data) -{ - unsigned long flags; - ktime_t now_ktime; - static ktime_t idle_begin_time; - static int time_init = 1; - - if (!throttle_low_limit) - return 0; - - if (unlikely(time_init)) { - time_init = 0; - idle_begin_time = ktime_get(); - } - - raw_spin_lock_irqsave(&i7300_idle_lock, flags); - if (val == IDLE_START) { - - cpumask_set_cpu(smp_processor_id(), idle_cpumask); - - if (cpumask_weight(idle_cpumask) != num_online_cpus()) - goto end; - - now_ktime = ktime_get(); - idle_begin_time = now_ktime; - - if (i7300_avg_duration_check()) - goto end; - - i7300_idle_active = 1; - total_starts++; - start_ktime = now_ktime; - - i7300_idle_start(); - i7300_idle_ioat_start(); - - } else if (val == IDLE_END) { - cpumask_clear_cpu(smp_processor_id(), idle_cpumask); - if (cpumask_weight(idle_cpumask) == (num_online_cpus() - 1)) { - /* First CPU coming out of idle */ - u64 idle_duration_us; - - now_ktime = ktime_get(); - - idle_duration_us = ktime_to_us(ktime_sub - (now_ktime, idle_begin_time)); - - avg_idle_us = - ((100 - DURATION_WEIGHT_PCT) * avg_idle_us + - DURATION_WEIGHT_PCT * idle_duration_us) / 100; - - if (i7300_idle_active) { - ktime_t idle_ktime; - - idle_ktime = ktime_sub(now_ktime, start_ktime); - total_us += ktime_to_us(idle_ktime); - - i7300_idle_ioat_stop(); - i7300_idle_stop(); - i7300_idle_active = 0; - } - } - } -end: - raw_spin_unlock_irqrestore(&i7300_idle_lock, flags); - return 0; -} - -static struct notifier_block i7300_idle_nb = { - .notifier_call = i7300_idle_notifier, -}; - -MODULE_DEVICE_TABLE(pci, pci_tbl); - -static ssize_t stats_read_ul(struct file *fp, char __user *ubuf, size_t count, - loff_t *off) -{ - unsigned long *p = fp->private_data; - char buf[32]; - int len; - - len = snprintf(buf, 32, "%lu\n", *p); - return simple_read_from_buffer(ubuf, count, off, buf, len); -} - -static const struct file_operations idle_fops = { - .open = simple_open, - .read = stats_read_ul, - .llseek = default_llseek, -}; - -struct debugfs_file_info { - void *ptr; - char name[32]; - struct dentry *file; -} debugfs_file_list[] = { - {&total_starts, "total_starts", NULL}, - {&total_us, "total_us", NULL}, -#ifdef DEBUG - {&past_skip, "past_skip", NULL}, -#endif - {NULL, "", NULL} - }; - -static int __init i7300_idle_init(void) -{ - raw_spin_lock_init(&i7300_idle_lock); - total_us = 0; - - if (i7300_idle_platform_probe(&fbd_dev, &ioat_dev, forceload)) - return -ENODEV; - - if (i7300_idle_thrt_save()) - return -ENODEV; - - if (i7300_idle_ioat_init()) - return -ENODEV; - - if (!zalloc_cpumask_var(&idle_cpumask, GFP_KERNEL)) - return -ENOMEM; - - debugfs_dir = debugfs_create_dir("i7300_idle", NULL); - if (debugfs_dir) { - int i = 0; - - while (debugfs_file_list[i].ptr != NULL) { - debugfs_file_list[i].file = debugfs_create_file( - debugfs_file_list[i].name, - S_IRUSR, - debugfs_dir, - debugfs_file_list[i].ptr, - &idle_fops); - i++; - } - } - - idle_notifier_register(&i7300_idle_nb); - - printk(KERN_INFO "i7300_idle: loaded v%s\n", I7300_IDLE_DRIVER_VERSION); - return 0; -} - -static void __exit i7300_idle_exit(void) -{ - idle_notifier_unregister(&i7300_idle_nb); - free_cpumask_var(idle_cpumask); - - if (debugfs_dir) { - int i = 0; - - while (debugfs_file_list[i].file != NULL) { - debugfs_remove(debugfs_file_list[i].file); - i++; - } - - debugfs_remove(debugfs_dir); - } - i7300_idle_thrt_restore(); - i7300_idle_ioat_exit(); -} - -module_init(i7300_idle_init); -module_exit(i7300_idle_exit); - -MODULE_AUTHOR("Andy Henroid "); -MODULE_DESCRIPTION("Intel Chipset DIMM Idle Power Saving Driver v" - I7300_IDLE_DRIVER_VERSION); -MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 8e7a7ee9ddd5d4275f1194ef2cc243ea86b0fb6f Mon Sep 17 00:00:00 2001 From: Len Brown Date: Fri, 18 Nov 2016 01:23:18 -0500 Subject: x86/idle: Remove idle_notifier Upon removal of the i7300_idle driver, the idle_notifer is unused. Signed-off-by: Len Brown Acked-by: Ingo Molnar Acked-by: Peter Zijlstra (Intel) Link: http://lkml.kernel.org/r/f15385a82ec4bf51f4f06777193d83f03b28cfdd.1479449716.git.len.brown@intel.com Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/idle.h | 7 ------- arch/x86/kernel/process.c | 15 --------------- 2 files changed, 22 deletions(-) diff --git a/arch/x86/include/asm/idle.h b/arch/x86/include/asm/idle.h index c5d1785373ed..02bab09707f2 100644 --- a/arch/x86/include/asm/idle.h +++ b/arch/x86/include/asm/idle.h @@ -1,13 +1,6 @@ #ifndef _ASM_X86_IDLE_H #define _ASM_X86_IDLE_H -#define IDLE_START 1 -#define IDLE_END 2 - -struct notifier_block; -void idle_notifier_register(struct notifier_block *n); -void idle_notifier_unregister(struct notifier_block *n); - #ifdef CONFIG_X86_64 void enter_idle(void); void exit_idle(void); diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 0888a879120f..f51950715145 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -67,19 +67,6 @@ EXPORT_PER_CPU_SYMBOL(cpu_tss); #ifdef CONFIG_X86_64 static DEFINE_PER_CPU(unsigned char, is_idle); -static ATOMIC_NOTIFIER_HEAD(idle_notifier); - -void idle_notifier_register(struct notifier_block *n) -{ - atomic_notifier_chain_register(&idle_notifier, n); -} -EXPORT_SYMBOL_GPL(idle_notifier_register); - -void idle_notifier_unregister(struct notifier_block *n) -{ - atomic_notifier_chain_unregister(&idle_notifier, n); -} -EXPORT_SYMBOL_GPL(idle_notifier_unregister); #endif /* @@ -255,14 +242,12 @@ static inline void play_dead(void) void enter_idle(void) { this_cpu_write(is_idle, 1); - atomic_notifier_call_chain(&idle_notifier, IDLE_START, NULL); } static void __exit_idle(void) { if (x86_test_and_clear_bit_percpu(0, is_idle) == 0) return; - atomic_notifier_call_chain(&idle_notifier, IDLE_END, NULL); } /* Called from interrupts to signify idle end */ -- cgit v1.2.3 From f08b5fe2d4eeb0a8a6e0e7e71928cf2c7b1b791d Mon Sep 17 00:00:00 2001 From: Len Brown Date: Fri, 18 Nov 2016 01:23:19 -0500 Subject: x86/idle: Remove is_idle flag Upon removal of the idle_notifier, all accesses to the "is_idle" flag serve no purpose. Signed-off-by: Len Brown Acked-by: Ingo Molnar Acked-by: Peter Zijlstra (Intel) Link: http://lkml.kernel.org/r/e4a24197cf9c227fcd1ca2df09999eaec9052f49.1479449716.git.len.brown@intel.com Signed-off-by: Thomas Gleixner --- arch/x86/kernel/process.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index f51950715145..d8e9d794e114 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -65,10 +65,6 @@ __visible DEFINE_PER_CPU_SHARED_ALIGNED(struct tss_struct, cpu_tss) = { }; EXPORT_PER_CPU_SYMBOL(cpu_tss); -#ifdef CONFIG_X86_64 -static DEFINE_PER_CPU(unsigned char, is_idle); -#endif - /* * this gets called so that we can store lazy state into memory and copy the * current task into the new thread. @@ -241,13 +237,10 @@ static inline void play_dead(void) #ifdef CONFIG_X86_64 void enter_idle(void) { - this_cpu_write(is_idle, 1); } static void __exit_idle(void) { - if (x86_test_and_clear_bit_percpu(0, is_idle) == 0) - return; } /* Called from interrupts to signify idle end */ -- cgit v1.2.3 From 9694be731dc81fec5ad59e863fa6538878ac496a Mon Sep 17 00:00:00 2001 From: Len Brown Date: Fri, 18 Nov 2016 01:23:20 -0500 Subject: x86: Remove x86_test_and_clear_bit_percpu() Upon removal of the "is_idle" flag, x86_test_and_clear_bit_percpu() is no longer used. Signed-off-by: Len Brown Acked-by: Ingo Molnar Acked-by: Peter Zijlstra (Intel) Link: http://lkml.kernel.org/r/b334ae6819507e3dfc0a4b33ed974714d067eb4a.1479449716.git.len.brown@intel.com Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/percpu.h | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h index 84f58de08c2b..9fa03604b2b3 100644 --- a/arch/x86/include/asm/percpu.h +++ b/arch/x86/include/asm/percpu.h @@ -507,17 +507,6 @@ do { \ #endif -/* This is not atomic against other CPUs -- CPU preemption needs to be off */ -#define x86_test_and_clear_bit_percpu(bit, var) \ -({ \ - bool old__; \ - asm volatile("btr %2,"__percpu_arg(1)"\n\t" \ - CC_SET(c) \ - : CC_OUT(c) (old__), "+m" (var) \ - : "dIr" (bit)); \ - old__; \ -}) - static __always_inline bool x86_this_cpu_constant_test_bit(unsigned int nr, const unsigned long __percpu *addr) { -- cgit v1.2.3 From 7a3e686e1bb57c34f73d3f19d620fe29035a6c99 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Fri, 18 Nov 2016 01:23:21 -0500 Subject: x86/idle: Remove enter_idle(), exit_idle() Upon removal of the is_idle flag, these routines became NOPs. Signed-off-by: Len Brown Acked-by: Ingo Molnar Acked-by: Peter Zijlstra (Intel) Link: http://lkml.kernel.org/r/822f2c22cc5890f7b8ea0eeec60277eb44505b4e.1479449716.git.len.brown@intel.com Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/apic.h | 1 - arch/x86/include/asm/idle.h | 9 --------- arch/x86/kernel/kvm.c | 2 -- arch/x86/kernel/process.c | 25 ------------------------- drivers/xen/events/events_base.c | 1 - 5 files changed, 38 deletions(-) diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index f5aaf6c83222..5731274bfdba 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -639,7 +639,6 @@ extern void irq_exit(void); static inline void entering_irq(void) { irq_enter(); - exit_idle(); } static inline void entering_ack_irq(void) diff --git a/arch/x86/include/asm/idle.h b/arch/x86/include/asm/idle.h index 02bab09707f2..dcebb1c634f1 100644 --- a/arch/x86/include/asm/idle.h +++ b/arch/x86/include/asm/idle.h @@ -1,15 +1,6 @@ #ifndef _ASM_X86_IDLE_H #define _ASM_X86_IDLE_H -#ifdef CONFIG_X86_64 -void enter_idle(void); -void exit_idle(void); -#else /* !CONFIG_X86_64 */ -static inline void enter_idle(void) { } -static inline void exit_idle(void) { } -static inline void __exit_idle(void) { } -#endif /* CONFIG_X86_64 */ - void amd_e400_remove_cpu(int cpu); #endif /* _ASM_X86_IDLE_H */ diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index edbbfc854e39..093f550f372d 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c @@ -267,13 +267,11 @@ do_async_page_fault(struct pt_regs *regs, unsigned long error_code) case KVM_PV_REASON_PAGE_NOT_PRESENT: /* page is swapped out by the host. */ prev_state = exception_enter(); - exit_idle(); kvm_async_pf_task_wait((u32)read_cr2()); exception_exit(prev_state); break; case KVM_PV_REASON_PAGE_READY: rcu_irq_enter(); - exit_idle(); kvm_async_pf_task_wake((u32)read_cr2()); rcu_irq_exit(); break; diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index d8e9d794e114..ee023919e476 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -234,34 +234,9 @@ static inline void play_dead(void) } #endif -#ifdef CONFIG_X86_64 -void enter_idle(void) -{ -} - -static void __exit_idle(void) -{ -} - -/* Called from interrupts to signify idle end */ -void exit_idle(void) -{ - /* idle loop has pid 0 */ - if (current->pid) - return; - __exit_idle(); -} -#endif - void arch_cpu_idle_enter(void) { local_touch_nmi(); - enter_idle(); -} - -void arch_cpu_idle_exit(void) -{ - __exit_idle(); } void arch_cpu_idle_dead(void) diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c index 9ecfcdcdd6d6..9ad622ab05dc 100644 --- a/drivers/xen/events/events_base.c +++ b/drivers/xen/events/events_base.c @@ -1256,7 +1256,6 @@ void xen_evtchn_do_upcall(struct pt_regs *regs) irq_enter(); #ifdef CONFIG_X86 - exit_idle(); inc_irq_stat(irq_hv_callback_count); #endif -- cgit v1.2.3 From a588b9836447ac683a8f63949ad55265813826f5 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Fri, 9 Dec 2016 19:29:08 +0100 Subject: x86/cpufeature: Provide helper to set bugs bits Will be used in a later patch to set bug bits for bugs which need late detection. Signed-off-by: Borislav Petkov Cc: Jiri Olsa Link: http://lkml.kernel.org/r/20161209182912.2726-2-bp@alien8.de Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/cpufeature.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 1d2b69fc0ceb..d59c15c3defd 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -204,6 +204,7 @@ static __always_inline __pure bool _static_cpu_has(u16 bit) #define static_cpu_has_bug(bit) static_cpu_has((bit)) #define boot_cpu_has_bug(bit) cpu_has_bug(&boot_cpu_data, (bit)) +#define boot_cpu_set_bug(bit) set_cpu_cap(&boot_cpu_data, (bit)) #define MAX_CPU_FEATURES (NCAPINTS * 32) #define cpu_have_feature boot_cpu_has -- cgit v1.2.3 From 3344ed30791af66dbbad5f375008f3d1863b6c99 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 9 Dec 2016 19:29:09 +0100 Subject: x86/bugs: Separate AMD E400 erratum and C1E bug The workaround for the AMD Erratum E400 (Local APIC timer stops in C1E state) is a two step process: - Selection of the E400 aware idle routine - Detection whether the platform is affected The idle routine selection happens for possibly affected CPUs depending on family/model/stepping information. These range of CPUs is not necessarily affected as the decision whether to enable the C1E feature is made by the firmware. Unfortunately there is no way to query this at early boot. The current implementation polls a MSR in the E400 aware idle routine to detect whether the CPU is affected. This is inefficient on non affected CPUs because every idle entry has to do the MSR read. There is a better way to detect this before going idle for the first time which requires to seperate the bug flags: X86_BUG_AMD_E400 - Selects the E400 aware idle routine and enables the detection X86_BUG_AMD_APIC_C1E - Set when the platform is affected by E400 Replace the current X86_BUG_AMD_APIC_C1E usage by the new X86_BUG_AMD_E400 bug bit to select the idle routine which currently does an unconditional detection poll. X86_BUG_AMD_APIC_C1E is going to be used in later patches to remove the MSR polling and simplify the handling of this misfeature. Signed-off-by: Thomas Gleixner Signed-off-by: Borislav Petkov Cc: Jiri Olsa Link: http://lkml.kernel.org/r/20161209182912.2726-3-bp@alien8.de Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/cpufeatures.h | 2 ++ arch/x86/kernel/cpu/amd.c | 20 +++++++++++++------- arch/x86/kernel/process.c | 3 +-- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h index a39629206864..ed10b5bf9b93 100644 --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h @@ -311,4 +311,6 @@ #define X86_BUG_NULL_SEG X86_BUG(10) /* Nulling a selector preserves the base */ #define X86_BUG_SWAPGS_FENCE X86_BUG(11) /* SWAPGS without input dep on GS */ #define X86_BUG_MONITOR X86_BUG(12) /* IPI required to wake up remote CPU */ +#define X86_BUG_AMD_E400 X86_BUG(13) /* CPU is among the affected by Erratum 400 */ + #endif /* _ASM_X86_CPUFEATURES_H */ diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index b81fe2d63e15..ae26c282f5d3 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -20,6 +20,10 @@ #include "cpu.h" +static const int amd_erratum_383[]; +static const int amd_erratum_400[]; +static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum); + /* * nodes_per_socket: Stores the number of nodes per socket. * Refer to Fam15h Models 00-0fh BKDG - CPUID Fn8000_001E_ECX @@ -589,11 +593,16 @@ static void early_init_amd(struct cpuinfo_x86 *c) /* F16h erratum 793, CVE-2013-6885 */ if (c->x86 == 0x16 && c->x86_model <= 0xf) msr_set_bit(MSR_AMD64_LS_CFG, 15); -} -static const int amd_erratum_383[]; -static const int amd_erratum_400[]; -static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum); + /* + * Check whether the machine is affected by erratum 400. This is + * used to select the proper idle routine and to enable the check + * whether the machine is affected in arch_post_acpi_init(), which + * sets the X86_BUG_AMD_APIC_C1E bug depending on the MSR check. + */ + if (cpu_has_amd_erratum(c, amd_erratum_400)) + set_cpu_bug(c, X86_BUG_AMD_E400); +} static void init_amd_k8(struct cpuinfo_x86 *c) { @@ -774,9 +783,6 @@ static void init_amd(struct cpuinfo_x86 *c) if (c->x86 > 0x11) set_cpu_cap(c, X86_FEATURE_ARAT); - if (cpu_has_amd_erratum(c, amd_erratum_400)) - set_cpu_bug(c, X86_BUG_AMD_APIC_C1E); - rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy); /* 3DNow or LM implies PREFETCHW */ diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index ee023919e476..29bbbce4f2fd 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -401,8 +401,7 @@ void select_idle_routine(const struct cpuinfo_x86 *c) if (x86_idle || boot_option_idle_override == IDLE_POLL) return; - if (cpu_has_bug(c, X86_BUG_AMD_APIC_C1E)) { - /* E400: APIC timer interrupt does not wake up CPU from C1e */ + if (boot_cpu_has_bug(X86_BUG_AMD_E400)) { pr_info("using AMD E400 aware idle routine\n"); x86_idle = amd_e400_idle; } else if (prefer_mwait_c1_over_halt(c)) { -- cgit v1.2.3 From e7ff3a47630d9512d0bcbdfa73660021087ba445 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 9 Dec 2016 19:29:10 +0100 Subject: x86/amd: Check for the C1E bug post ACPI subsystem init AMD CPUs affected by the E400 erratum suffer from the issue that the local APIC timer stops when the CPU goes into C1E. Unfortunately there is no way to detect the affected CPUs on early boot. It's only possible to determine the range of possibly affected CPUs from the family/model range. The actual decision whether to enter C1E and thus cause the bug is done by the firmware and we need to detect that case late, after ACPI has been initialized. The current solution is to check in the idle routine whether the CPU is affected by reading the MSR_K8_INT_PENDING_MSG MSR and checking for the K8_INTP_C1E_ACTIVE_MASK bits. If one of the bits is set then the CPU is affected and the system is switched into forced broadcast mode. This is ineffective and on non-affected CPUs every entry to idle does the extra RDMSR. After doing some research it turns out that the bits are visible on the boot CPU right after the ACPI subsystem is initialized in the early boot process. So instead of polling for the bits in the idle loop, add a detection function after acpi_subsystem_init() and check for the MSR bits. If set, then the X86_BUG_AMD_APIC_C1E is set on the boot CPU and the TSC is marked unstable when X86_FEATURE_NONSTOP_TSC is not set as it will stop in C1E state as well. The switch to broadcast mode cannot be done at this point because the boot CPU still uses HPET as a clockevent device and the local APIC timer is not yet calibrated and installed. The switch to broadcast mode on the affected CPUs needs to be done when the local APIC timer is actually set up. This allows to cleanup the amd_e400_idle() function in the next step. Signed-off-by: Thomas Gleixner Signed-off-by: Borislav Petkov Cc: Jiri Olsa Link: http://lkml.kernel.org/r/20161209182912.2726-4-bp@alien8.de Signed-off-by: Thomas Gleixner --- arch/x86/kernel/process.c | 23 +++++++++++++++++++++++ init/main.c | 3 +++ 2 files changed, 26 insertions(+) diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 29bbbce4f2fd..ced76f13d20d 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -418,6 +418,29 @@ void __init init_amd_e400_c1e_mask(void) zalloc_cpumask_var(&amd_e400_c1e_mask, GFP_KERNEL); } +void __init arch_post_acpi_subsys_init(void) +{ + u32 lo, hi; + + if (!boot_cpu_has_bug(X86_BUG_AMD_E400)) + return; + + /* + * AMD E400 detection needs to happen after ACPI has been enabled. If + * the machine is affected K8_INTP_C1E_ACTIVE_MASK bits are set in + * MSR_K8_INT_PENDING_MSG. + */ + rdmsr(MSR_K8_INT_PENDING_MSG, lo, hi); + if (!(lo & K8_INTP_C1E_ACTIVE_MASK)) + return; + + boot_cpu_set_bug(X86_BUG_AMD_APIC_C1E); + + if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) + mark_tsc_unstable("TSC halt in AMD C1E"); + pr_info("System has AMD C1E enabled\n"); +} + static int __init idle_setup(char *str) { if (!str) diff --git a/init/main.c b/init/main.c index 2858be732f6d..1d7038c1ee19 100644 --- a/init/main.c +++ b/init/main.c @@ -448,6 +448,8 @@ void __init parse_early_param(void) done = 1; } +void __init __weak arch_post_acpi_subsys_init(void) { } + void __init __weak smp_setup_processor_id(void) { } @@ -649,6 +651,7 @@ asmlinkage __visible void __init start_kernel(void) check_bugs(); acpi_subsystem_init(); + arch_post_acpi_subsys_init(); sfi_init_late(); if (efi_enabled(EFI_RUNTIME_SERVICES)) { -- cgit v1.2.3 From 07c94a38125376d70d156bd8bff98ddfe4c8ea95 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Fri, 9 Dec 2016 19:29:11 +0100 Subject: x86/amd: Simplify AMD E400 aware idle routine Reorganize the E400 detection now that we have everything in place: switch the CPUs to broadcast mode after the LAPIC has been initialized and remove the facilities that were used previously on the idle path. Unfortunately static_cpu_has_bug() cannpt be used in the E400 idle routine because alternatives have been applied when the actual detection happens, so the static switching does not take effect and the test will stay false. Use boot_cpu_has_bug() instead which is definitely an improvement over the RDMSR and the cpumask handling. Suggested-by: Thomas Gleixner Signed-off-by: Borislav Petkov Cc: Jiri Olsa Link: http://lkml.kernel.org/r/20161209182912.2726-5-bp@alien8.de Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/acpi.h | 2 +- arch/x86/include/asm/processor.h | 3 +- arch/x86/kernel/apic/apic.c | 2 ++ arch/x86/kernel/cpu/common.c | 1 - arch/x86/kernel/process.c | 75 ++++++++++++++-------------------------- arch/x86/kernel/smpboot.c | 1 - drivers/acpi/processor_idle.c | 2 +- 7 files changed, 31 insertions(+), 55 deletions(-) diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h index 5391b0ae7cc3..395b69551fce 100644 --- a/arch/x86/include/asm/acpi.h +++ b/arch/x86/include/asm/acpi.h @@ -94,7 +94,7 @@ static inline unsigned int acpi_processor_cstate_check(unsigned int max_cstate) boot_cpu_data.x86_model <= 0x05 && boot_cpu_data.x86_mask < 0x0A) return 1; - else if (amd_e400_c1e_detected) + else if (boot_cpu_has(X86_BUG_AMD_APIC_C1E)) return 1; else return max_cstate; diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 984a7bf17f6a..fa609c6f6ba9 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -621,10 +621,9 @@ static inline void sync_core(void) } extern void select_idle_routine(const struct cpuinfo_x86 *c); -extern void init_amd_e400_c1e_mask(void); +extern void amd_e400_c1e_apic_setup(void); extern unsigned long boot_option_idle_override; -extern bool amd_e400_c1e_detected; enum idle_boot_override {IDLE_NO_OVERRIDE=0, IDLE_HALT, IDLE_NOMWAIT, IDLE_POLL}; diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 88c657b057e2..cc89ce200183 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -894,11 +894,13 @@ void __init setup_boot_APIC_clock(void) /* Setup the lapic or request the broadcast */ setup_APIC_timer(); + amd_e400_c1e_apic_setup(); } void setup_secondary_APIC_clock(void) { setup_APIC_timer(); + amd_e400_c1e_apic_setup(); } /* diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 9bd910a7dd0a..e1f98ff9a3f0 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -1144,7 +1144,6 @@ void enable_sep_cpu(void) void __init identify_boot_cpu(void) { identify_cpu(&boot_cpu_data); - init_amd_e400_c1e_mask(); #ifdef CONFIG_X86_32 sysenter_setup(); enable_sep_cpu(); diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index ced76f13d20d..2c2b55ab41e7 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -289,59 +289,33 @@ void stop_this_cpu(void *dummy) halt(); } -bool amd_e400_c1e_detected; -EXPORT_SYMBOL(amd_e400_c1e_detected); - -static cpumask_var_t amd_e400_c1e_mask; - -void amd_e400_remove_cpu(int cpu) -{ - if (amd_e400_c1e_mask != NULL) - cpumask_clear_cpu(cpu, amd_e400_c1e_mask); -} - /* - * AMD Erratum 400 aware idle routine. We check for C1E active in the interrupt - * pending message MSR. If we detect C1E, then we handle it the same - * way as C3 power states (local apic timer and TSC stop) + * AMD Erratum 400 aware idle routine. We handle it the same way as C3 power + * states (local apic timer and TSC stop). */ static void amd_e400_idle(void) { - if (!amd_e400_c1e_detected) { - u32 lo, hi; - - rdmsr(MSR_K8_INT_PENDING_MSG, lo, hi); - - if (lo & K8_INTP_C1E_ACTIVE_MASK) { - amd_e400_c1e_detected = true; - if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) - mark_tsc_unstable("TSC halt in AMD C1E"); - pr_info("System has AMD C1E enabled\n"); - } + /* + * We cannot use static_cpu_has_bug() here because X86_BUG_AMD_APIC_C1E + * gets set after static_cpu_has() places have been converted via + * alternatives. + */ + if (!boot_cpu_has_bug(X86_BUG_AMD_APIC_C1E)) { + default_idle(); + return; } - if (amd_e400_c1e_detected) { - int cpu = smp_processor_id(); + tick_broadcast_enter(); - if (!cpumask_test_cpu(cpu, amd_e400_c1e_mask)) { - cpumask_set_cpu(cpu, amd_e400_c1e_mask); - /* Force broadcast so ACPI can not interfere. */ - tick_broadcast_force(); - pr_info("Switch to broadcast mode on CPU%d\n", cpu); - } - tick_broadcast_enter(); + default_idle(); - default_idle(); - - /* - * The switch back from broadcast mode needs to be - * called with interrupts disabled. - */ - local_irq_disable(); - tick_broadcast_exit(); - local_irq_enable(); - } else - default_idle(); + /* + * The switch back from broadcast mode needs to be called with + * interrupts disabled. + */ + local_irq_disable(); + tick_broadcast_exit(); + local_irq_enable(); } /* @@ -411,11 +385,14 @@ void select_idle_routine(const struct cpuinfo_x86 *c) x86_idle = default_idle; } -void __init init_amd_e400_c1e_mask(void) +void amd_e400_c1e_apic_setup(void) { - /* If we're using amd_e400_idle, we need to allocate amd_e400_c1e_mask. */ - if (x86_idle == amd_e400_idle) - zalloc_cpumask_var(&amd_e400_c1e_mask, GFP_KERNEL); + if (boot_cpu_has_bug(X86_BUG_AMD_APIC_C1E)) { + pr_info("Switch to broadcast mode on CPU%d\n", smp_processor_id()); + local_irq_disable(); + tick_broadcast_force(); + local_irq_enable(); + } } void __init arch_post_acpi_subsys_init(void) diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 42f5eb7b4f6c..0229ccbfcd66 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1575,7 +1575,6 @@ void play_dead_common(void) { idle_task_exit(); reset_lazy_tlbstate(); - amd_e400_remove_cpu(raw_smp_processor_id()); /* Ack it */ (void)cpu_report_death(); diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 2237d3f24f0e..5c8aa9cf62d7 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -141,7 +141,7 @@ static void lapic_timer_check_state(int state, struct acpi_processor *pr, if (cpu_has(&cpu_data(pr->id), X86_FEATURE_ARAT)) return; - if (amd_e400_c1e_detected) + if (boot_cpu_has_bug(X86_BUG_AMD_APIC_C1E)) type = ACPI_STATE_C1; /* -- cgit v1.2.3 From 34bc3560c657d3d4fb17367ed9bfda803166dce0 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 9 Dec 2016 19:29:12 +0100 Subject: x86: Remove empty idle.h header One include less is always a good thing(tm). Good riddance. Signed-off-by: Thomas Gleixner Signed-off-by: Borislav Petkov Cc: Jiri Olsa Link: http://lkml.kernel.org/r/20161209182912.2726-6-bp@alien8.de Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/apic.h | 1 - arch/x86/include/asm/idle.h | 6 ------ arch/x86/kernel/apic/apic.c | 1 - arch/x86/kernel/apic/io_apic.c | 1 - arch/x86/kernel/cpu/mcheck/mce_amd.c | 1 - arch/x86/kernel/cpu/mcheck/therm_throt.c | 1 - arch/x86/kernel/cpu/mcheck/threshold.c | 1 - arch/x86/kernel/cpu/mshyperv.c | 1 - arch/x86/kernel/irq.c | 1 - arch/x86/kernel/irq_64.c | 1 - arch/x86/kernel/kvm.c | 1 - arch/x86/kernel/process.c | 1 - arch/x86/kernel/process_32.c | 1 - arch/x86/kernel/process_64.c | 1 - arch/x86/kernel/smpboot.c | 1 - arch/x86/platform/uv/tlb_uv.c | 1 - drivers/thermal/intel_powerclamp.c | 1 - drivers/xen/events/events_base.c | 1 - 18 files changed, 23 deletions(-) delete mode 100644 arch/x86/include/asm/idle.h diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index 5731274bfdba..30a5642eb405 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -11,7 +11,6 @@ #include #include #include -#include #define ARCH_APICTIMER_STOPS_ON_C3 1 diff --git a/arch/x86/include/asm/idle.h b/arch/x86/include/asm/idle.h deleted file mode 100644 index dcebb1c634f1..000000000000 --- a/arch/x86/include/asm/idle.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_X86_IDLE_H -#define _ASM_X86_IDLE_H - -void amd_e400_remove_cpu(int cpu); - -#endif /* _ASM_X86_IDLE_H */ diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index cc89ce200183..2ab0ff0f1dbe 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -48,7 +48,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 48e6d84f173e..945e512a112a 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -48,7 +48,6 @@ #include #include -#include #include #include #include diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index 9b5403462936..832f634fdf47 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c @@ -24,7 +24,6 @@ #include #include -#include #include #include #include diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c index 6b9dc4d18ccc..2f5c3418b18b 100644 --- a/arch/x86/kernel/cpu/mcheck/therm_throt.c +++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c @@ -26,7 +26,6 @@ #include #include -#include #include #include #include diff --git a/arch/x86/kernel/cpu/mcheck/threshold.c b/arch/x86/kernel/cpu/mcheck/threshold.c index fcf9ae9384f4..9beb092d68a5 100644 --- a/arch/x86/kernel/cpu/mcheck/threshold.c +++ b/arch/x86/kernel/cpu/mcheck/threshold.c @@ -6,7 +6,6 @@ #include #include -#include #include #include diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index 8f44c5a50ab8..6c044543545e 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index 9f669fdd2010..7c6e9ffe4424 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c index 9ebd0b0e73d9..6b0678a541e2 100644 --- a/arch/x86/kernel/irq_64.c +++ b/arch/x86/kernel/irq_64.c @@ -16,7 +16,6 @@ #include #include #include -#include #include int sysctl_panic_on_stackoverflow; diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index 093f550f372d..05fe50e5f42c 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c @@ -42,7 +42,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 2c2b55ab41e7..43c36d8a6ae2 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index bd7be8efdc4c..3e4ff92597ff 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -49,7 +49,6 @@ #include #include -#include #include #include #include diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index b3760b3c1ca0..bb1517106ec1 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -44,7 +44,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 0229ccbfcd66..352ddd560d19 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -58,7 +58,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c index 9e42842e924a..766d4d3529a1 100644 --- a/arch/x86/platform/uv/tlb_uv.c +++ b/arch/x86/platform/uv/tlb_uv.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/thermal/intel_powerclamp.c b/drivers/thermal/intel_powerclamp.c index 7a223074df3d..bfc5a142667b 100644 --- a/drivers/thermal/intel_powerclamp.c +++ b/drivers/thermal/intel_powerclamp.c @@ -56,7 +56,6 @@ #include #include #include -#include #include #define MAX_TARGET_RATIO (50U) diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c index 9ad622ab05dc..adc19ce3cc66 100644 --- a/drivers/xen/events/events_base.c +++ b/drivers/xen/events/events_base.c @@ -37,7 +37,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3