summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/include/asm/entry-common.h12
-rw-r--r--arch/powerpc/kernel/eeh_driver.c2
-rw-r--r--arch/powerpc/kernel/interrupt.c2
-rw-r--r--arch/powerpc/kernel/rtas_pci.c8
-rw-r--r--arch/powerpc/kernel/syscall.c4
-rw-r--r--arch/powerpc/kexec/file_load_64.c10
-rw-r--r--arch/powerpc/platforms/powernv/pci-ioda.c6
-rw-r--r--arch/powerpc/platforms/ps3/repository.c5
-rw-r--r--arch/powerpc/platforms/pseries/pci.c13
9 files changed, 38 insertions, 24 deletions
diff --git a/arch/powerpc/include/asm/entry-common.h b/arch/powerpc/include/asm/entry-common.h
index c5adb5006361..80b07750b531 100644
--- a/arch/powerpc/include/asm/entry-common.h
+++ b/arch/powerpc/include/asm/entry-common.h
@@ -270,7 +270,7 @@ static inline void arch_interrupt_exit_prepare(struct pt_regs *regs)
}
/* irqentry_exit expects to be called with interrupts disabled */
- local_irq_disable();
+ hard_irq_disable();
}
static inline void arch_interrupt_async_enter_prepare(struct pt_regs *regs)
@@ -515,8 +515,14 @@ static inline void arch_exit_to_user_mode_prepare(struct pt_regs *regs,
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
local_paca->tm_scratch = regs->msr;
#endif
- /* Restore user access locks last */
- kuap_user_restore(regs);
+ /*
+ * Do not restore KUAP here. Generic entry might treat this as the last
+ * arch step before userspace but PowerPC still has kernel work after
+ * irqentry_exit()/syscall_exit_to_user_mode() i.e. in
+ * interrupt_exit_user_prepare() / syscall_exit_prepare() may enable
+ * IRQs and retry. Those functions restore KUAP immediately before rfi,
+ * which is where it should belong.
+ */
}
#define arch_exit_to_user_mode_prepare arch_exit_to_user_mode_prepare
diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c
index 028f69158532..d64cce17a4e0 100644
--- a/arch/powerpc/kernel/eeh_driver.c
+++ b/arch/powerpc/kernel/eeh_driver.c
@@ -533,9 +533,7 @@ static void eeh_rmv_device(struct eeh_dev *edev, void *userdata)
if (rmv_data)
list_add(&edev->rmv_entry, &rmv_data->removed_vf_list);
} else {
- pci_lock_rescan_remove();
pci_stop_and_remove_bus_device(dev);
- pci_unlock_rescan_remove();
}
}
diff --git a/arch/powerpc/kernel/interrupt.c b/arch/powerpc/kernel/interrupt.c
index 5b88bf72786c..55f9c0c9922a 100644
--- a/arch/powerpc/kernel/interrupt.c
+++ b/arch/powerpc/kernel/interrupt.c
@@ -175,7 +175,7 @@ again:
current_thread_info()->exit_flags &= ~_TIF_RESTOREALL;
regs->exit_result |= ret;
- return ret;
+ return regs->exit_result;
}
#endif
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c
index fccf96e897f6..206c825225c2 100644
--- a/arch/powerpc/kernel/rtas_pci.c
+++ b/arch/powerpc/kernel/rtas_pci.c
@@ -54,6 +54,10 @@ int rtas_pci_dn_read_config(struct pci_dn *pdn, int where, int size, u32 *val)
if (!config_access_valid(pdn, where))
return PCIBIOS_BAD_REGISTER_NUMBER;
#ifdef CONFIG_EEH
+ if (pdn->edev &&
+ (pdn->edev->mode & EEH_DEV_REMOVED))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
if (pdn->edev && pdn->edev->pe &&
(pdn->edev->pe->state & EEH_PE_CFG_BLOCKED))
return PCIBIOS_SET_FAILED;
@@ -105,6 +109,10 @@ int rtas_pci_dn_write_config(struct pci_dn *pdn, int where, int size, u32 val)
if (!config_access_valid(pdn, where))
return PCIBIOS_BAD_REGISTER_NUMBER;
#ifdef CONFIG_EEH
+ if (pdn->edev &&
+ (pdn->edev->mode & EEH_DEV_REMOVED))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
if (pdn->edev && pdn->edev->pe &&
(pdn->edev->pe->state & EEH_PE_CFG_BLOCKED))
return PCIBIOS_SET_FAILED;
diff --git a/arch/powerpc/kernel/syscall.c b/arch/powerpc/kernel/syscall.c
index 4916c205c4bb..fbefe1927b10 100644
--- a/arch/powerpc/kernel/syscall.c
+++ b/arch/powerpc/kernel/syscall.c
@@ -18,8 +18,10 @@ notrace long system_call_exception(struct pt_regs *regs, unsigned long r0)
long ret;
syscall_fn f;
- if (unlikely(!syscall_enter_from_user_mode_randomize_stack(regs, &r0)))
+ if (unlikely(!syscall_enter_from_user_mode_randomize_stack(regs, &r0))) {
+ clear_thread_flag(TIF_SYSCALL_RET);
return syscall_get_error(current, regs);
+ }
if (unlikely(test_and_clear_thread_flag(TIF_SYSCALL_RET)))
return syscall_get_error(current, regs);
diff --git a/arch/powerpc/kexec/file_load_64.c b/arch/powerpc/kexec/file_load_64.c
index 6075b1c88511..bd80c5fb1b1f 100644
--- a/arch/powerpc/kexec/file_load_64.c
+++ b/arch/powerpc/kexec/file_load_64.c
@@ -57,7 +57,7 @@ int arch_check_excluded_range(struct kimage *image, unsigned long start,
emem = image->arch.exclude_ranges;
for (i = 0; i < emem->nr_ranges; i++)
- if (start < emem->ranges[i].end && end > emem->ranges[i].start)
+ if (start <= emem->ranges[i].end && end >= emem->ranges[i].start)
return 1;
return 0;
@@ -113,7 +113,7 @@ static int add_usable_mem(struct umem_info *um_info, u64 base, u64 end)
loc_end = um_info->ranges[i].end;
if (loc_base >= base && loc_end <= end)
add = true;
- else if (base < loc_end && end > loc_base) {
+ else if (base <= loc_end && end >= loc_base) {
if (loc_base < base)
loc_base = base;
if (loc_end > end)
@@ -377,16 +377,12 @@ static int load_backup_segment(struct kimage *image, struct kexec_buf *kbuf)
static unsigned int kdump_extra_elfcorehdr_size(struct crash_mem *cmem)
{
#if defined(CONFIG_CRASH_HOTPLUG) && defined(CONFIG_MEMORY_HOTPLUG)
- unsigned int extra_sz = 0;
-
if (CONFIG_CRASH_MAX_MEMORY_RANGES > (unsigned int)PN_XNUM)
pr_warn("Number of Phdrs %u exceeds max\n", CONFIG_CRASH_MAX_MEMORY_RANGES);
else if (cmem->nr_ranges >= CONFIG_CRASH_MAX_MEMORY_RANGES)
pr_warn("Configured crash mem ranges may not be enough\n");
else
- extra_sz = (CONFIG_CRASH_MAX_MEMORY_RANGES - cmem->nr_ranges) * sizeof(Elf64_Phdr);
-
- return extra_sz;
+ return (CONFIG_CRASH_MAX_MEMORY_RANGES - cmem->nr_ranges) * sizeof(Elf64_Phdr);
#endif
return 0;
}
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index 32ecbc46e74b..728a5610d167 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -1623,15 +1623,13 @@ int64_t pnv_opal_pci_msi_eoi(struct irq_data *d)
return opal_pci_msi_eoi(phb->opal_id, d->parent_data->hwirq);
}
-static struct irq_chip pnv_pci_msi_irq_chip;
-
/*
* Returns true iff chip is something that we could call
* pnv_opal_pci_msi_eoi for.
*/
bool is_pnv_opal_msi(struct irq_chip *chip)
{
- return chip == &pnv_pci_msi_irq_chip;
+ return chip && chip->name && str_has_prefix(chip->name, "PNV-");
}
EXPORT_SYMBOL_GPL(is_pnv_opal_msi);
@@ -1728,7 +1726,7 @@ static const struct msi_parent_ops pnv_msi_parent_ops = {
.chip_flags = MSI_CHIP_FLAG_SET_EOI,
.bus_select_token = DOMAIN_BUS_NEXUS,
.bus_select_mask = MATCH_PCI_MSI,
- .prefix = "PNV-",
+ .prefix = "PNV-", /* Note: is_pnv_opal_msi() uses this */
.init_dev_msi_info = pnv_init_dev_msi_info,
};
diff --git a/arch/powerpc/platforms/ps3/repository.c b/arch/powerpc/platforms/ps3/repository.c
index b8c030eab138..0cc755ac3e7f 100644
--- a/arch/powerpc/platforms/ps3/repository.c
+++ b/arch/powerpc/platforms/ps3/repository.c
@@ -6,6 +6,8 @@
* Copyright 2006 Sony Corp.
*/
+#include <linux/minmax.h>
+
#include <asm/lv1call.h>
#include "platform.h"
@@ -74,8 +76,9 @@ static void _dump_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4,
static u64 make_first_field(const char *text, u64 index)
{
u64 n = 0;
+ size_t len = min(strlen(text), sizeof(n));
- memcpy((char *)&n, text, strnlen(text, sizeof(n)));
+ memcpy(&n, text, len);
return PS3_VENDOR_ID_NONE + (n >> 32) + index;
}
diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c
index d11a64a086c1..6fc13f4a79a3 100644
--- a/arch/powerpc/platforms/pseries/pci.c
+++ b/arch/powerpc/platforms/pseries/pci.c
@@ -132,11 +132,14 @@ static int pseries_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs)
/* First integer stores max config */
max_config_vfs = of_read_number(&max_vfs[0], 1);
- if (max_config_vfs < num_vfs || num_vfs > MAX_VFS_FOR_MAP_PE) {
- dev_err(&pdev->dev,
- "Num VFs %x > %x Configurable VFs\n",
- num_vfs, (num_vfs > MAX_VFS_FOR_MAP_PE) ?
- MAX_VFS_FOR_MAP_PE : max_config_vfs);
+ if (max_config_vfs < num_vfs) {
+ dev_err(&pdev->dev, "Num VFs %x > %x Configurable VFs\n",
+ num_vfs, max_config_vfs);
+ return -EINVAL;
+ }
+ if (num_vfs > MAX_VFS_FOR_MAP_PE) {
+ dev_err(&pdev->dev, "Num VFs %x > %x PE mapping limit\n",
+ num_vfs, MAX_VFS_FOR_MAP_PE);
return -EINVAL;
}