diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-09 08:35:31 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-09 08:35:31 -0700 |
commit | 042f7b7cbd1e531278a09c449563165ba1f07673 (patch) | |
tree | 40eba4972e77931c5e4b890d57964642f006062c /arch/powerpc/platforms/powernv/opal.c | |
parent | 69cd9eba38867a493a043bb13eb9b33cad5f1a9a (diff) | |
parent | cc4f265ad9a37bdb1846c45eebe454c382f31d67 (diff) |
Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
Pull more powerpc updates from Ben Herrenschmidt:
"Here are a few more powerpc things for you.
So you'll find here the conversion of the two new firmware sysfs
interfaces to the new API for self-removing files that Greg and Tejun
introduced, so they can finally remove the old one.
I'm also reverting the hwmon driver for powernv. I shouldn't have
merged it, I got a bit carried away here. I hadn't realized it was
never CCed to the relevant maintainer(s) and list(s), and happens to
have some issues so I'm taking it out and it will come back via the
proper channels.
The rest is a bunch of LE fixes (argh, some of the new stuff was
broken on LE, I really need to start testing LE myself !) and various
random fixes here and there.
Finally one bit that's not strictly a fix, which is the HVC OPAL
change to "kick" the HVC thread when the firmware tells us there is
new incoming data. I don't feel like waiting for this one, it's
simple enough, and it makes a big difference in console responsiveness
which is good for my nerves"
* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (26 commits)
powerpc/powernv Adapt opal-elog and opal-dump to new sysfs_remove_file_self
Revert "powerpc/powernv: hwmon driver for power values, fan rpm and temperature"
power, sched: stop updating inside arch_update_cpu_topology() when nothing to be update
powerpc/le: Avoid creatng R_PPC64_TOCSAVE relocations for modules.
arch/powerpc: Use RCU_INIT_POINTER(x, NULL) in platforms/cell/spu_syscalls.c
powerpc/opal: Add missing include
powerpc: Convert last uses of __FUNCTION__ to __func__
powerpc: Add lq/stq emulation
powerpc/powernv: Add invalid OPAL call
powerpc/powernv: Add OPAL message log interface
powerpc/book3s: Fix mc_recoverable_range buffer overrun issue.
powerpc: Remove dead code in sycall entry
powerpc: Use of_node_init() for the fakenode in msi_bitmap.c
powerpc/mm: NUMA pte should be handled via slow path in get_user_pages_fast()
powerpc/powernv: Fix endian issues with sensor code
powerpc/powernv: Fix endian issues with OPAL async code
tty/hvc_opal: Kick the HVC thread on OPAL console events
powerpc/powernv: Add opal_notifier_unregister() and export to modules
powerpc/ppc64: Do not turn AIL (reloc-on interrupts) too early
powerpc/ppc64: Gracefully handle early interrupts
...
Diffstat (limited to 'arch/powerpc/platforms/powernv/opal.c')
-rw-r--r-- | arch/powerpc/platforms/powernv/opal.c | 59 |
1 files changed, 46 insertions, 13 deletions
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c index e92f2f67640f..49d2f00019e5 100644 --- a/arch/powerpc/platforms/powernv/opal.c +++ b/arch/powerpc/platforms/powernv/opal.c @@ -46,7 +46,7 @@ struct mcheck_recoverable_range { static struct mcheck_recoverable_range *mc_recoverable_range; static int mc_recoverable_range_len; -static struct device_node *opal_node; +struct device_node *opal_node; static DEFINE_SPINLOCK(opal_write_lock); extern u64 opal_mc_secondary_handler[]; static unsigned int *opal_irqs; @@ -102,13 +102,13 @@ int __init early_init_dt_scan_opal(unsigned long node, int __init early_init_dt_scan_recoverable_ranges(unsigned long node, const char *uname, int depth, void *data) { - unsigned long i, size; + unsigned long i, psize, size; const __be32 *prop; if (depth != 1 || strcmp(uname, "ibm,opal") != 0) return 0; - prop = of_get_flat_dt_prop(node, "mcheck-recoverable-ranges", &size); + prop = of_get_flat_dt_prop(node, "mcheck-recoverable-ranges", &psize); if (!prop) return 1; @@ -116,6 +116,23 @@ int __init early_init_dt_scan_recoverable_ranges(unsigned long node, pr_debug("Found machine check recoverable ranges.\n"); /* + * Calculate number of available entries. + * + * Each recoverable address range entry is (start address, len, + * recovery address), 2 cells each for start and recovery address, + * 1 cell for len, totalling 5 cells per entry. + */ + mc_recoverable_range_len = psize / (sizeof(*prop) * 5); + + /* Sanity check */ + if (!mc_recoverable_range_len) + return 1; + + /* Size required to hold all the entries. */ + size = mc_recoverable_range_len * + sizeof(struct mcheck_recoverable_range); + + /* * Allocate a buffer to hold the MC recoverable ranges. We would be * accessing them in real mode, hence it needs to be within * RMO region. @@ -124,11 +141,7 @@ int __init early_init_dt_scan_recoverable_ranges(unsigned long node, ppc64_rma_size)); memset(mc_recoverable_range, 0, size); - /* - * Each recoverable address entry is an (start address,len, - * recover address) pair, * 2 cells each, totalling 4 cells per entry. - */ - for (i = 0; i < size / (sizeof(*prop) * 5); i++) { + for (i = 0; i < mc_recoverable_range_len; i++) { mc_recoverable_range[i].start_addr = of_read_number(prop + (i * 5) + 0, 2); mc_recoverable_range[i].end_addr = @@ -142,7 +155,6 @@ int __init early_init_dt_scan_recoverable_ranges(unsigned long node, mc_recoverable_range[i].end_addr, mc_recoverable_range[i].recover_addr); } - mc_recoverable_range_len = i; return 1; } @@ -180,6 +192,20 @@ int opal_notifier_register(struct notifier_block *nb) atomic_notifier_chain_register(&opal_notifier_head, nb); return 0; } +EXPORT_SYMBOL_GPL(opal_notifier_register); + +int opal_notifier_unregister(struct notifier_block *nb) +{ + if (!nb) { + pr_warning("%s: Invalid argument (%p)\n", + __func__, nb); + return -EINVAL; + } + + atomic_notifier_chain_unregister(&opal_notifier_head, nb); + return 0; +} +EXPORT_SYMBOL_GPL(opal_notifier_unregister); static void opal_do_notifier(uint64_t events) { @@ -267,6 +293,7 @@ static void opal_handle_message(void) * value in /proc/device-tree. */ static struct opal_msg msg; + u32 type; ret = opal_get_msg(__pa(&msg), sizeof(msg)); /* No opal message pending. */ @@ -280,13 +307,14 @@ static void opal_handle_message(void) return; } + type = be32_to_cpu(msg.msg_type); + /* Sanity check */ - if (msg.msg_type > OPAL_MSG_TYPE_MAX) { - pr_warning("%s: Unknown message type: %u\n", - __func__, msg.msg_type); + if (type > OPAL_MSG_TYPE_MAX) { + pr_warning("%s: Unknown message type: %u\n", __func__, type); return; } - opal_message_do_notify(msg.msg_type, (void *)&msg); + opal_message_do_notify(type, (void *)&msg); } static int opal_message_notify(struct notifier_block *nb, @@ -574,6 +602,8 @@ static int __init opal_init(void) opal_platform_dump_init(); /* Setup system parameters interface */ opal_sys_param_init(); + /* Setup message log interface. */ + opal_msglog_init(); } return 0; @@ -605,3 +635,6 @@ void opal_shutdown(void) mdelay(10); } } + +/* Export this so that test modules can use it */ +EXPORT_SYMBOL_GPL(opal_invalid_call); |