Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
Pull main powerpc updates from Ben Herrenschmidt: "This time around, the powerpc merges are going to be a little bit more complicated than usual. This is the main pull request with most of the work for this merge window. I will describe it a bit more further down. There is some additional cpuidle driver work, however I haven't included it in this tree as it depends on some work in tip/timer-core which Thomas accidentally forgot to put in a topic branch. Since I didn't want to carry all of that tip timer stuff in powerpc -next, I setup a separate branch on top of Thomas tree with just that cpuidle driver in it, and Stephen has been carrying that in next separately for a while now. I'll send a separate pull request for it. Additionally, two new pieces in this tree add users for a sysfs API that Tejun and Greg have been deprecating in drivers-core-next. Thankfully Greg reverted the patch that removes the old API so this merge can happen cleanly, but once merged, I will send a patch adjusting our new code to the new API so that Greg can send you the removal patch. Now as for the content of this branch, we have a lot of perf work for power8 new counters including support for our new "nest" counters (also called 24x7) under pHyp (not natively yet). We have new functionality when running under the OPAL firmware (non-virtualized or KVM host), such as access to the firmware error logs and service processor dumps, system parameters and sensors, along with a hwmon driver for the latter. There's also a bunch of bug fixes accross the board, some LE fixes, and a nice set of selftests for validating our various types of copy loops. On the Freescale side, we see mostly new chip/board revisions, some clock updates, better support for machine checks and debug exceptions, etc..." * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (70 commits) powerpc/book3s: Fix CFAR clobbering issue in machine check handler. powerpc/compat: 32-bit little endian machine name is ppcle, not ppc powerpc/le: Big endian arguments for ppc_rtas() powerpc: Use default set of netfilter modules (CONFIG_NETFILTER_ADVANCED=n) powerpc/defconfigs: Enable THP in pseries defconfig powerpc/mm: Make sure a local_irq_disable prevent a parallel THP split powerpc: Rate-limit users spamming kernel log buffer powerpc/perf: Fix handling of L3 events with bank == 1 powerpc/perf/hv_{gpci, 24x7}: Add documentation of device attributes powerpc/perf: Add kconfig option for hypervisor provided counters powerpc/perf: Add support for the hv 24x7 interface powerpc/perf: Add support for the hv gpci (get performance counter info) interface powerpc/perf: Add macros for defining event fields & formats powerpc/perf: Add a shared interface to get gpci version and capabilities powerpc/perf: Add 24x7 interface headers powerpc/perf: Add hv_gpci interface header powerpc: Add hvcalls for 24x7 and gpci (Get Performance Counter Info) sysfs: create bin_attributes under the requested group powerpc/perf: Enable BHRB access for EBB events powerpc/perf: Add BHRB constraint and IFM MMCRA handling for EBB ...
This commit is contained in:
@@ -111,6 +111,18 @@ config CMM
|
||||
will be reused for other LPARs. The interface allows firmware to
|
||||
balance memory across many LPARs.
|
||||
|
||||
config HV_PERF_CTRS
|
||||
bool "Hypervisor supplied PMU events (24x7 & GPCI)"
|
||||
default y
|
||||
depends on PERF_EVENTS && PPC_PSERIES
|
||||
help
|
||||
Enable access to hypervisor supplied counters in perf. Currently,
|
||||
this enables code that uses the hcall GetPerfCounterInfo and 24x7
|
||||
interfaces to retrieve counters. GPCI exists on Power 6 and later
|
||||
systems. 24x7 is available on Power 8 systems.
|
||||
|
||||
If unsure, select Y.
|
||||
|
||||
config DTL
|
||||
bool "Dispatch Trace Log"
|
||||
depends on PPC_SPLPAR && DEBUG_FS
|
||||
|
@@ -420,4 +420,4 @@ static int __init pseries_cpu_hotplug_init(void)
|
||||
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(pseries_cpu_hotplug_init);
|
||||
machine_arch_initcall(pseries, pseries_cpu_hotplug_init);
|
||||
|
@@ -14,6 +14,7 @@
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/memory.h>
|
||||
#include <linux/memory_hotplug.h>
|
||||
|
||||
#include <asm/firmware.h>
|
||||
#include <asm/machdep.h>
|
||||
@@ -75,50 +76,13 @@ unsigned long memory_block_size_bytes(void)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MEMORY_HOTREMOVE
|
||||
static int pseries_remove_memblock(unsigned long base, unsigned int memblock_size)
|
||||
static int pseries_remove_memory(u64 start, u64 size)
|
||||
{
|
||||
unsigned long start, start_pfn;
|
||||
struct zone *zone;
|
||||
int ret;
|
||||
unsigned long section;
|
||||
unsigned long sections_to_remove;
|
||||
|
||||
start_pfn = base >> PAGE_SHIFT;
|
||||
|
||||
if (!pfn_valid(start_pfn)) {
|
||||
memblock_remove(base, memblock_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
zone = page_zone(pfn_to_page(start_pfn));
|
||||
|
||||
/*
|
||||
* Remove section mappings and sysfs entries for the
|
||||
* section of the memory we are removing.
|
||||
*
|
||||
* NOTE: Ideally, this should be done in generic code like
|
||||
* remove_memory(). But remove_memory() gets called by writing
|
||||
* to sysfs "state" file and we can't remove sysfs entries
|
||||
* while writing to it. So we have to defer it to here.
|
||||
*/
|
||||
sections_to_remove = (memblock_size >> PAGE_SHIFT) / PAGES_PER_SECTION;
|
||||
for (section = 0; section < sections_to_remove; section++) {
|
||||
unsigned long pfn = start_pfn + section * PAGES_PER_SECTION;
|
||||
ret = __remove_pages(zone, pfn, PAGES_PER_SECTION);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update memory regions for memory remove
|
||||
*/
|
||||
memblock_remove(base, memblock_size);
|
||||
|
||||
/*
|
||||
* Remove htab bolted mappings for this section of memory
|
||||
*/
|
||||
start = (unsigned long)__va(base);
|
||||
ret = remove_section_mapping(start, start + memblock_size);
|
||||
/* Remove htab bolted mappings for this section of memory */
|
||||
start = (unsigned long)__va(start);
|
||||
ret = remove_section_mapping(start, start + size);
|
||||
|
||||
/* Ensure all vmalloc mappings are flushed in case they also
|
||||
* hit that section of memory
|
||||
@@ -128,7 +92,34 @@ static int pseries_remove_memblock(unsigned long base, unsigned int memblock_siz
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pseries_remove_memory(struct device_node *np)
|
||||
static int pseries_remove_memblock(unsigned long base, unsigned int memblock_size)
|
||||
{
|
||||
unsigned long block_sz, start_pfn;
|
||||
int sections_per_block;
|
||||
int i, nid;
|
||||
|
||||
start_pfn = base >> PAGE_SHIFT;
|
||||
|
||||
if (!pfn_valid(start_pfn)) {
|
||||
memblock_remove(base, memblock_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
block_sz = memory_block_size_bytes();
|
||||
sections_per_block = block_sz / MIN_MEMORY_BLOCK_SIZE;
|
||||
nid = memory_add_physaddr_to_nid(base);
|
||||
|
||||
for (i = 0; i < sections_per_block; i++) {
|
||||
remove_memory(nid, base, MIN_MEMORY_BLOCK_SIZE);
|
||||
base += MIN_MEMORY_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
/* Update memory regions for memory remove */
|
||||
memblock_remove(base, memblock_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pseries_remove_mem_node(struct device_node *np)
|
||||
{
|
||||
const char *type;
|
||||
const unsigned int *regs;
|
||||
@@ -153,8 +144,8 @@ static int pseries_remove_memory(struct device_node *np)
|
||||
base = *(unsigned long *)regs;
|
||||
lmb_size = regs[3];
|
||||
|
||||
ret = pseries_remove_memblock(base, lmb_size);
|
||||
return ret;
|
||||
pseries_remove_memblock(base, lmb_size);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static inline int pseries_remove_memblock(unsigned long base,
|
||||
@@ -162,13 +153,13 @@ static inline int pseries_remove_memblock(unsigned long base,
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
static inline int pseries_remove_memory(struct device_node *np)
|
||||
static inline int pseries_remove_mem_node(struct device_node *np)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
#endif /* CONFIG_MEMORY_HOTREMOVE */
|
||||
|
||||
static int pseries_add_memory(struct device_node *np)
|
||||
static int pseries_add_mem_node(struct device_node *np)
|
||||
{
|
||||
const char *type;
|
||||
const unsigned int *regs;
|
||||
@@ -254,10 +245,10 @@ static int pseries_memory_notifier(struct notifier_block *nb,
|
||||
|
||||
switch (action) {
|
||||
case OF_RECONFIG_ATTACH_NODE:
|
||||
err = pseries_add_memory(node);
|
||||
err = pseries_add_mem_node(node);
|
||||
break;
|
||||
case OF_RECONFIG_DETACH_NODE:
|
||||
err = pseries_remove_memory(node);
|
||||
err = pseries_remove_mem_node(node);
|
||||
break;
|
||||
case OF_RECONFIG_UPDATE_PROPERTY:
|
||||
pr = (struct of_prop_reconfig *)node;
|
||||
@@ -277,6 +268,10 @@ static int __init pseries_memory_hotplug_init(void)
|
||||
if (firmware_has_feature(FW_FEATURE_LPAR))
|
||||
of_reconfig_notifier_register(&pseries_mem_nb);
|
||||
|
||||
#ifdef CONFIG_MEMORY_HOTREMOVE
|
||||
ppc_md.remove_memory = pseries_remove_memory;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
machine_device_initcall(pseries, pseries_memory_hotplug_init);
|
||||
|
@@ -290,13 +290,6 @@ void post_mobility_fixup(void)
|
||||
int rc;
|
||||
int activate_fw_token;
|
||||
|
||||
rc = pseries_devicetree_update(MIGRATION_SCOPE);
|
||||
if (rc) {
|
||||
printk(KERN_ERR "Initial post-mobility device tree update "
|
||||
"failed: %d\n", rc);
|
||||
return;
|
||||
}
|
||||
|
||||
activate_fw_token = rtas_token("ibm,activate-firmware");
|
||||
if (activate_fw_token == RTAS_UNKNOWN_SERVICE) {
|
||||
printk(KERN_ERR "Could not make post-mobility "
|
||||
@@ -304,16 +297,17 @@ void post_mobility_fixup(void)
|
||||
return;
|
||||
}
|
||||
|
||||
rc = rtas_call(activate_fw_token, 0, 1, NULL);
|
||||
if (!rc) {
|
||||
rc = pseries_devicetree_update(MIGRATION_SCOPE);
|
||||
if (rc)
|
||||
printk(KERN_ERR "Secondary post-mobility device tree "
|
||||
"update failed: %d\n", rc);
|
||||
} else {
|
||||
do {
|
||||
rc = rtas_call(activate_fw_token, 0, 1, NULL);
|
||||
} while (rtas_busy_delay(rc));
|
||||
|
||||
if (rc)
|
||||
printk(KERN_ERR "Post-mobility activate-fw failed: %d\n", rc);
|
||||
return;
|
||||
}
|
||||
|
||||
rc = pseries_devicetree_update(MIGRATION_SCOPE);
|
||||
if (rc)
|
||||
printk(KERN_ERR "Post-mobility device tree update "
|
||||
"failed: %d\n", rc);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@@ -26,6 +26,7 @@
|
||||
#include <asm/mmu.h>
|
||||
#include <asm/rtas.h>
|
||||
#include <asm/topology.h>
|
||||
#include "../../kernel/cacheinfo.h"
|
||||
|
||||
static u64 stream_id;
|
||||
static struct device suspend_dev;
|
||||
@@ -78,6 +79,23 @@ static int pseries_suspend_cpu(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* pseries_suspend_enable_irqs
|
||||
*
|
||||
* Post suspend configuration updates
|
||||
*
|
||||
**/
|
||||
static void pseries_suspend_enable_irqs(void)
|
||||
{
|
||||
/*
|
||||
* Update configuration which can be modified based on device tree
|
||||
* changes during resume.
|
||||
*/
|
||||
cacheinfo_cpu_offline(smp_processor_id());
|
||||
post_mobility_fixup();
|
||||
cacheinfo_cpu_online(smp_processor_id());
|
||||
}
|
||||
|
||||
/**
|
||||
* pseries_suspend_enter - Final phase of hibernation
|
||||
*
|
||||
@@ -174,7 +192,30 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(hibernate, S_IWUSR, NULL, store_hibernate);
|
||||
#define USER_DT_UPDATE 0
|
||||
#define KERN_DT_UPDATE 1
|
||||
|
||||
/**
|
||||
* show_hibernate - Report device tree update responsibilty
|
||||
* @dev: subsys root device
|
||||
* @attr: device attribute struct
|
||||
* @buf: buffer
|
||||
*
|
||||
* Report whether a device tree update is performed by the kernel after a
|
||||
* resume, or if drmgr must coordinate the update from user space.
|
||||
*
|
||||
* Return value:
|
||||
* 0 if drmgr is to initiate update, and 1 otherwise
|
||||
**/
|
||||
static ssize_t show_hibernate(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return sprintf(buf, "%d\n", KERN_DT_UPDATE);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(hibernate, S_IWUSR | S_IRUGO,
|
||||
show_hibernate, store_hibernate);
|
||||
|
||||
static struct bus_type suspend_subsys = {
|
||||
.name = "power",
|
||||
@@ -235,6 +276,7 @@ static int __init pseries_suspend_init(void)
|
||||
return rc;
|
||||
|
||||
ppc_md.suspend_disable_cpu = pseries_suspend_cpu;
|
||||
ppc_md.suspend_enable_irqs = pseries_suspend_enable_irqs;
|
||||
suspend_set_ops(&pseries_suspend_ops);
|
||||
return 0;
|
||||
}
|
||||
|
Fai riferimento in un nuovo problema
Block a user