powerpc fixes for 4.9 #3
Fixes marked for stable: - Prevent unlikely crash in copro_calculate_slb() (Frederic Barrat) - cxl: Prevent adapter reset if an active context exists (Vaibhav Jain) Fixes for code merged this cycle: - Fix boot on systems with uncompressed kernel image (Heiner Kallweit) - Drop dump_numa_memory_topology() (Michael Ellerman) - Fix numa topology console print (Aneesh Kumar K.V) - Ignore the pkey system calls for now (Stephen Rothwell) -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJYCpJqAAoJEFHr6jzI4aWABS8QAJXuCjXrfNdQoiNmSHTOOUuj Z1KFIU/WjLa42VD2KIvW/OiTjzmrA9yl/PkNYD185yXu5DAE1h+lH0gBCA3KlSUc LwNneqn+3aGqmAX7jTm1HaWFCQt6mF0z3hwDPvEXhC4hcNjhe3mp3Q9/Q8idVfAJ f48vBa8qgJ5gpD5zVva5ujh1F2RUA+RQmhaR+LS19B+OH6xPzRp7VGUdsKRp75pI ILVCsjxA+DoaMOUK9quE5/9n9IK+N10QLfCqJu6HxJJ47nBxkiDPtdcndv0WTA9m kYTdqcv5o7A4+SrdXOkNBBHjj09UhdHBmhIrEt6286wyJ3thvDIhjMrX6OwJSCyb oB8PhXwjyUQrws19h4RNDToPG2Hr9A8BXVTofyPV4ku6gvucI03WFcVbHMWhAiLh lwR3Ppg4mHHAndL4oRlRhpvEVmBGwMuKEbisTa82T5RK4iPVWRcGqN6bltj9g6QX VXc8KQzKM+qEKQmDzdjExr0ZFq+USea96JmCJs6l9+M1nwe5CRCJAZyjp5LhVYRf ky9DSmp+nwIUxAQ73rv/NrjvRNZXCaUn4G+vpcSix7jrq6DqJoLSTEqpfw3Lfejj oJ1YxqD9SrNYhXChj071zLoDznZIviCxitLbQYVLt1Y72iLUXgt+s/y3JZWuxGrt EAmIXJq8fJHhHEd0TEW9 =39+z -----END PGP SIGNATURE----- Merge tag 'powerpc-4.9-3' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux Pull powerpc fixes from Michael Ellerman: "Fixes marked for stable: - Prevent unlikely crash in copro_calculate_slb() (Frederic Barrat) - cxl: Prevent adapter reset if an active context exists (Vaibhav Jain) Fixes for code merged this cycle: - Fix boot on systems with uncompressed kernel image (Heiner Kallweit) - Drop dump_numa_memory_topology() (Michael Ellerman) - Fix numa topology console print (Aneesh Kumar K.V) - Ignore the pkey system calls for now (Stephen Rothwell)" * tag 'powerpc-4.9-3' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: powerpc: Ignore the pkey system calls for now powerpc: Fix numa topology console print powerpc/mm: Drop dump_numa_memory_topology() cxl: Prevent adapter reset if an active context exists powerpc/boot: Fix boot on systems with uncompressed kernel image powerpc/mm: Prevent unlikely crash in copro_calculate_slb()
This commit is contained in:
commit
dcd4693cf4
|
@ -220,8 +220,11 @@ What: /sys/class/cxl/<card>/reset
|
||||||
Date: October 2014
|
Date: October 2014
|
||||||
Contact: linuxppc-dev@lists.ozlabs.org
|
Contact: linuxppc-dev@lists.ozlabs.org
|
||||||
Description: write only
|
Description: write only
|
||||||
Writing 1 will issue a PERST to card which may cause the card
|
Writing 1 will issue a PERST to card provided there are no
|
||||||
to reload the FPGA depending on load_image_on_perst.
|
contexts active on any one of the card AFUs. This may cause
|
||||||
|
the card to reload the FPGA depending on load_image_on_perst.
|
||||||
|
Writing -1 will do a force PERST irrespective of any active
|
||||||
|
contexts on the card AFUs.
|
||||||
Users: https://github.com/ibm-capi/libcxl
|
Users: https://github.com/ibm-capi/libcxl
|
||||||
|
|
||||||
What: /sys/class/cxl/<card>/perst_reloads_same_image (not in a guest)
|
What: /sys/class/cxl/<card>/perst_reloads_same_image (not in a guest)
|
||||||
|
|
|
@ -32,9 +32,16 @@ static struct addr_range prep_kernel(void)
|
||||||
void *addr = 0;
|
void *addr = 0;
|
||||||
struct elf_info ei;
|
struct elf_info ei;
|
||||||
long len;
|
long len;
|
||||||
|
int uncompressed_image = 0;
|
||||||
|
|
||||||
partial_decompress(vmlinuz_addr, vmlinuz_size,
|
len = partial_decompress(vmlinuz_addr, vmlinuz_size,
|
||||||
elfheader, sizeof(elfheader), 0);
|
elfheader, sizeof(elfheader), 0);
|
||||||
|
/* assume uncompressed data if -1 is returned */
|
||||||
|
if (len == -1) {
|
||||||
|
uncompressed_image = 1;
|
||||||
|
memcpy(elfheader, vmlinuz_addr, sizeof(elfheader));
|
||||||
|
printf("No valid compressed data found, assume uncompressed data\n\r");
|
||||||
|
}
|
||||||
|
|
||||||
if (!parse_elf64(elfheader, &ei) && !parse_elf32(elfheader, &ei))
|
if (!parse_elf64(elfheader, &ei) && !parse_elf32(elfheader, &ei))
|
||||||
fatal("Error: not a valid PPC32 or PPC64 ELF file!\n\r");
|
fatal("Error: not a valid PPC32 or PPC64 ELF file!\n\r");
|
||||||
|
@ -67,6 +74,13 @@ static struct addr_range prep_kernel(void)
|
||||||
"device tree\n\r");
|
"device tree\n\r");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (uncompressed_image) {
|
||||||
|
memcpy(addr, vmlinuz_addr + ei.elfoffset, ei.loadsize);
|
||||||
|
printf("0x%lx bytes of uncompressed data copied\n\r",
|
||||||
|
ei.loadsize);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/* Finally, decompress the kernel */
|
/* Finally, decompress the kernel */
|
||||||
printf("Decompressing (0x%p <- 0x%p:0x%p)...\n\r", addr,
|
printf("Decompressing (0x%p <- 0x%p:0x%p)...\n\r", addr,
|
||||||
vmlinuz_addr, vmlinuz_addr+vmlinuz_size);
|
vmlinuz_addr, vmlinuz_addr+vmlinuz_size);
|
||||||
|
@ -82,7 +96,7 @@ static struct addr_range prep_kernel(void)
|
||||||
len, ei.loadsize);
|
len, ei.loadsize);
|
||||||
|
|
||||||
printf("Done! Decompressed 0x%lx bytes\n\r", len);
|
printf("Done! Decompressed 0x%lx bytes\n\r", len);
|
||||||
|
out:
|
||||||
flush_cache(addr, ei.loadsize);
|
flush_cache(addr, ei.loadsize);
|
||||||
|
|
||||||
return (struct addr_range){addr, ei.memsize};
|
return (struct addr_range){addr, ei.memsize};
|
||||||
|
|
|
@ -16,6 +16,10 @@
|
||||||
|
|
||||||
#define __NR__exit __NR_exit
|
#define __NR__exit __NR_exit
|
||||||
|
|
||||||
|
#define __IGNORE_pkey_mprotect
|
||||||
|
#define __IGNORE_pkey_alloc
|
||||||
|
#define __IGNORE_pkey_free
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
|
@ -106,6 +106,8 @@ int copro_calculate_slb(struct mm_struct *mm, u64 ea, struct copro_slb *slb)
|
||||||
switch (REGION_ID(ea)) {
|
switch (REGION_ID(ea)) {
|
||||||
case USER_REGION_ID:
|
case USER_REGION_ID:
|
||||||
pr_devel("%s: 0x%llx -- USER_REGION_ID\n", __func__, ea);
|
pr_devel("%s: 0x%llx -- USER_REGION_ID\n", __func__, ea);
|
||||||
|
if (mm == NULL)
|
||||||
|
return 1;
|
||||||
psize = get_slice_psize(mm, ea);
|
psize = get_slice_psize(mm, ea);
|
||||||
ssize = user_segment_size(ea);
|
ssize = user_segment_size(ea);
|
||||||
vsid = get_vsid(mm->context.id, ea, ssize);
|
vsid = get_vsid(mm->context.id, ea, ssize);
|
||||||
|
|
|
@ -845,7 +845,7 @@ void __init dump_numa_cpu_topology(void)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for_each_online_node(node) {
|
for_each_online_node(node) {
|
||||||
printk(KERN_DEBUG "Node %d CPUs:", node);
|
pr_info("Node %d CPUs:", node);
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
/*
|
/*
|
||||||
|
@ -856,52 +856,18 @@ void __init dump_numa_cpu_topology(void)
|
||||||
if (cpumask_test_cpu(cpu,
|
if (cpumask_test_cpu(cpu,
|
||||||
node_to_cpumask_map[node])) {
|
node_to_cpumask_map[node])) {
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
printk(" %u", cpu);
|
pr_cont(" %u", cpu);
|
||||||
++count;
|
++count;
|
||||||
} else {
|
} else {
|
||||||
if (count > 1)
|
if (count > 1)
|
||||||
printk("-%u", cpu - 1);
|
pr_cont("-%u", cpu - 1);
|
||||||
count = 0;
|
count = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count > 1)
|
if (count > 1)
|
||||||
printk("-%u", nr_cpu_ids - 1);
|
pr_cont("-%u", nr_cpu_ids - 1);
|
||||||
printk("\n");
|
pr_cont("\n");
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __init dump_numa_memory_topology(void)
|
|
||||||
{
|
|
||||||
unsigned int node;
|
|
||||||
unsigned int count;
|
|
||||||
|
|
||||||
if (min_common_depth == -1 || !numa_enabled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for_each_online_node(node) {
|
|
||||||
unsigned long i;
|
|
||||||
|
|
||||||
printk(KERN_DEBUG "Node %d Memory:", node);
|
|
||||||
|
|
||||||
count = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < memblock_end_of_DRAM();
|
|
||||||
i += (1 << SECTION_SIZE_BITS)) {
|
|
||||||
if (early_pfn_to_nid(i >> PAGE_SHIFT) == node) {
|
|
||||||
if (count == 0)
|
|
||||||
printk(" 0x%lx", i);
|
|
||||||
++count;
|
|
||||||
} else {
|
|
||||||
if (count > 0)
|
|
||||||
printk("-0x%lx", i);
|
|
||||||
count = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count > 0)
|
|
||||||
printk("-0x%lx", i);
|
|
||||||
printk("\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -947,8 +913,6 @@ void __init initmem_init(void)
|
||||||
|
|
||||||
if (parse_numa_properties())
|
if (parse_numa_properties())
|
||||||
setup_nonnuma();
|
setup_nonnuma();
|
||||||
else
|
|
||||||
dump_numa_memory_topology();
|
|
||||||
|
|
||||||
memblock_dump_all();
|
memblock_dump_all();
|
||||||
|
|
||||||
|
|
|
@ -229,6 +229,14 @@ int cxl_start_context(struct cxl_context *ctx, u64 wed,
|
||||||
if (ctx->status == STARTED)
|
if (ctx->status == STARTED)
|
||||||
goto out; /* already started */
|
goto out; /* already started */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Increment the mapped context count for adapter. This also checks
|
||||||
|
* if adapter_context_lock is taken.
|
||||||
|
*/
|
||||||
|
rc = cxl_adapter_context_get(ctx->afu->adapter);
|
||||||
|
if (rc)
|
||||||
|
goto out;
|
||||||
|
|
||||||
if (task) {
|
if (task) {
|
||||||
ctx->pid = get_task_pid(task, PIDTYPE_PID);
|
ctx->pid = get_task_pid(task, PIDTYPE_PID);
|
||||||
ctx->glpid = get_task_pid(task->group_leader, PIDTYPE_PID);
|
ctx->glpid = get_task_pid(task->group_leader, PIDTYPE_PID);
|
||||||
|
@ -240,6 +248,7 @@ int cxl_start_context(struct cxl_context *ctx, u64 wed,
|
||||||
|
|
||||||
if ((rc = cxl_ops->attach_process(ctx, kernel, wed, 0))) {
|
if ((rc = cxl_ops->attach_process(ctx, kernel, wed, 0))) {
|
||||||
put_pid(ctx->pid);
|
put_pid(ctx->pid);
|
||||||
|
cxl_adapter_context_put(ctx->afu->adapter);
|
||||||
cxl_ctx_put();
|
cxl_ctx_put();
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
|
@ -238,6 +238,9 @@ int __detach_context(struct cxl_context *ctx)
|
||||||
put_pid(ctx->glpid);
|
put_pid(ctx->glpid);
|
||||||
|
|
||||||
cxl_ctx_put();
|
cxl_ctx_put();
|
||||||
|
|
||||||
|
/* Decrease the attached context count on the adapter */
|
||||||
|
cxl_adapter_context_put(ctx->afu->adapter);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -618,6 +618,14 @@ struct cxl {
|
||||||
bool perst_select_user;
|
bool perst_select_user;
|
||||||
bool perst_same_image;
|
bool perst_same_image;
|
||||||
bool psl_timebase_synced;
|
bool psl_timebase_synced;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* number of contexts mapped on to this card. Possible values are:
|
||||||
|
* >0: Number of contexts mapped and new one can be mapped.
|
||||||
|
* 0: No active contexts and new ones can be mapped.
|
||||||
|
* -1: No contexts mapped and new ones cannot be mapped.
|
||||||
|
*/
|
||||||
|
atomic_t contexts_num;
|
||||||
};
|
};
|
||||||
|
|
||||||
int cxl_pci_alloc_one_irq(struct cxl *adapter);
|
int cxl_pci_alloc_one_irq(struct cxl *adapter);
|
||||||
|
@ -944,4 +952,20 @@ bool cxl_pci_is_vphb_device(struct pci_dev *dev);
|
||||||
|
|
||||||
/* decode AFU error bits in the PSL register PSL_SERR_An */
|
/* decode AFU error bits in the PSL register PSL_SERR_An */
|
||||||
void cxl_afu_decode_psl_serr(struct cxl_afu *afu, u64 serr);
|
void cxl_afu_decode_psl_serr(struct cxl_afu *afu, u64 serr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Increments the number of attached contexts on an adapter.
|
||||||
|
* In case an adapter_context_lock is taken the return -EBUSY.
|
||||||
|
*/
|
||||||
|
int cxl_adapter_context_get(struct cxl *adapter);
|
||||||
|
|
||||||
|
/* Decrements the number of attached contexts on an adapter */
|
||||||
|
void cxl_adapter_context_put(struct cxl *adapter);
|
||||||
|
|
||||||
|
/* If no active contexts then prevents contexts from being attached */
|
||||||
|
int cxl_adapter_context_lock(struct cxl *adapter);
|
||||||
|
|
||||||
|
/* Unlock the contexts-lock if taken. Warn and force unlock otherwise */
|
||||||
|
void cxl_adapter_context_unlock(struct cxl *adapter);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -205,11 +205,22 @@ static long afu_ioctl_start_work(struct cxl_context *ctx,
|
||||||
ctx->pid = get_task_pid(current, PIDTYPE_PID);
|
ctx->pid = get_task_pid(current, PIDTYPE_PID);
|
||||||
ctx->glpid = get_task_pid(current->group_leader, PIDTYPE_PID);
|
ctx->glpid = get_task_pid(current->group_leader, PIDTYPE_PID);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Increment the mapped context count for adapter. This also checks
|
||||||
|
* if adapter_context_lock is taken.
|
||||||
|
*/
|
||||||
|
rc = cxl_adapter_context_get(ctx->afu->adapter);
|
||||||
|
if (rc) {
|
||||||
|
afu_release_irqs(ctx, ctx);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
trace_cxl_attach(ctx, work.work_element_descriptor, work.num_interrupts, amr);
|
trace_cxl_attach(ctx, work.work_element_descriptor, work.num_interrupts, amr);
|
||||||
|
|
||||||
if ((rc = cxl_ops->attach_process(ctx, false, work.work_element_descriptor,
|
if ((rc = cxl_ops->attach_process(ctx, false, work.work_element_descriptor,
|
||||||
amr))) {
|
amr))) {
|
||||||
afu_release_irqs(ctx, ctx);
|
afu_release_irqs(ctx, ctx);
|
||||||
|
cxl_adapter_context_put(ctx->afu->adapter);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1152,6 +1152,9 @@ struct cxl *cxl_guest_init_adapter(struct device_node *np, struct platform_devic
|
||||||
if ((rc = cxl_sysfs_adapter_add(adapter)))
|
if ((rc = cxl_sysfs_adapter_add(adapter)))
|
||||||
goto err_put1;
|
goto err_put1;
|
||||||
|
|
||||||
|
/* release the context lock as the adapter is configured */
|
||||||
|
cxl_adapter_context_unlock(adapter);
|
||||||
|
|
||||||
return adapter;
|
return adapter;
|
||||||
|
|
||||||
err_put1:
|
err_put1:
|
||||||
|
|
|
@ -243,8 +243,10 @@ struct cxl *cxl_alloc_adapter(void)
|
||||||
if (dev_set_name(&adapter->dev, "card%i", adapter->adapter_num))
|
if (dev_set_name(&adapter->dev, "card%i", adapter->adapter_num))
|
||||||
goto err2;
|
goto err2;
|
||||||
|
|
||||||
return adapter;
|
/* start with context lock taken */
|
||||||
|
atomic_set(&adapter->contexts_num, -1);
|
||||||
|
|
||||||
|
return adapter;
|
||||||
err2:
|
err2:
|
||||||
cxl_remove_adapter_nr(adapter);
|
cxl_remove_adapter_nr(adapter);
|
||||||
err1:
|
err1:
|
||||||
|
@ -286,6 +288,44 @@ int cxl_afu_select_best_mode(struct cxl_afu *afu)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int cxl_adapter_context_get(struct cxl *adapter)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = atomic_inc_unless_negative(&adapter->contexts_num);
|
||||||
|
return rc >= 0 ? 0 : -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cxl_adapter_context_put(struct cxl *adapter)
|
||||||
|
{
|
||||||
|
atomic_dec_if_positive(&adapter->contexts_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cxl_adapter_context_lock(struct cxl *adapter)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
/* no active contexts -> contexts_num == 0 */
|
||||||
|
rc = atomic_cmpxchg(&adapter->contexts_num, 0, -1);
|
||||||
|
return rc ? -EBUSY : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cxl_adapter_context_unlock(struct cxl *adapter)
|
||||||
|
{
|
||||||
|
int val = atomic_cmpxchg(&adapter->contexts_num, -1, 0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* contexts lock taken -> contexts_num == -1
|
||||||
|
* If not true then show a warning and force reset the lock.
|
||||||
|
* This will happen when context_unlock was requested without
|
||||||
|
* doing a context_lock.
|
||||||
|
*/
|
||||||
|
if (val != -1) {
|
||||||
|
atomic_set(&adapter->contexts_num, 0);
|
||||||
|
WARN(1, "Adapter context unlocked with %d active contexts",
|
||||||
|
val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int __init init_cxl(void)
|
static int __init init_cxl(void)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
|
@ -1487,6 +1487,8 @@ static int cxl_configure_adapter(struct cxl *adapter, struct pci_dev *dev)
|
||||||
if ((rc = cxl_native_register_psl_err_irq(adapter)))
|
if ((rc = cxl_native_register_psl_err_irq(adapter)))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
/* Release the context lock as adapter is configured */
|
||||||
|
cxl_adapter_context_unlock(adapter);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
|
|
@ -75,12 +75,31 @@ static ssize_t reset_adapter_store(struct device *device,
|
||||||
int val;
|
int val;
|
||||||
|
|
||||||
rc = sscanf(buf, "%i", &val);
|
rc = sscanf(buf, "%i", &val);
|
||||||
if ((rc != 1) || (val != 1))
|
if ((rc != 1) || (val != 1 && val != -1))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if ((rc = cxl_ops->adapter_reset(adapter)))
|
/*
|
||||||
return rc;
|
* See if we can lock the context mapping that's only allowed
|
||||||
return count;
|
* when there are no contexts attached to the adapter. Once
|
||||||
|
* taken this will also prevent any context from getting activated.
|
||||||
|
*/
|
||||||
|
if (val == 1) {
|
||||||
|
rc = cxl_adapter_context_lock(adapter);
|
||||||
|
if (rc)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
rc = cxl_ops->adapter_reset(adapter);
|
||||||
|
/* In case reset failed release context lock */
|
||||||
|
if (rc)
|
||||||
|
cxl_adapter_context_unlock(adapter);
|
||||||
|
|
||||||
|
} else if (val == -1) {
|
||||||
|
/* Perform a forced adapter reset */
|
||||||
|
rc = cxl_ops->adapter_reset(adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
return rc ? rc : count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t load_image_on_perst_show(struct device *device,
|
static ssize_t load_image_on_perst_show(struct device *device,
|
||||||
|
|
Loading…
Reference in New Issue