summaryrefslogtreecommitdiff
path: root/arch/powerpc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/kernel/prom_init.c58
-rw-r--r--arch/powerpc/kernel/signal_32.c11
-rw-r--r--arch/powerpc/kernel/signal_64.c2
-rw-r--r--arch/powerpc/mm/hash_native_64.c4
-rw-r--r--arch/powerpc/platforms/cell/setup.c11
-rw-r--r--arch/powerpc/platforms/powermac/low_i2c.c12
-rw-r--r--arch/powerpc/platforms/powermac/pfunc_core.c18
-rw-r--r--arch/powerpc/platforms/powermac/setup.c12
-rw-r--r--arch/powerpc/platforms/pseries/setup.c8
9 files changed, 117 insertions, 19 deletions
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 2d80653aa2af..f70bd090dacd 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -822,6 +822,7 @@ static void __init prom_send_capabilities(void)
/* try calling the ibm,client-architecture-support method */
if (call_prom_ret("call-method", 3, 2, &ret,
ADDR("ibm,client-architecture-support"),
+ root,
ADDR(ibm_architecture_vec)) == 0) {
/* the call exists... */
if (ret)
@@ -1622,6 +1623,15 @@ static int __init prom_find_machine_type(void)
if (strstr(p, RELOC("Power Macintosh")) ||
strstr(p, RELOC("MacRISC")))
return PLATFORM_POWERMAC;
+#ifdef CONFIG_PPC64
+ /* We must make sure we don't detect the IBM Cell
+ * blades as pSeries due to some firmware issues,
+ * so we do it here.
+ */
+ if (strstr(p, RELOC("IBM,CBEA")) ||
+ strstr(p, RELOC("IBM,CPBW-1.0")))
+ return PLATFORM_GENERIC;
+#endif /* CONFIG_PPC64 */
i += sl + 1;
}
}
@@ -2057,10 +2067,45 @@ static void __init flatten_device_tree(void)
}
-
-static void __init fixup_device_tree(void)
+#ifdef CONFIG_PPC_MAPLE
+/* PIBS Version 1.05.0000 04/26/2005 has an incorrect /ht/isa/ranges property.
+ * The values are bad, and it doesn't even have the right number of cells. */
+static void __init fixup_device_tree_maple(void)
{
+ phandle isa;
+ u32 isa_ranges[6];
+
+ isa = call_prom("finddevice", 1, 1, ADDR("/ht@0/isa@4"));
+ if (!PHANDLE_VALID(isa))
+ return;
+
+ if (prom_getprop(isa, "ranges", isa_ranges, sizeof(isa_ranges))
+ == PROM_ERROR)
+ return;
+
+ if (isa_ranges[0] != 0x1 ||
+ isa_ranges[1] != 0xf4000000 ||
+ isa_ranges[2] != 0x00010000)
+ return;
+
+ prom_printf("fixing up bogus ISA range on Maple...\n");
+
+ isa_ranges[0] = 0x1;
+ isa_ranges[1] = 0x0;
+ isa_ranges[2] = 0x01002000; /* IO space; PCI device = 4 */
+ isa_ranges[3] = 0x0;
+ isa_ranges[4] = 0x0;
+ isa_ranges[5] = 0x00010000;
+ prom_setprop(isa, "/ht@0/isa@4", "ranges",
+ isa_ranges, sizeof(isa_ranges));
+}
+#else
+#define fixup_device_tree_maple()
+#endif
+
#if defined(CONFIG_PPC64) && defined(CONFIG_PPC_PMAC)
+static void __init fixup_device_tree_pmac(void)
+{
phandle u3, i2c, mpic;
u32 u3_rev;
u32 interrupts[2];
@@ -2097,9 +2142,16 @@ static void __init fixup_device_tree(void)
parent = (u32)mpic;
prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupt-parent",
&parent, sizeof(parent));
-#endif
}
+#else
+#define fixup_device_tree_pmac()
+#endif
+static void __init fixup_device_tree(void)
+{
+ fixup_device_tree_maple();
+ fixup_device_tree_pmac();
+}
static void __init prom_find_boot_cpu(void)
{
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 01e3c08cb550..8fdeca2d4597 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -803,10 +803,13 @@ static int do_setcontext(struct ucontext __user *ucp, struct pt_regs *regs, int
if (__get_user(cmcp, &ucp->uc_regs))
return -EFAULT;
mcp = (struct mcontext __user *)(u64)cmcp;
+ /* no need to check access_ok(mcp), since mcp < 4GB */
}
#else
if (__get_user(mcp, &ucp->uc_regs))
return -EFAULT;
+ if (!access_ok(VERIFY_READ, mcp, sizeof(*mcp)))
+ return -EFAULT;
#endif
restore_sigmask(&set);
if (restore_user_regs(regs, mcp, sig))
@@ -908,13 +911,14 @@ int sys_debug_setcontext(struct ucontext __user *ctx,
{
struct sig_dbg_op op;
int i;
+ unsigned char tmp;
unsigned long new_msr = regs->msr;
#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
unsigned long new_dbcr0 = current->thread.dbcr0;
#endif
for (i=0; i<ndbg; i++) {
- if (__copy_from_user(&op, dbg, sizeof(op)))
+ if (copy_from_user(&op, dbg + i, sizeof(op)))
return -EFAULT;
switch (op.dbg_type) {
case SIG_DBG_SINGLE_STEPPING:
@@ -959,6 +963,11 @@ int sys_debug_setcontext(struct ucontext __user *ctx,
current->thread.dbcr0 = new_dbcr0;
#endif
+ if (!access_ok(VERIFY_READ, ctx, sizeof(*ctx))
+ || __get_user(tmp, (u8 __user *) ctx)
+ || __get_user(tmp, (u8 __user *) (ctx + 1) - 1))
+ return -EFAULT;
+
/*
* If we get a fault copying the context into the kernel's
* image of the user's registers, we can't just return -EFAULT
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index 27f65b95184d..c2db642f4cdd 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -182,6 +182,8 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
err |= __get_user(msr, &sc->gp_regs[PT_MSR]);
if (err)
return err;
+ if (v_regs && !access_ok(VERIFY_READ, v_regs, 34 * sizeof(vector128)))
+ return -EFAULT;
/* Copy 33 vec registers (vr0..31 and vscr) from the stack */
if (v_regs != 0 && (msr & MSR_VEC) != 0)
err |= __copy_from_user(current->thread.vr, v_regs,
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
index 33654d1b1b43..994856e55b7c 100644
--- a/arch/powerpc/mm/hash_native_64.c
+++ b/arch/powerpc/mm/hash_native_64.c
@@ -52,7 +52,7 @@ static inline void __tlbie(unsigned long va, unsigned int psize)
default:
penc = mmu_psize_defs[psize].penc;
va &= ~((1ul << mmu_psize_defs[psize].shift) - 1);
- va |= (0x7f >> (8 - penc)) << 12;
+ va |= penc << 12;
asm volatile("tlbie %0,1" : : "r" (va) : "memory");
break;
}
@@ -74,7 +74,7 @@ static inline void __tlbiel(unsigned long va, unsigned int psize)
default:
penc = mmu_psize_defs[psize].penc;
va &= ~((1ul << mmu_psize_defs[psize].shift) - 1);
- va |= (0x7f >> (8 - penc)) << 12;
+ va |= penc << 12;
asm volatile(".long 0x7c000224 | (%0 << 11) | (1 << 21)"
: : "r"(va) : "memory");
break;
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
index 6574b22b3cf3..fd3e5609e3e0 100644
--- a/arch/powerpc/platforms/cell/setup.c
+++ b/arch/powerpc/platforms/cell/setup.c
@@ -125,14 +125,13 @@ static void __init cell_init_early(void)
static int __init cell_probe(void)
{
- /* XXX This is temporary, the Cell maintainer will come up with
- * more appropriate detection logic
- */
unsigned long root = of_get_flat_dt_root();
- if (!of_flat_dt_is_compatible(root, "IBM,CPBW-1.0"))
- return 0;
- return 1;
+ if (of_flat_dt_is_compatible(root, "IBM,CBEA") ||
+ of_flat_dt_is_compatible(root, "IBM,CPBW-1.0"))
+ return 1;
+
+ return 0;
}
/*
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c
index df2343e1956b..c896ce83d412 100644
--- a/arch/powerpc/platforms/powermac/low_i2c.c
+++ b/arch/powerpc/platforms/powermac/low_i2c.c
@@ -1157,6 +1157,7 @@ EXPORT_SYMBOL_GPL(pmac_i2c_xfer);
/* some quirks for platform function decoding */
enum {
pmac_i2c_quirk_invmask = 0x00000001u,
+ pmac_i2c_quirk_skip = 0x00000002u,
};
static void pmac_i2c_devscan(void (*callback)(struct device_node *dev,
@@ -1172,6 +1173,15 @@ static void pmac_i2c_devscan(void (*callback)(struct device_node *dev,
/* XXX Study device-tree's & apple drivers are get the quirks
* right !
*/
+ /* Workaround: It seems that running the clockspreading
+ * properties on the eMac will cause lockups during boot.
+ * The machine seems to work fine without that. So for now,
+ * let's make sure i2c-hwclock doesn't match about "imic"
+ * clocks and we'll figure out if we really need to do
+ * something special about those later.
+ */
+ { "i2c-hwclock", "imic5002", pmac_i2c_quirk_skip },
+ { "i2c-hwclock", "imic5003", pmac_i2c_quirk_skip },
{ "i2c-hwclock", NULL, pmac_i2c_quirk_invmask },
{ "i2c-cpu-voltage", NULL, 0},
{ "temp-monitor", NULL, 0 },
@@ -1198,6 +1208,8 @@ static void pmac_i2c_devscan(void (*callback)(struct device_node *dev,
if (p->compatible &&
!device_is_compatible(np, p->compatible))
continue;
+ if (p->quirks & pmac_i2c_quirk_skip)
+ break;
callback(np, p->quirks);
break;
}
diff --git a/arch/powerpc/platforms/powermac/pfunc_core.c b/arch/powerpc/platforms/powermac/pfunc_core.c
index 4baa75b1d36f..f08173b0f065 100644
--- a/arch/powerpc/platforms/powermac/pfunc_core.c
+++ b/arch/powerpc/platforms/powermac/pfunc_core.c
@@ -11,6 +11,7 @@
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/module.h>
+#include <linux/mutex.h>
#include <asm/semaphore.h>
#include <asm/prom.h>
@@ -546,6 +547,7 @@ struct pmf_device {
static LIST_HEAD(pmf_devices);
static spinlock_t pmf_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_MUTEX(pmf_irq_mutex);
static void pmf_release_device(struct kref *kref)
{
@@ -864,15 +866,17 @@ int pmf_register_irq_client(struct device_node *target,
spin_lock_irqsave(&pmf_lock, flags);
func = __pmf_find_function(target, name, PMF_FLAGS_INT_GEN);
- if (func == NULL) {
- spin_unlock_irqrestore(&pmf_lock, flags);
+ if (func)
+ func = pmf_get_function(func);
+ spin_unlock_irqrestore(&pmf_lock, flags);
+ if (func == NULL)
return -ENODEV;
- }
+ mutex_lock(&pmf_irq_mutex);
if (list_empty(&func->irq_clients))
func->dev->handlers->irq_enable(func);
list_add(&client->link, &func->irq_clients);
client->func = func;
- spin_unlock_irqrestore(&pmf_lock, flags);
+ mutex_unlock(&pmf_irq_mutex);
return 0;
}
@@ -881,16 +885,16 @@ EXPORT_SYMBOL_GPL(pmf_register_irq_client);
void pmf_unregister_irq_client(struct pmf_irq_client *client)
{
struct pmf_function *func = client->func;
- unsigned long flags;
BUG_ON(func == NULL);
- spin_lock_irqsave(&pmf_lock, flags);
+ mutex_lock(&pmf_irq_mutex);
client->func = NULL;
list_del(&client->link);
if (list_empty(&func->irq_clients))
func->dev->handlers->irq_disable(func);
- spin_unlock_irqrestore(&pmf_lock, flags);
+ mutex_unlock(&pmf_irq_mutex);
+ pmf_put_function(func);
}
EXPORT_SYMBOL_GPL(pmf_unregister_irq_client);
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 4d15e396655c..b9200fb07815 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -463,11 +463,23 @@ static int pmac_pm_finish(suspend_state_t state)
return 0;
}
+static int pmac_pm_valid(suspend_state_t state)
+{
+ switch (state) {
+ case PM_SUSPEND_DISK:
+ return 1;
+ /* can't do any other states via generic mechanism yet */
+ default:
+ return 0;
+ }
+}
+
static struct pm_ops pmac_pm_ops = {
.pm_disk_mode = PM_DISK_SHUTDOWN,
.prepare = pmac_pm_prepare,
.enter = pmac_pm_enter,
.finish = pmac_pm_finish,
+ .valid = pmac_pm_valid,
};
#endif /* CONFIG_SOFTWARE_SUSPEND */
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 5f79f01c44f2..3ba87835757e 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -389,6 +389,7 @@ static int __init pSeries_probe_hypertas(unsigned long node,
static int __init pSeries_probe(void)
{
+ unsigned long root = of_get_flat_dt_root();
char *dtype = of_get_flat_dt_prop(of_get_flat_dt_root(),
"device_type", NULL);
if (dtype == NULL)
@@ -396,6 +397,13 @@ static int __init pSeries_probe(void)
if (strcmp(dtype, "chrp"))
return 0;
+ /* Cell blades firmware claims to be chrp while it's not. Until this
+ * is fixed, we need to avoid those here.
+ */
+ if (of_flat_dt_is_compatible(root, "IBM,CPBW-1.0") ||
+ of_flat_dt_is_compatible(root, "IBM,CBEA"))
+ return 0;
+
DBG("pSeries detected, looking for LPAR capability...\n");
/* Now try to figure out if we are running on LPAR */