mirror of
https://github.com/fail0verflow/switch-linux.git
synced 2025-05-04 02:34:21 -04:00
The hotplug code uses its own workqueue to handle IRQ requests (pseries_hp_wq), however that workqueue is initialized after init_ras_IRQ(). That can lead to a kernel panic if any hotplug interrupts fire after init_ras_IRQ() but before pseries_hp_wq is initialised. eg: UDP-Lite hash table entries: 2048 (order: 0, 65536 bytes) NET: Registered protocol family 1 Unpacking initramfs... (qemu) object_add memory-backend-ram,id=mem1,size=10G (qemu) device_add pc-dimm,id=dimm1,memdev=mem1 Unable to handle kernel paging request for data at address 0xf94d03007c421378 Faulting instruction address: 0xc00000000012d744 Oops: Kernel access of bad area, sig: 11 [#1] LE SMP NR_CPUS=2048 NUMA pSeries Modules linked in: CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.15.0-rc2-ziviani+ #26 task: (ptrval) task.stack: (ptrval) NIP: c00000000012d744 LR: c00000000012d744 CTR: 0000000000000000 REGS: (ptrval) TRAP: 0380 Not tainted (4.15.0-rc2-ziviani+) MSR: 8000000000009033 <SF,EE,ME,IR,DR,RI,LE> CR: 28088042 XER: 20040000 CFAR: c00000000012d3c4 SOFTE: 0 ... NIP [c00000000012d744] __queue_work+0xd4/0x5c0 LR [c00000000012d744] __queue_work+0xd4/0x5c0 Call Trace: [c0000000fffefb90] [c00000000012d744] __queue_work+0xd4/0x5c0 (unreliable) [c0000000fffefc70] [c00000000012dce4] queue_work_on+0xb4/0xf0 This commit makes the RAS IRQ registration explicitly dependent on the creation of the pseries_hp_wq. Reported-by: Min Deng <mdeng@redhat.com> Reported-by: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> Tested-by: Jose Ricardo Ziviani <joserz@linux.vnet.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
103 lines
2.6 KiB
C
103 lines
2.6 KiB
C
/*
|
|
* Copyright 2006 IBM Corporation.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version
|
|
* 2 of the License, or (at your option) any later version.
|
|
*/
|
|
|
|
#ifndef _PSERIES_PSERIES_H
|
|
#define _PSERIES_PSERIES_H
|
|
|
|
#include <linux/interrupt.h>
|
|
#include <asm/rtas.h>
|
|
|
|
struct device_node;
|
|
|
|
extern void request_event_sources_irqs(struct device_node *np,
|
|
irq_handler_t handler, const char *name);
|
|
|
|
#include <linux/of.h>
|
|
|
|
struct pt_regs;
|
|
|
|
extern int pSeries_system_reset_exception(struct pt_regs *regs);
|
|
extern int pSeries_machine_check_exception(struct pt_regs *regs);
|
|
|
|
#ifdef CONFIG_SMP
|
|
extern void smp_init_pseries(void);
|
|
#else
|
|
static inline void smp_init_pseries(void) { };
|
|
#endif
|
|
|
|
extern void pseries_kexec_cpu_down(int crash_shutdown, int secondary);
|
|
|
|
extern void pSeries_final_fixup(void);
|
|
|
|
/* Poweron flag used for enabling auto ups restart */
|
|
extern unsigned long rtas_poweron_auto;
|
|
|
|
/* Provided by HVC VIO */
|
|
extern void hvc_vio_init_early(void);
|
|
|
|
/* Dynamic logical Partitioning/Mobility */
|
|
extern void dlpar_free_cc_nodes(struct device_node *);
|
|
extern void dlpar_free_cc_property(struct property *);
|
|
extern struct device_node *dlpar_configure_connector(__be32,
|
|
struct device_node *);
|
|
extern int dlpar_attach_node(struct device_node *, struct device_node *);
|
|
extern int dlpar_detach_node(struct device_node *);
|
|
extern int dlpar_acquire_drc(u32 drc_index);
|
|
extern int dlpar_release_drc(u32 drc_index);
|
|
|
|
void queue_hotplug_event(struct pseries_hp_errorlog *hp_errlog,
|
|
struct completion *hotplug_done, int *rc);
|
|
#ifdef CONFIG_MEMORY_HOTPLUG
|
|
int dlpar_memory(struct pseries_hp_errorlog *hp_elog);
|
|
#else
|
|
static inline int dlpar_memory(struct pseries_hp_errorlog *hp_elog)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_HOTPLUG_CPU
|
|
int dlpar_cpu(struct pseries_hp_errorlog *hp_elog);
|
|
#else
|
|
static inline int dlpar_cpu(struct pseries_hp_errorlog *hp_elog)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
#endif
|
|
|
|
/* PCI root bridge prepare function override for pseries */
|
|
struct pci_host_bridge;
|
|
int pseries_root_bridge_prepare(struct pci_host_bridge *bridge);
|
|
|
|
extern struct pci_controller_ops pseries_pci_controller_ops;
|
|
|
|
unsigned long pseries_memory_block_size(void);
|
|
|
|
extern int CMO_PrPSP;
|
|
extern int CMO_SecPSP;
|
|
extern unsigned long CMO_PageSize;
|
|
|
|
static inline int cmo_get_primary_psp(void)
|
|
{
|
|
return CMO_PrPSP;
|
|
}
|
|
|
|
static inline int cmo_get_secondary_psp(void)
|
|
{
|
|
return CMO_SecPSP;
|
|
}
|
|
|
|
static inline unsigned long cmo_get_page_size(void)
|
|
{
|
|
return CMO_PageSize;
|
|
}
|
|
|
|
int dlpar_workqueue_init(void);
|
|
|
|
#endif /* _PSERIES_PSERIES_H */
|