powerpc fixes for 4.2
- opal-prd mmap fix from Vaidy. - Set kernel taint for MCEs from Daniel. - Alignment exception description from Anton. - ppc4xx_hsta_msi build fix from Daniel - opal-elog interrupt fix from Alistair. - core_idle_state race fix from Shreyas. - hv-24x7 lockdep fix from Sukadev. - Multiple cxl fixes from Daniel, Ian, Mikey & Maninder. - Update MAINTAINERS to point at shared tree. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJVn3eKAAoJEFHr6jzI4aWAPCAP/3ORZnylGUJGlR7GMtktn7vm XJyagXcFbtBYDz8HJUtDESwjCGd/mSOErBZaOEBWgv3qWf60VJzAnzQTgKvIWU1j 4WXILIQivb9ibajUN5SkghgSgwekc7VqJnnlA2BfVTMtZiuD5DQqMWs4Mc/jIREU 41g/Fc1vCiXW7dwFAxtvH14kBGCmkU+Fd/z9bDlOeLVAyDlqEl/dCdtjyRpipHSd nzAea2s9bwH6QYNSZKjtnTbJAelrg/ZG8CHSkr3UGTf/ak/YouPqzWp4aJcRmWe3 GMCeC+93fCQ4bOuzQolgdYHPbMQa/sil+3RLuipPETLV+dbqhtMb/NLxqcihyKuE V8Sk7PsIPtveCbCOyvQTM3RrUtg7oOYPgraXrKtICx3n05vkVNI+Q/3uCWwmic42 396KR9lcdpn3TDl6+MgJsWvKCxM0DX4dsFMQwjoXwi2Evd0EpMDfxIVBnCwzcRBw WNILcGT+uupfKrrROdC7NNmgevAK0mRWX5NeguRIk8AEe2ywaKZ2cBGhxte7669P Y98OuNtHhv4Pvhni0uRB0UTFaxjkSTZqJzUHXAl9xfRPlD1i+UVTdEAaRxN6yyn0 r7c5b0o1fTiM/Nxvh6WL9rBV10XhJ0XerKqO4PU3zW9olZKG7ZUqFF/qsXklljAc FNJN31RCIgtctO+iLe5e =+CJX -----END PGP SIGNATURE----- Merge tag 'powerpc-4.2-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux Pull powerpc fixes from Michael Ellerman: - opal-prd mmap fix from Vaidy - set kernel taint for MCEs from Daniel - alignment exception description from Anton - ppc4xx_hsta_msi build fix from Daniel - opal-elog interrupt fix from Alistair - core_idle_state race fix from Shreyas - hv-24x7 lockdep fix from Sukadev - multiple cxl fixes from Daniel, Ian, Mikey & Maninder - update MAINTAINERS to point at shared tree * tag 'powerpc-4.2-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: cxl: Check if afu is not null in cxl_slbia powerpc: Update MAINTAINERS to point at shared tree powerpc/perf/24x7: Fix lockdep warning cxl: Fix off by one error allowing subsequent mmap page to be accessed cxl: Fail mmap if requested mapping is larger than assigned problem state area cxl: Fix refcounting in kernel API powerpc/powernv: Fix race in updating core_idle_state powerpc/powernv: Fix opal-elog interrupt handler powerpc/ppc4xx_hsta_msi: Include ppc-pci.h to fix reference to hose_list powerpc: Add plain English description for alignment exception oopses cxl: Test the correct mmio space before unmapping powerpc: Set the correct kernel taint on machine check errors cxl/vphb.c: Use phb pointer after NULL check powerpc/powernv: Fix vma page prot flags in opal-prd driver
This commit is contained in:
commit
3cdeb9d151
13 changed files with 60 additions and 40 deletions
|
@ -6173,7 +6173,7 @@ M: Michael Ellerman <mpe@ellerman.id.au>
|
|||
W: http://www.penguinppc.org/
|
||||
L: linuxppc-dev@lists.ozlabs.org
|
||||
Q: http://patchwork.ozlabs.org/project/linuxppc-dev/list/
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git
|
||||
S: Supported
|
||||
F: Documentation/powerpc/
|
||||
F: arch/powerpc/
|
||||
|
|
|
@ -51,6 +51,22 @@
|
|||
|
||||
.text
|
||||
|
||||
/*
|
||||
* Used by threads when the lock bit of core_idle_state is set.
|
||||
* Threads will spin in HMT_LOW until the lock bit is cleared.
|
||||
* r14 - pointer to core_idle_state
|
||||
* r15 - used to load contents of core_idle_state
|
||||
*/
|
||||
|
||||
core_idle_lock_held:
|
||||
HMT_LOW
|
||||
3: lwz r15,0(r14)
|
||||
andi. r15,r15,PNV_CORE_IDLE_LOCK_BIT
|
||||
bne 3b
|
||||
HMT_MEDIUM
|
||||
lwarx r15,0,r14
|
||||
blr
|
||||
|
||||
/*
|
||||
* Pass requested state in r3:
|
||||
* r3 - PNV_THREAD_NAP/SLEEP/WINKLE
|
||||
|
@ -150,6 +166,10 @@ power7_enter_nap_mode:
|
|||
ld r14,PACA_CORE_IDLE_STATE_PTR(r13)
|
||||
lwarx_loop1:
|
||||
lwarx r15,0,r14
|
||||
|
||||
andi. r9,r15,PNV_CORE_IDLE_LOCK_BIT
|
||||
bnel core_idle_lock_held
|
||||
|
||||
andc r15,r15,r7 /* Clear thread bit */
|
||||
|
||||
andi. r15,r15,PNV_CORE_IDLE_THREAD_BITS
|
||||
|
@ -294,7 +314,7 @@ lwarx_loop2:
|
|||
* workaround undo code or resyncing timebase or restoring context
|
||||
* In either case loop until the lock bit is cleared.
|
||||
*/
|
||||
bne core_idle_lock_held
|
||||
bnel core_idle_lock_held
|
||||
|
||||
cmpwi cr2,r15,0
|
||||
lbz r4,PACA_SUBCORE_SIBLING_MASK(r13)
|
||||
|
@ -319,15 +339,6 @@ lwarx_loop2:
|
|||
isync
|
||||
b common_exit
|
||||
|
||||
core_idle_lock_held:
|
||||
HMT_LOW
|
||||
core_idle_lock_loop:
|
||||
lwz r15,0(14)
|
||||
andi. r9,r15,PNV_CORE_IDLE_LOCK_BIT
|
||||
bne core_idle_lock_loop
|
||||
HMT_MEDIUM
|
||||
b lwarx_loop2
|
||||
|
||||
first_thread_in_subcore:
|
||||
/* First thread in subcore to wakeup */
|
||||
ori r15,r15,PNV_CORE_IDLE_LOCK_BIT
|
||||
|
|
|
@ -297,6 +297,8 @@ long machine_check_early(struct pt_regs *regs)
|
|||
|
||||
__this_cpu_inc(irq_stat.mce_exceptions);
|
||||
|
||||
add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE);
|
||||
|
||||
if (cur_cpu_spec && cur_cpu_spec->machine_check_early)
|
||||
handled = cur_cpu_spec->machine_check_early(regs);
|
||||
return handled;
|
||||
|
|
|
@ -529,6 +529,10 @@ void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
|
|||
printk(KERN_ALERT "Unable to handle kernel paging request for "
|
||||
"instruction fetch\n");
|
||||
break;
|
||||
case 0x600:
|
||||
printk(KERN_ALERT "Unable to handle kernel paging request for "
|
||||
"unaligned access at address 0x%08lx\n", regs->dar);
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ALERT "Unable to handle kernel paging request for "
|
||||
"unknown fault\n");
|
||||
|
|
|
@ -320,6 +320,8 @@ static struct attribute *device_str_attr_create_(char *name, char *str)
|
|||
if (!attr)
|
||||
return NULL;
|
||||
|
||||
sysfs_attr_init(&attr->attr.attr);
|
||||
|
||||
attr->var = str;
|
||||
attr->attr.attr.name = name;
|
||||
attr->attr.attr.mode = 0444;
|
||||
|
|
|
@ -237,7 +237,7 @@ static struct elog_obj *create_elog_obj(uint64_t id, size_t size, uint64_t type)
|
|||
return elog;
|
||||
}
|
||||
|
||||
static void elog_work_fn(struct work_struct *work)
|
||||
static irqreturn_t elog_event(int irq, void *data)
|
||||
{
|
||||
__be64 size;
|
||||
__be64 id;
|
||||
|
@ -251,7 +251,7 @@ static void elog_work_fn(struct work_struct *work)
|
|||
rc = opal_get_elog_size(&id, &size, &type);
|
||||
if (rc != OPAL_SUCCESS) {
|
||||
pr_err("ELOG: OPAL log info read failed\n");
|
||||
return;
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
elog_size = be64_to_cpu(size);
|
||||
|
@ -270,16 +270,10 @@ static void elog_work_fn(struct work_struct *work)
|
|||
* entries.
|
||||
*/
|
||||
if (kset_find_obj(elog_kset, name))
|
||||
return;
|
||||
return IRQ_HANDLED;
|
||||
|
||||
create_elog_obj(log_id, elog_size, elog_type);
|
||||
}
|
||||
|
||||
static DECLARE_WORK(elog_work, elog_work_fn);
|
||||
|
||||
static irqreturn_t elog_event(int irq, void *data)
|
||||
{
|
||||
schedule_work(&elog_work);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
@ -304,8 +298,8 @@ int __init opal_elog_init(void)
|
|||
return irq;
|
||||
}
|
||||
|
||||
rc = request_irq(irq, elog_event,
|
||||
IRQ_TYPE_LEVEL_HIGH, "opal-elog", NULL);
|
||||
rc = request_threaded_irq(irq, NULL, elog_event,
|
||||
IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "opal-elog", NULL);
|
||||
if (rc) {
|
||||
pr_err("%s: Can't request OPAL event irq (%d)\n",
|
||||
__func__, rc);
|
||||
|
|
|
@ -112,6 +112,7 @@ static int opal_prd_open(struct inode *inode, struct file *file)
|
|||
static int opal_prd_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
{
|
||||
size_t addr, size;
|
||||
pgprot_t page_prot;
|
||||
int rc;
|
||||
|
||||
pr_devel("opal_prd_mmap(0x%016lx, 0x%016lx, 0x%lx, 0x%lx)\n",
|
||||
|
@ -125,13 +126,11 @@ static int opal_prd_mmap(struct file *file, struct vm_area_struct *vma)
|
|||
if (!opal_prd_range_is_valid(addr, size))
|
||||
return -EINVAL;
|
||||
|
||||
vma->vm_page_prot = __pgprot(pgprot_val(phys_mem_access_prot(file,
|
||||
vma->vm_pgoff,
|
||||
size, vma->vm_page_prot))
|
||||
| _PAGE_SPECIAL);
|
||||
page_prot = phys_mem_access_prot(file, vma->vm_pgoff,
|
||||
size, vma->vm_page_prot);
|
||||
|
||||
rc = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, size,
|
||||
vma->vm_page_prot);
|
||||
page_prot);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <asm/msi_bitmap.h>
|
||||
#include <asm/ppc-pci.h>
|
||||
|
||||
struct ppc4xx_hsta_msi {
|
||||
struct device *dev;
|
||||
|
|
|
@ -23,6 +23,7 @@ struct cxl_context *cxl_dev_context_init(struct pci_dev *dev)
|
|||
|
||||
afu = cxl_pci_to_afu(dev);
|
||||
|
||||
get_device(&afu->dev);
|
||||
ctx = cxl_context_alloc();
|
||||
if (IS_ERR(ctx))
|
||||
return ctx;
|
||||
|
@ -31,6 +32,7 @@ struct cxl_context *cxl_dev_context_init(struct pci_dev *dev)
|
|||
rc = cxl_context_init(ctx, afu, false, NULL);
|
||||
if (rc) {
|
||||
kfree(ctx);
|
||||
put_device(&afu->dev);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
cxl_assign_psn_space(ctx);
|
||||
|
@ -60,6 +62,8 @@ int cxl_release_context(struct cxl_context *ctx)
|
|||
if (ctx->status != CLOSED)
|
||||
return -EBUSY;
|
||||
|
||||
put_device(&ctx->afu->dev);
|
||||
|
||||
cxl_context_free(ctx);
|
||||
|
||||
return 0;
|
||||
|
@ -159,7 +163,6 @@ int cxl_start_context(struct cxl_context *ctx, u64 wed,
|
|||
}
|
||||
|
||||
ctx->status = STARTED;
|
||||
get_device(&ctx->afu->dev);
|
||||
out:
|
||||
mutex_unlock(&ctx->status_mutex);
|
||||
return rc;
|
||||
|
@ -175,12 +178,7 @@ EXPORT_SYMBOL_GPL(cxl_process_element);
|
|||
/* Stop a context. Returns 0 on success, otherwise -Errno */
|
||||
int cxl_stop_context(struct cxl_context *ctx)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = __detach_context(ctx);
|
||||
if (!rc)
|
||||
put_device(&ctx->afu->dev);
|
||||
return rc;
|
||||
return __detach_context(ctx);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cxl_stop_context);
|
||||
|
||||
|
|
|
@ -113,11 +113,11 @@ static int cxl_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
|
|||
|
||||
if (ctx->afu->current_mode == CXL_MODE_DEDICATED) {
|
||||
area = ctx->afu->psn_phys;
|
||||
if (offset > ctx->afu->adapter->ps_size)
|
||||
if (offset >= ctx->afu->adapter->ps_size)
|
||||
return VM_FAULT_SIGBUS;
|
||||
} else {
|
||||
area = ctx->psn_phys;
|
||||
if (offset > ctx->psn_size)
|
||||
if (offset >= ctx->psn_size)
|
||||
return VM_FAULT_SIGBUS;
|
||||
}
|
||||
|
||||
|
@ -145,8 +145,16 @@ static const struct vm_operations_struct cxl_mmap_vmops = {
|
|||
*/
|
||||
int cxl_context_iomap(struct cxl_context *ctx, struct vm_area_struct *vma)
|
||||
{
|
||||
u64 start = vma->vm_pgoff << PAGE_SHIFT;
|
||||
u64 len = vma->vm_end - vma->vm_start;
|
||||
len = min(len, ctx->psn_size);
|
||||
|
||||
if (ctx->afu->current_mode == CXL_MODE_DEDICATED) {
|
||||
if (start + len > ctx->afu->adapter->ps_size)
|
||||
return -EINVAL;
|
||||
} else {
|
||||
if (start + len > ctx->psn_size)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ctx->afu->current_mode != CXL_MODE_DEDICATED) {
|
||||
/* make sure there is a valid per process space for this AFU */
|
||||
|
|
|
@ -73,7 +73,7 @@ static inline void cxl_slbia_core(struct mm_struct *mm)
|
|||
spin_lock(&adapter->afu_list_lock);
|
||||
for (slice = 0; slice < adapter->slices; slice++) {
|
||||
afu = adapter->afu[slice];
|
||||
if (!afu->enabled)
|
||||
if (!afu || !afu->enabled)
|
||||
continue;
|
||||
rcu_read_lock();
|
||||
idr_for_each_entry(&afu->contexts_idr, ctx, id)
|
||||
|
|
|
@ -539,7 +539,7 @@ static int cxl_map_slice_regs(struct cxl_afu *afu, struct cxl *adapter, struct p
|
|||
|
||||
static void cxl_unmap_slice_regs(struct cxl_afu *afu)
|
||||
{
|
||||
if (afu->p1n_mmio)
|
||||
if (afu->p2n_mmio)
|
||||
iounmap(afu->p2n_mmio);
|
||||
if (afu->p1n_mmio)
|
||||
iounmap(afu->p1n_mmio);
|
||||
|
|
|
@ -112,9 +112,10 @@ static int cxl_pcie_config_info(struct pci_bus *bus, unsigned int devfn,
|
|||
unsigned long addr;
|
||||
|
||||
phb = pci_bus_to_host(bus);
|
||||
afu = (struct cxl_afu *)phb->private_data;
|
||||
if (phb == NULL)
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
afu = (struct cxl_afu *)phb->private_data;
|
||||
|
||||
if (cxl_pcie_cfg_record(bus->number, devfn) > afu->crs_num)
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
if (offset >= (unsigned long)phb->cfg_data)
|
||||
|
|
Loading…
Reference in a new issue