mirror of
https://github.com/torvalds/linux.git
synced 2026-05-12 16:18:45 +02:00
powerpc fixes for 7.1 #2
- Fix KASAN sanitization flag for core_$(BITS).o - Fixes for handling offset values in pseries htmdump - Fix interrupt mask in cpm1_gpiochip_add16() - ps3/pasemi fixes to drop redundant result assignment - Fixes in papr-hvpipe code path - powerpc/perf: Update check for PERF_SAMPLE_DATA_SRC marked events Thanks to: Aboorva Devarajan, Athira Rajeev, Christophe Leroy (CS GROUP), Geert Uytterhoeven, Haren Myneni, Krzysztof Kozlowski, Mukesh Kumar Chaurasiya (IBM), Nathan Chancellor, Ritesh Harjani (IBM), Shivani Nittor, Sourabh Jain, Thomas Zimmermann, Venkat Rao Bagalkote -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEqX2DNAOgU8sBX3pRpnEsdPSHZJQFAmn+wiwACgkQpnEsdPSH ZJTF7g//aOOjo6k1HR+HMjIVdk2ri3XOQurw76uJw1HDNhgdsOpT9EUIsKJ2yRPQ pSBrqVJ0stn0g1HV38oRKi7zBeTvyBtI1xLKnim93hdLHNjrjgGSL1U884QE35IB TTH8agzpqsCWQlg6nge/3bTCROedkWltEgoohmMsaUHUOgh/lWVXFCjXKyNSAoLr AxPeCLFqYAr+QplFz9YU5SziLJ5MkWzfaNE0jYzhtfNs9l8CUAaHimq+ggCYirEO arXcccSkG2OW7fB6ImsVg1jVNoA5TtdmG2IUv+hB/pSXpJ1H0o2gEMRFI2avoPtu LzH85cQej/i1pX4H6JZj8oYzP3vkMR+aypid2O3vE7vJFAqHtydbgwgQKsupaFyi aPYMZR1r7UgDmqi6CoCcc55Wyoid9j7oZj9B5EDnWEcLcfPb7Gc7Pe2VdHj0Vu8j OSDPuJ3FPI7s03/T0KSXkJKAGZbigvHY/gSI2YRtCMyKSk56dYut/ARCEEFTr+hU NXGOwD/fe9nAg2fDdK9ou+iuBk943WPNMQTWZ4rcrV/XkpGS1mgXh9yIiJ3o4jr2 Mlodv5fOhFJwt/vn/0WPi9gA9e5saOme6cKEhFyNtjHhLAqws3E/+VOTgxfXRauY k4zGaJ5jbXupjCJkwh+UpAHa/sN+LN2cpx/zhQYtt8yG6qBXM2I= =ZRl8 -----END PGP SIGNATURE----- Merge tag 'powerpc-7.1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux Pull powerpc fixes from Madhavan Srinivasan: - Fix KASAN sanitization flag for core_$(BITS).o - Fixes for handling offset values in pseries htmdump - Fix interrupt mask in cpm1_gpiochip_add16() - ps3/pasemi fixes to drop redundant result assignment - Fixes in papr-hvpipe code path - powerpc/perf: Update check for PERF_SAMPLE_DATA_SRC marked events Thanks to Aboorva Devarajan, Athira Rajeev, Christophe Leroy (CS GROUP), Geert Uytterhoeven, Haren Myneni, Krzysztof Kozlowski, Mukesh Kumar Chaurasiya (IBM), Nathan Chancellor, Ritesh Harjani (IBM), Shivani Nittor, Sourabh Jain, Thomas Zimmermann, and Venkat Rao Bagalkote. * tag 'powerpc-7.1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: (21 commits) powerpc/pasemi: Drop redundant res assignment powerpc/ps3: Drop redundant result assignment powerpc/vdso: Drop -DCC_USING_PATCHABLE_FUNCTION_ENTRY from 32-bit flags with clang arch/powerpc: Drop CONFIG_FIRMWARE_EDID from defconfig files powerpc/perf: Update check for PERF_SAMPLE_DATA_SRC marked events powerpc/8xx: Fix interrupt mask in cpm1_gpiochip_add16() powerpc/vmx: avoid KASAN instrumentation in enter_vmx_ops() for kexec powerpc/kdump: fix KASAN sanitization flag for core_$(BITS).o pseries/papr-hvpipe: Fix style and checkpatch issues in enable_hvpipe_IRQ() pseries/papr-hvpipe: Refactor and simplify hvpipe_rtas_recv_msg() pseries/papr-hvpipe: Kill task_struct pointer from struct hvpipe_source_info pseries/papr-hvpipe: Simplify spin unlock usage in papr_hvpipe_handle_release() pseries/papr-hvpipe: Fix the usage of copy_to_user() pseries/papr-hvpipe: Fix & simplify error handling in papr_hvpipe_init() pseries/papr-hvpipe: Fix null ptr deref in papr_hvpipe_dev_create_handle() pseries/papr-hvpipe: Prevent kernel stack memory leak to userspace pseries/papr-hvpipe: Fix race with interrupt handler powerpc/pseries/htmdump: Add memory configuration dump support to htmdump module powerpc/pseries/htmdump: Fix the offset value used in htm status dump powerpc/pseries/htmdump: Fix the offset value used in processor configuration dump ...
This commit is contained in:
commit
bf0e022821
|
|
@ -76,7 +76,6 @@ CONFIG_SERIAL_8250_CONSOLE=y
|
|||
# CONFIG_HW_RANDOM is not set
|
||||
# CONFIG_HWMON is not set
|
||||
CONFIG_FB=y
|
||||
CONFIG_FIRMWARE_EDID=y
|
||||
CONFIG_FB_TILEBLITTING=y
|
||||
CONFIG_FB_RADEON=y
|
||||
CONFIG_FB_3DFX=y
|
||||
|
|
|
|||
|
|
@ -76,7 +76,6 @@ CONFIG_SERIAL_8250_CONSOLE=y
|
|||
CONFIG_NVRAM=y
|
||||
# CONFIG_HWMON is not set
|
||||
CONFIG_FB=y
|
||||
CONFIG_FIRMWARE_EDID=y
|
||||
CONFIG_FB_OF=y
|
||||
CONFIG_FB_MATROX=y
|
||||
CONFIG_FB_MATROX_MILLENIUM=y
|
||||
|
|
|
|||
|
|
@ -121,7 +121,6 @@ CONFIG_I2C_CHARDEV=y
|
|||
CONFIG_AGP=m
|
||||
CONFIG_AGP_UNINORTH=m
|
||||
CONFIG_FB=y
|
||||
CONFIG_FIRMWARE_EDID=y
|
||||
CONFIG_FB_TILEBLITTING=y
|
||||
CONFIG_FB_OF=y
|
||||
CONFIG_FB_NVIDIA=y
|
||||
|
|
|
|||
|
|
@ -98,7 +98,6 @@ CONFIG_SENSORS_LM85=y
|
|||
CONFIG_SENSORS_LM90=y
|
||||
CONFIG_DRM=y
|
||||
CONFIG_DRM_RADEON=y
|
||||
CONFIG_FIRMWARE_EDID=y
|
||||
CONFIG_FB_TILEBLITTING=y
|
||||
CONFIG_FB_VGA16=y
|
||||
CONFIG_FB_NVIDIA=y
|
||||
|
|
|
|||
|
|
@ -196,7 +196,6 @@ CONFIG_I2C_CHARDEV=y
|
|||
# CONFIG_PTP_1588_CLOCK is not set
|
||||
CONFIG_DRM=y
|
||||
CONFIG_DRM_AST=y
|
||||
CONFIG_FIRMWARE_EDID=y
|
||||
CONFIG_FB_OF=y
|
||||
CONFIG_FB_MATROX=m
|
||||
CONFIG_FB_MATROX_MILLENIUM=y
|
||||
|
|
|
|||
|
|
@ -249,7 +249,6 @@ CONFIG_I2C_CHARDEV=y
|
|||
CONFIG_I2C_AMD8111=y
|
||||
CONFIG_I2C_PASEMI=y
|
||||
CONFIG_FB=y
|
||||
CONFIG_FIRMWARE_EDID=y
|
||||
CONFIG_FB_OF=y
|
||||
CONFIG_FB_MATROX=y
|
||||
CONFIG_FB_MATROX_MILLENIUM=y
|
||||
|
|
|
|||
|
|
@ -118,7 +118,6 @@ CONFIG_SERIAL_8250_CONSOLE=y
|
|||
CONFIG_I2C_CHARDEV=y
|
||||
CONFIG_I2C_AMD8111=y
|
||||
CONFIG_FB=y
|
||||
CONFIG_FIRMWARE_EDID=y
|
||||
CONFIG_FB_OF=y
|
||||
CONFIG_FB_MATROX=y
|
||||
CONFIG_FB_MATROX_MILLENIUM=y
|
||||
|
|
|
|||
|
|
@ -214,7 +214,6 @@ CONFIG_SENSORS_IBMPOWERNV=m
|
|||
CONFIG_DRM=m
|
||||
CONFIG_DRM_AST=m
|
||||
CONFIG_FB=y
|
||||
CONFIG_FIRMWARE_EDID=y
|
||||
# CONFIG_VGA_CONSOLE is not set
|
||||
CONFIG_FRAMEBUFFER_CONSOLE=y
|
||||
CONFIG_LOGO=y
|
||||
|
|
|
|||
|
|
@ -62,6 +62,12 @@ CC32FLAGSREMOVE += -fno-stack-clash-protection
|
|||
# 32-bit one. clang validates the values passed to these arguments during
|
||||
# parsing, even when -fno-stack-protector is passed afterwards.
|
||||
CC32FLAGSREMOVE += -mstack-protector-guard%
|
||||
# ftrace is disabled for the vdso but arch/powerpc/Makefile adds this define to
|
||||
# KBUILD_CPPFLAGS, which enables use of the 'patchable_function_entry'
|
||||
# attribute in the 'inline' define via 'notrace'. This attribute is not
|
||||
# supported for the powerpcle target, resulting in many instances of
|
||||
# -Wunknown-attributes.
|
||||
CC32FLAGSREMOVE += -DCC_USING_PATCHABLE_FUNCTION_ENTRY
|
||||
endif
|
||||
LD32FLAGS := -Wl,-soname=linux-vdso32.so.1
|
||||
AS32FLAGS := -D__VDSO32__
|
||||
|
|
|
|||
|
|
@ -16,4 +16,4 @@ GCOV_PROFILE_core_$(BITS).o := n
|
|||
KCOV_INSTRUMENT_core_$(BITS).o := n
|
||||
UBSAN_SANITIZE_core_$(BITS).o := n
|
||||
KASAN_SANITIZE_core.o := n
|
||||
KASAN_SANITIZE_core_$(BITS) := n
|
||||
KASAN_SANITIZE_core_$(BITS).o := n
|
||||
|
|
|
|||
|
|
@ -52,7 +52,14 @@ int exit_vmx_usercopy(void)
|
|||
}
|
||||
EXPORT_SYMBOL(exit_vmx_usercopy);
|
||||
|
||||
int enter_vmx_ops(void)
|
||||
/*
|
||||
* Can be called from kexec copy_page() path with MMU off. The kexec
|
||||
* code sets preempt_count to HARDIRQ_OFFSET so we return early here.
|
||||
* Since in_interrupt() is always inline, __no_sanitize_address on this
|
||||
* function is sufficient to avoid KASAN shadow memory accesses in real
|
||||
* mode.
|
||||
*/
|
||||
int __no_sanitize_address enter_vmx_ops(void)
|
||||
{
|
||||
if (in_interrupt())
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -2242,6 +2242,7 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
|
|||
const u64 last_period = event->hw.last_period;
|
||||
s64 prev, delta, left;
|
||||
int record = 0;
|
||||
int mark_event = regs->dsisr & MMCRA_SAMPLE_ENABLE;
|
||||
|
||||
if (event->hw.state & PERF_HES_STOPPED) {
|
||||
write_pmc(event->hw.idx, 0);
|
||||
|
|
@ -2304,9 +2305,9 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
|
|||
* In ISA v3.0 and before values "0" and "7" are considered reserved.
|
||||
* In ISA v3.1, value "7" has been used to indicate "larx/stcx".
|
||||
* Drop the sample if "type" has reserved values for this field with a
|
||||
* ISA version check.
|
||||
* ISA version check for marked events.
|
||||
*/
|
||||
if (event->attr.sample_type & PERF_SAMPLE_DATA_SRC &&
|
||||
if (mark_event && event->attr.sample_type & PERF_SAMPLE_DATA_SRC &&
|
||||
ppmu->get_mem_data_src) {
|
||||
val = (regs->dar & SIER_TYPE_MASK) >> SIER_TYPE_SHIFT;
|
||||
if (val == 0 || (val == 7 && !cpu_has_feature(CPU_FTR_ARCH_31))) {
|
||||
|
|
|
|||
|
|
@ -477,7 +477,7 @@ int cpm1_gpiochip_add16(struct device *dev)
|
|||
struct device_node *np = dev->of_node;
|
||||
struct cpm1_gpio16_chip *cpm1_gc;
|
||||
struct gpio_chip *gc;
|
||||
u16 mask;
|
||||
u32 mask;
|
||||
|
||||
cpm1_gc = devm_kzalloc(dev, sizeof(*cpm1_gc), GFP_KERNEL);
|
||||
if (!cpm1_gc)
|
||||
|
|
@ -485,7 +485,7 @@ int cpm1_gpiochip_add16(struct device *dev)
|
|||
|
||||
spin_lock_init(&cpm1_gc->lock);
|
||||
|
||||
if (!of_property_read_u16(np, "fsl,cpm1-gpio-irq-mask", &mask)) {
|
||||
if (!of_property_read_u32(np, "fsl,cpm1-gpio-irq-mask", &mask)) {
|
||||
int i, j;
|
||||
|
||||
for (i = 0, j = 0; i < 16; i++)
|
||||
|
|
|
|||
|
|
@ -272,13 +272,12 @@ void __init pas_pci_init(void)
|
|||
{
|
||||
struct device_node *root = of_find_node_by_path("/");
|
||||
struct device_node *np;
|
||||
int res;
|
||||
|
||||
pci_set_flags(PCI_SCAN_ALL_PCIE_DEVS);
|
||||
|
||||
np = of_find_compatible_node(root, NULL, "pasemi,rootbus");
|
||||
if (np) {
|
||||
res = pas_add_bridge(np);
|
||||
pas_add_bridge(np);
|
||||
of_node_put(np);
|
||||
}
|
||||
of_node_put(root);
|
||||
|
|
|
|||
|
|
@ -950,8 +950,6 @@ static int __init ps3_start_probe_thread(enum ps3_bus_type bus_type)
|
|||
|
||||
static int __init ps3_register_devices(void)
|
||||
{
|
||||
int result;
|
||||
|
||||
if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
|
||||
return -ENODEV;
|
||||
|
||||
|
|
@ -959,7 +957,7 @@ static int __init ps3_register_devices(void)
|
|||
|
||||
/* ps3_repository_dump_bus_info(); */
|
||||
|
||||
result = ps3_start_probe_thread(PS3_BUS_TYPE_STORAGE);
|
||||
ps3_start_probe_thread(PS3_BUS_TYPE_STORAGE);
|
||||
|
||||
ps3_register_vuart_devices();
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ static void *htm_buf;
|
|||
static void *htm_status_buf;
|
||||
static void *htm_info_buf;
|
||||
static void *htm_caps_buf;
|
||||
static void *htm_mem_buf;
|
||||
static u32 nodeindex;
|
||||
static u32 nodalchipindex;
|
||||
static u32 coreindexonchip;
|
||||
|
|
@ -86,7 +87,7 @@ static ssize_t htm_return_check(long rc)
|
|||
static ssize_t htmdump_read(struct file *filp, char __user *ubuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
void *htm_buf = filp->private_data;
|
||||
void *htm_buf_data = filp->private_data;
|
||||
unsigned long page, read_size, available;
|
||||
loff_t offset;
|
||||
long rc, ret;
|
||||
|
|
@ -100,7 +101,7 @@ static ssize_t htmdump_read(struct file *filp, char __user *ubuf,
|
|||
* - last three values are address, size and offset
|
||||
*/
|
||||
rc = htm_hcall_wrapper(htmflags, nodeindex, nodalchipindex, coreindexonchip,
|
||||
htmtype, H_HTM_OP_DUMP_DATA, virt_to_phys(htm_buf),
|
||||
htmtype, H_HTM_OP_DUMP_DATA, virt_to_phys(htm_buf_data),
|
||||
PAGE_SIZE, page);
|
||||
|
||||
ret = htm_return_check(rc);
|
||||
|
|
@ -112,7 +113,61 @@ static ssize_t htmdump_read(struct file *filp, char __user *ubuf,
|
|||
available = PAGE_SIZE;
|
||||
read_size = min(count, available);
|
||||
*ppos += read_size;
|
||||
return simple_read_from_buffer(ubuf, count, &offset, htm_buf, available);
|
||||
return simple_read_from_buffer(ubuf, count, &offset, htm_buf_data, available);
|
||||
}
|
||||
|
||||
static ssize_t htmsystem_mem_read(struct file *filp, char __user *ubuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
void *htm_mem_data = filp->private_data;
|
||||
long rc, ret;
|
||||
u64 *num_entries;
|
||||
u64 to_copy = 0;
|
||||
loff_t offset = 0;
|
||||
u64 mem_offset = 0;
|
||||
|
||||
/*
|
||||
* Invoke H_HTM call with:
|
||||
* - operation as htm status (H_HTM_OP_STATUS)
|
||||
* - last three values as addr, size and offset. "offset"
|
||||
* is value from output buffer header that points to next
|
||||
* entry to dump. 0 is the first entry to dump. next entry
|
||||
* is read from the output bufferbyte offset 0x8.
|
||||
*
|
||||
* When first time hcall is invoked, mem_offset should be
|
||||
* zero because zero is the first entry.
|
||||
* In the next hcall, offset of next entry to read from is
|
||||
* picked from output buffer header itself. So don't fill
|
||||
* mem_offset for first read.
|
||||
*
|
||||
* If there is no further data to read in next iteration,
|
||||
* offset value from output buffer header will point to -1.
|
||||
*/
|
||||
if (*ppos) {
|
||||
mem_offset = *(u64 *)(htm_mem_data + 0x8);
|
||||
if (mem_offset == -1)
|
||||
return 0;
|
||||
}
|
||||
rc = htm_hcall_wrapper(htmflags, nodeindex, nodalchipindex, coreindexonchip,
|
||||
htmtype, H_HTM_OP_DUMP_SYSMEM_CONF, virt_to_phys(htm_mem_data),
|
||||
PAGE_SIZE, be64_to_cpu(mem_offset));
|
||||
ret = htm_return_check(rc);
|
||||
if (ret <= 0) {
|
||||
pr_debug("H_HTM hcall returned for op: H_HTM_OP_DUMP_SYSMEM_CONF with hcall returning %ld\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* HTM system mem buffer, start of buffer + 0x10 gives the
|
||||
* number of HTM entries in the buffer.
|
||||
* So total count to copy is:
|
||||
* 32 bytes (for first 5 fields) + (number of HTM entries * entry size)
|
||||
*/
|
||||
num_entries = htm_mem_data + 0x10;
|
||||
to_copy = 32 + (be64_to_cpu(*num_entries) * 32);
|
||||
|
||||
*ppos += to_copy;
|
||||
return simple_read_from_buffer(ubuf, count, &offset, htm_mem_data, to_copy);
|
||||
}
|
||||
|
||||
static const struct file_operations htmdump_fops = {
|
||||
|
|
@ -121,6 +176,12 @@ static const struct file_operations htmdump_fops = {
|
|||
.open = simple_open,
|
||||
};
|
||||
|
||||
static const struct file_operations htmsystem_mem_fops = {
|
||||
.llseek = NULL,
|
||||
.read = htmsystem_mem_read,
|
||||
.open = simple_open,
|
||||
};
|
||||
|
||||
static int htmconfigure_set(void *data, u64 val)
|
||||
{
|
||||
long rc, ret;
|
||||
|
|
@ -226,20 +287,31 @@ static int htmstart_get(void *data, u64 *val)
|
|||
static ssize_t htmstatus_read(struct file *filp, char __user *ubuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
void *htm_status_buf = filp->private_data;
|
||||
void *htm_status_data = filp->private_data;
|
||||
long rc, ret;
|
||||
u64 *num_entries;
|
||||
u64 to_copy;
|
||||
int htmstatus_flag;
|
||||
loff_t offset = 0;
|
||||
u64 status_offset = 0;
|
||||
|
||||
/*
|
||||
* Invoke H_HTM call with:
|
||||
* - operation as htm status (H_HTM_OP_STATUS)
|
||||
* - last three values as addr, size and offset
|
||||
* - last three values as addr, size and offset.
|
||||
* "offset" is value from output buffer header
|
||||
* that points to next entry to dump. 0 is the first
|
||||
* entry to dump. next entry is read from the output
|
||||
* bufferbyte offset 0x8.
|
||||
*/
|
||||
if (*ppos) {
|
||||
status_offset = *(u64 *)(htm_status_data + 0x8);
|
||||
if (status_offset == -1)
|
||||
return 0;
|
||||
}
|
||||
rc = htm_hcall_wrapper(htmflags, nodeindex, nodalchipindex, coreindexonchip,
|
||||
htmtype, H_HTM_OP_STATUS, virt_to_phys(htm_status_buf),
|
||||
PAGE_SIZE, 0);
|
||||
htmtype, H_HTM_OP_STATUS, virt_to_phys(htm_status_data),
|
||||
PAGE_SIZE, be64_to_cpu(status_offset));
|
||||
|
||||
ret = htm_return_check(rc);
|
||||
if (ret <= 0) {
|
||||
|
|
@ -255,13 +327,15 @@ static ssize_t htmstatus_read(struct file *filp, char __user *ubuf,
|
|||
* So total count to copy is:
|
||||
* 32 bytes (for first 7 fields) + (number of HTM entries * entry size)
|
||||
*/
|
||||
num_entries = htm_status_buf + 0x10;
|
||||
num_entries = htm_status_data + 0x10;
|
||||
if (htmtype == 0x2)
|
||||
htmstatus_flag = 0x8;
|
||||
else
|
||||
htmstatus_flag = 0x6;
|
||||
to_copy = 32 + (be64_to_cpu(*num_entries) * htmstatus_flag);
|
||||
return simple_read_from_buffer(ubuf, count, ppos, htm_status_buf, to_copy);
|
||||
*ppos += to_copy;
|
||||
|
||||
return simple_read_from_buffer(ubuf, count, &offset, htm_status_data, to_copy);
|
||||
}
|
||||
|
||||
static const struct file_operations htmstatus_fops = {
|
||||
|
|
@ -273,19 +347,30 @@ static const struct file_operations htmstatus_fops = {
|
|||
static ssize_t htminfo_read(struct file *filp, char __user *ubuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
void *htm_info_buf = filp->private_data;
|
||||
void *htm_info_data = filp->private_data;
|
||||
long rc, ret;
|
||||
u64 *num_entries;
|
||||
u64 to_copy;
|
||||
loff_t offset = 0;
|
||||
u64 info_offset = 0;
|
||||
|
||||
/*
|
||||
* Invoke H_HTM call with:
|
||||
* - operation as htm status (H_HTM_OP_STATUS)
|
||||
* - last three values as addr, size and offset
|
||||
* "offset" is value from output buffer header
|
||||
* that points to next entry to dump. 0 is the first
|
||||
* entry to dump. next entry is read from the output
|
||||
* bufferbyte offset 0x8.
|
||||
*/
|
||||
if (*ppos) {
|
||||
info_offset = *(u64 *)(htm_info_data + 0x8);
|
||||
if (info_offset == -1)
|
||||
return 0;
|
||||
}
|
||||
rc = htm_hcall_wrapper(htmflags, nodeindex, nodalchipindex, coreindexonchip,
|
||||
htmtype, H_HTM_OP_DUMP_SYSPROC_CONF, virt_to_phys(htm_info_buf),
|
||||
PAGE_SIZE, 0);
|
||||
htmtype, H_HTM_OP_DUMP_SYSPROC_CONF, virt_to_phys(htm_info_data),
|
||||
PAGE_SIZE, be64_to_cpu(info_offset));
|
||||
|
||||
ret = htm_return_check(rc);
|
||||
if (ret <= 0) {
|
||||
|
|
@ -301,15 +386,17 @@ static ssize_t htminfo_read(struct file *filp, char __user *ubuf,
|
|||
* So total count to copy is:
|
||||
* 32 bytes (for first 5 fields) + (number of HTM entries * entry size)
|
||||
*/
|
||||
num_entries = htm_info_buf + 0x10;
|
||||
num_entries = htm_info_data + 0x10;
|
||||
to_copy = 32 + (be64_to_cpu(*num_entries) * 16);
|
||||
return simple_read_from_buffer(ubuf, count, ppos, htm_info_buf, to_copy);
|
||||
|
||||
*ppos += to_copy;
|
||||
return simple_read_from_buffer(ubuf, count, &offset, htm_info_data, to_copy);
|
||||
}
|
||||
|
||||
static ssize_t htmcaps_read(struct file *filp, char __user *ubuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
void *htm_caps_buf = filp->private_data;
|
||||
void *htm_caps_data = filp->private_data;
|
||||
long rc, ret;
|
||||
|
||||
/*
|
||||
|
|
@ -319,7 +406,7 @@ static ssize_t htmcaps_read(struct file *filp, char __user *ubuf,
|
|||
* and zero
|
||||
*/
|
||||
rc = htm_hcall_wrapper(htmflags, nodeindex, nodalchipindex, coreindexonchip,
|
||||
htmtype, H_HTM_OP_CAPABILITIES, virt_to_phys(htm_caps_buf),
|
||||
htmtype, H_HTM_OP_CAPABILITIES, virt_to_phys(htm_caps_data),
|
||||
0x80, 0);
|
||||
|
||||
ret = htm_return_check(rc);
|
||||
|
|
@ -328,7 +415,7 @@ static ssize_t htmcaps_read(struct file *filp, char __user *ubuf,
|
|||
return ret;
|
||||
}
|
||||
|
||||
return simple_read_from_buffer(ubuf, count, ppos, htm_caps_buf, 0x80);
|
||||
return simple_read_from_buffer(ubuf, count, ppos, htm_caps_data, 0x80);
|
||||
}
|
||||
|
||||
static const struct file_operations htminfo_fops = {
|
||||
|
|
@ -457,9 +544,17 @@ static int htmdump_init_debugfs(void)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Memory to present HTM system memory configuration */
|
||||
htm_mem_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
if (!htm_mem_buf) {
|
||||
pr_err("Failed to allocate htm mem buf\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
debugfs_create_file("htmstatus", 0400, htmdump_debugfs_dir, htm_status_buf, &htmstatus_fops);
|
||||
debugfs_create_file("htminfo", 0400, htmdump_debugfs_dir, htm_info_buf, &htminfo_fops);
|
||||
debugfs_create_file("htmcaps", 0400, htmdump_debugfs_dir, htm_caps_buf, &htmcaps_fops);
|
||||
debugfs_create_file("htmsystem_mem", 0400, htmdump_debugfs_dir, htm_mem_buf, &htmsystem_mem_fops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -482,6 +577,10 @@ static void __exit htmdump_exit(void)
|
|||
{
|
||||
debugfs_remove_recursive(htmdump_debugfs_dir);
|
||||
kfree(htm_buf);
|
||||
kfree(htm_status_buf);
|
||||
kfree(htm_info_buf);
|
||||
kfree(htm_caps_buf);
|
||||
kfree(htm_mem_buf);
|
||||
}
|
||||
|
||||
module_init(htmdump_init);
|
||||
|
|
|
|||
|
|
@ -190,9 +190,6 @@ static int hvpipe_rtas_recv_msg(char __user *buf, int size)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = rtas_ibm_receive_hvpipe_msg(work_area, &srcID,
|
||||
&bytes_written);
|
||||
if (!ret) {
|
||||
/*
|
||||
* Recv HVPIPE RTAS is successful.
|
||||
* When releasing FD or no one is waiting on the
|
||||
|
|
@ -200,23 +197,27 @@ static int hvpipe_rtas_recv_msg(char __user *buf, int size)
|
|||
* so that pipe is not blocked - this func is called
|
||||
* with NULL buf.
|
||||
*/
|
||||
if (buf) {
|
||||
ret = rtas_ibm_receive_hvpipe_msg(work_area, &srcID, &bytes_written);
|
||||
if (ret) {
|
||||
pr_err("ibm,receive-hvpipe-msg failed with %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!buf)
|
||||
goto out;
|
||||
|
||||
if (size < bytes_written) {
|
||||
pr_err("Received the payload size = %d, but the buffer size = %d\n",
|
||||
bytes_written, size);
|
||||
bytes_written = size;
|
||||
}
|
||||
ret = copy_to_user(buf,
|
||||
rtas_work_area_raw_buf(work_area),
|
||||
bytes_written);
|
||||
if (!ret)
|
||||
ret = bytes_written;
|
||||
}
|
||||
} else {
|
||||
pr_err("ibm,receive-hvpipe-msg failed with %d\n",
|
||||
ret);
|
||||
}
|
||||
|
||||
if (copy_to_user(buf, rtas_work_area_raw_buf(work_area), bytes_written))
|
||||
ret = -EFAULT;
|
||||
else
|
||||
ret = bytes_written;
|
||||
|
||||
out:
|
||||
rtas_work_area_free(work_area);
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -327,8 +328,8 @@ static ssize_t papr_hvpipe_handle_read(struct file *file,
|
|||
{
|
||||
|
||||
struct hvpipe_source_info *src_info = file->private_data;
|
||||
struct papr_hvpipe_hdr hdr;
|
||||
long ret;
|
||||
struct papr_hvpipe_hdr hdr = {};
|
||||
ssize_t ret = 0;
|
||||
|
||||
/*
|
||||
* Return -ENXIO during migration
|
||||
|
|
@ -376,7 +377,7 @@ static ssize_t papr_hvpipe_handle_read(struct file *file,
|
|||
|
||||
ret = copy_to_user(buf, &hdr, HVPIPE_HDR_LEN);
|
||||
if (ret)
|
||||
return ret;
|
||||
return -EFAULT;
|
||||
|
||||
/*
|
||||
* Message event has payload, so get the payload with
|
||||
|
|
@ -385,19 +386,23 @@ static ssize_t papr_hvpipe_handle_read(struct file *file,
|
|||
if (hdr.flags & HVPIPE_MSG_AVAILABLE) {
|
||||
ret = hvpipe_rtas_recv_msg(buf + HVPIPE_HDR_LEN,
|
||||
size - HVPIPE_HDR_LEN);
|
||||
if (ret > 0) {
|
||||
/*
|
||||
* Always clear MSG_AVAILABLE once the RTAS call has drained
|
||||
* the message, regardless of whether copy_to_user succeeded.
|
||||
*/
|
||||
if (ret >= 0 || ret == -EFAULT)
|
||||
src_info->hvpipe_status &= ~HVPIPE_MSG_AVAILABLE;
|
||||
ret += HVPIPE_HDR_LEN;
|
||||
}
|
||||
} else if (hdr.flags & HVPIPE_LOST_CONNECTION) {
|
||||
/*
|
||||
* Hypervisor is closing the pipe for the specific
|
||||
* source. So notify user space.
|
||||
*/
|
||||
src_info->hvpipe_status &= ~HVPIPE_LOST_CONNECTION;
|
||||
ret = HVPIPE_HDR_LEN;
|
||||
}
|
||||
|
||||
if (ret >= 0)
|
||||
ret += HVPIPE_HDR_LEN;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -444,16 +449,18 @@ static int papr_hvpipe_handle_release(struct inode *inode,
|
|||
struct file *file)
|
||||
{
|
||||
struct hvpipe_source_info *src_info;
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* Hold the lock, remove source from src_list, reset the
|
||||
* hvpipe status and release the lock to prevent any race
|
||||
* with message event IRQ.
|
||||
*/
|
||||
spin_lock(&hvpipe_src_list_lock);
|
||||
spin_lock_irqsave(&hvpipe_src_list_lock, flags);
|
||||
src_info = file->private_data;
|
||||
list_del(&src_info->list);
|
||||
file->private_data = NULL;
|
||||
spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
|
||||
/*
|
||||
* If the pipe for this specific source has any pending
|
||||
* payload, issue recv HVPIPE RTAS so that pipe will not
|
||||
|
|
@ -461,10 +468,8 @@ static int papr_hvpipe_handle_release(struct inode *inode,
|
|||
*/
|
||||
if (src_info->hvpipe_status & HVPIPE_MSG_AVAILABLE) {
|
||||
src_info->hvpipe_status = 0;
|
||||
spin_unlock(&hvpipe_src_list_lock);
|
||||
hvpipe_rtas_recv_msg(NULL, 0);
|
||||
} else
|
||||
spin_unlock(&hvpipe_src_list_lock);
|
||||
}
|
||||
|
||||
kfree(src_info);
|
||||
return 0;
|
||||
|
|
@ -479,50 +484,53 @@ static const struct file_operations papr_hvpipe_handle_ops = {
|
|||
|
||||
static int papr_hvpipe_dev_create_handle(u32 srcID)
|
||||
{
|
||||
struct hvpipe_source_info *src_info __free(kfree) = NULL;
|
||||
|
||||
spin_lock(&hvpipe_src_list_lock);
|
||||
/*
|
||||
* Do not allow more than one process communicates with
|
||||
* each source.
|
||||
*/
|
||||
src_info = hvpipe_find_source(srcID);
|
||||
if (src_info) {
|
||||
spin_unlock(&hvpipe_src_list_lock);
|
||||
pr_err("pid(%d) is already using the source(%d)\n",
|
||||
src_info->tsk->pid, srcID);
|
||||
return -EALREADY;
|
||||
}
|
||||
spin_unlock(&hvpipe_src_list_lock);
|
||||
struct hvpipe_source_info *src_info;
|
||||
int fd;
|
||||
unsigned long flags;
|
||||
|
||||
src_info = kzalloc_obj(*src_info, GFP_KERNEL_ACCOUNT);
|
||||
if (!src_info)
|
||||
return -ENOMEM;
|
||||
|
||||
src_info->srcID = srcID;
|
||||
src_info->tsk = current;
|
||||
init_waitqueue_head(&src_info->recv_wqh);
|
||||
|
||||
FD_PREPARE(fdf, O_RDONLY | O_CLOEXEC,
|
||||
anon_inode_getfile("[papr-hvpipe]", &papr_hvpipe_handle_ops,
|
||||
(void *)src_info, O_RDWR));
|
||||
if (fdf.err)
|
||||
return fdf.err;
|
||||
|
||||
retain_and_null_ptr(src_info);
|
||||
spin_lock(&hvpipe_src_list_lock);
|
||||
/*
|
||||
* If two processes are executing ioctl() for the same
|
||||
* source ID concurrently, prevent the second process to
|
||||
* acquire FD.
|
||||
* Do not allow more than one process communicates with
|
||||
* each source.
|
||||
*/
|
||||
spin_lock_irqsave(&hvpipe_src_list_lock, flags);
|
||||
if (hvpipe_find_source(srcID)) {
|
||||
spin_unlock(&hvpipe_src_list_lock);
|
||||
spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
|
||||
pr_err("pid(%s:%d) could not get the source(%d)\n",
|
||||
current->comm, task_pid_nr(current), srcID);
|
||||
kfree(src_info);
|
||||
return -EALREADY;
|
||||
}
|
||||
list_add(&src_info->list, &hvpipe_src_list);
|
||||
spin_unlock(&hvpipe_src_list_lock);
|
||||
return fd_publish(fdf);
|
||||
spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
|
||||
|
||||
fd = FD_ADD(O_RDONLY | O_CLOEXEC,
|
||||
anon_inode_getfile("[papr-hvpipe]", &papr_hvpipe_handle_ops,
|
||||
(void *)src_info, O_RDWR));
|
||||
if (fd < 0) {
|
||||
spin_lock_irqsave(&hvpipe_src_list_lock, flags);
|
||||
list_del(&src_info->list);
|
||||
spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
|
||||
/*
|
||||
* if we fail to add FD, that means no userspace program is
|
||||
* polling. In that case if there is a msg pending because the
|
||||
* interrupt was fired after the src_info was added to the
|
||||
* global list, then let's consume it here, to unblock the
|
||||
* hvpipe
|
||||
*/
|
||||
if (src_info->hvpipe_status & HVPIPE_MSG_AVAILABLE)
|
||||
hvpipe_rtas_recv_msg(NULL, 0);
|
||||
kfree(src_info);
|
||||
return fd;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -690,15 +698,14 @@ static int __init enable_hvpipe_IRQ(void)
|
|||
|
||||
/* hvpipe events */
|
||||
np = of_find_node_by_path("/event-sources/ibm,hvpipe-msg-events");
|
||||
if (np != NULL) {
|
||||
request_event_sources_irqs(np, hvpipe_event_interrupt,
|
||||
"HPIPE_EVENT");
|
||||
of_node_put(np);
|
||||
} else {
|
||||
pr_err("Can not enable hvpipe event IRQ\n");
|
||||
if (!np) {
|
||||
pr_err("No device node found, could not enable hvpipe event IRQ\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
request_event_sources_irqs(np, hvpipe_event_interrupt, "HPIPE_EVENT");
|
||||
of_node_put(np);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -775,23 +782,29 @@ static int __init papr_hvpipe_init(void)
|
|||
}
|
||||
|
||||
ret = enable_hvpipe_IRQ();
|
||||
if (!ret) {
|
||||
ret = set_hvpipe_sys_param(1);
|
||||
if (!ret)
|
||||
ret = misc_register(&papr_hvpipe_dev);
|
||||
}
|
||||
if (ret)
|
||||
goto out_wq;
|
||||
|
||||
ret = misc_register(&papr_hvpipe_dev);
|
||||
if (ret)
|
||||
goto out_wq;
|
||||
|
||||
ret = set_hvpipe_sys_param(1);
|
||||
if (ret)
|
||||
goto out_misc;
|
||||
|
||||
if (!ret) {
|
||||
pr_info("hvpipe feature is enabled\n");
|
||||
hvpipe_feature = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
pr_err("hvpipe feature is not enabled %d\n", ret);
|
||||
out_misc:
|
||||
misc_deregister(&papr_hvpipe_dev);
|
||||
out_wq:
|
||||
destroy_workqueue(papr_hvpipe_wq);
|
||||
out:
|
||||
kfree(papr_hvpipe_work);
|
||||
papr_hvpipe_work = NULL;
|
||||
pr_err("hvpipe feature is not enabled %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
machine_device_initcall(pseries, papr_hvpipe_init);
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ struct hvpipe_source_info {
|
|||
u32 srcID;
|
||||
u32 hvpipe_status;
|
||||
wait_queue_head_t recv_wqh; /* wake up poll() waitq */
|
||||
struct task_struct *tsk;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user