LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [patch 28/35] Work around errata 4712
From: Olof Johansson @ 2007-07-05 17:03 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20070705170233.258351000@lixom.net>

Workaround for errata 4712; on an SMP system the PIC can get stuck
trying to read the next available interrupt from INTACK in case there's
only a spurious available. The workaround is to program timers to cause
interrupts every now and then, which recovers from the lockup.


Index: mainline/arch/powerpc/sysdev/mpic.c
===================================================================
--- mainline.orig/arch/powerpc/sysdev/mpic.c
+++ mainline/arch/powerpc/sysdev/mpic.c
@@ -1602,3 +1602,37 @@ static int mpic_init_sys(void)
 }
 
 device_initcall(mpic_init_sys);
+
+
+static irqreturn_t intr_4712(int irq, void *data)
+{
+	return IRQ_HANDLED;
+}
+
+static int do_4712_workaround(void)
+{
+	struct mpic *mpic = mpic_primary;
+	int irq, ret;
+
+	/* HACK: setup timers 4 and 5: 2Hz for now, hold off for 1 sec */
+	/* Steal vectors 250 and 251, nothing uses them */
+
+	irq = irq_create_mapping(NULL, 250);
+	ret = request_irq(irq, &intr_4712, IRQF_DISABLED, "4712 workaround cpu0", NULL);
+	irq = irq_create_mapping(NULL, 251);
+	ret = request_irq(irq, &intr_4712, IRQF_DISABLED, "4712 workaround cpu1", NULL);
+
+	mpic_write(mpic->tmregs, 0 * MPIC_INFO(TIMER_STRIDE) + MPIC_INFO(TIMER_DESTINATION), 1);
+	mpic_write(mpic->tmregs, 0 * MPIC_INFO(TIMER_STRIDE) + MPIC_INFO(TIMER_VECTOR_PRI), (10 << MPIC_VECPRI_PRIORITY_SHIFT) | 250);
+	mpic_write(mpic->tmregs, 0 * MPIC_INFO(TIMER_STRIDE) + MPIC_INFO(TIMER_BASE_CNT), 8333333/4);
+	mpic_write(mpic->tmregs, 0 * MPIC_INFO(TIMER_STRIDE) + MPIC_INFO(TIMER_CURRENT_CNT), 8333333);
+
+	mpic_write(mpic->tmregs, 3 * MPIC_INFO(TIMER_STRIDE) + MPIC_INFO(TIMER_DESTINATION), 2);
+	mpic_write(mpic->tmregs, 3 * MPIC_INFO(TIMER_STRIDE) + MPIC_INFO(TIMER_VECTOR_PRI), (10 << MPIC_VECPRI_PRIORITY_SHIFT) | 251);
+	mpic_write(mpic->tmregs, 3 * MPIC_INFO(TIMER_STRIDE) + MPIC_INFO(TIMER_BASE_CNT), 8333333/4);
+	mpic_write(mpic->tmregs, 3 * MPIC_INFO(TIMER_STRIDE) + MPIC_INFO(TIMER_CURRENT_CNT), 8333333);
+
+	return 0;
+}
+late_initcall(do_4712_workaround);
+

--

^ permalink raw reply

* [patch 27/35] Work around errata 4290
From: Olof Johansson @ 2007-07-05 17:03 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20070705170233.258351000@lixom.net>

Workaround for errata 4290: The decrementer ticks at half the expected rate
so load it with half the value it would otherwise be loaded with.


Index: 2.6.21/include/asm-powerpc/time.h
===================================================================
--- 2.6.21.orig/include/asm-powerpc/time.h
+++ 2.6.21/include/asm-powerpc/time.h
@@ -173,6 +173,13 @@ static inline unsigned int get_dec(void)
 
 static inline void set_dec(int val)
 {
+#ifdef CONFIG_PPC_PASEMI
+	/* PA6T rev Ax have decrementer ticking at 1/2 tb rate */
+	val >>= 2;
+	if (!val)
+		val = 1;
+#endif
+
 #if defined(CONFIG_40x)
 	return;		/* Have to let it auto-reload */
 #elif defined(CONFIG_8xx_CPU6)

--

^ permalink raw reply

* [patch 18/35] Spread IRQs among cpus by default
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20070705170233.258351000@lixom.net>

Spread IRQs between the two cores on our openpic. Without this,
they get delivered to cpu 0 as long as it's available.

This needs a bit more cleanup -- it needs a flag so it can coexist
with other implementations.

Index: 2.6.21/arch/powerpc/sysdev/mpic.c
===================================================================
--- 2.6.21.orig/arch/powerpc/sysdev/mpic.c
+++ 2.6.21/arch/powerpc/sysdev/mpic.c
@@ -1191,6 +1191,11 @@ void __init mpic_init(struct mpic *mpic)
 			   mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
 			   | MPIC_GREG_GCONF_8259_PTHROU_DIS);
 
+	mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
+		   mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
+		   | 0x10000000);
+
+
 	/* Set current processor priority to 0 */
 	mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0);
 }

--

^ permalink raw reply

* [patch 31/35] Work around errata 4161
From: Olof Johansson @ 2007-07-05 17:03 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20070705170233.258351000@lixom.net>

Errata 4161: Concurring ptesyncs on both cores might lock up the
cores. Most ptesyncs are already under tlbie_lock, so use that in the only
other remaining location (the timer interrupt ones we've added ourselves).


Index: 2.6.21/arch/powerpc/kernel/time.c
===================================================================
--- 2.6.21.orig/arch/powerpc/kernel/time.c
+++ 2.6.21/arch/powerpc/kernel/time.c
@@ -618,8 +618,11 @@ void timer_interrupt(struct pt_regs * re
 	int cpu = smp_processor_id();
 	unsigned long ticks;
 	u64 tb_next_jiffy;
+	extern spinlock_t native_tlbie_lock;
 
+	spin_lock(&native_tlbie_lock);
 	asm("ptesync");
+	spin_unlock(&native_tlbie_lock);
 
 #ifdef CONFIG_PPC32
 	if (atomic_read(&ppc_n_lost_interrupts) != 0)
Index: 2.6.21/arch/powerpc/mm/hash_native_64.c
===================================================================
--- 2.6.21.orig/arch/powerpc/mm/hash_native_64.c
+++ 2.6.21/arch/powerpc/mm/hash_native_64.c
@@ -35,7 +35,7 @@
 
 #define HPTE_LOCK_BIT 3
 
-static DEFINE_SPINLOCK(native_tlbie_lock);
+DEFINE_SPINLOCK(native_tlbie_lock);
 
 static inline void __tlbie(unsigned long va, unsigned int psize)
 {

--

^ permalink raw reply

* [patch 32/35] Dont reset openpic on init
From: Olof Johansson @ 2007-07-05 17:03 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20070705170233.258351000@lixom.net>

Take out the MPIC_WANTS_RESET again, since it turns out it causes loss
of interrupt grant tokens during some circumstances on Ax.

Index: 2.6.21/arch/powerpc/platforms/pasemi/setup.c
===================================================================
--- 2.6.21.orig/arch/powerpc/platforms/pasemi/setup.c
+++ 2.6.21/arch/powerpc/platforms/pasemi/setup.c
@@ -156,7 +156,7 @@ static __init void pas_init_IRQ(void)
 	printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr);
 
 	mpic = mpic_alloc(mpic_node, openpic_addr,
-			  MPIC_PRIMARY|MPIC_LARGE_VECTORS|MPIC_WANTS_RESET,
+			  MPIC_PRIMARY|MPIC_LARGE_VECTORS,
 			  0, 0, " PAS-OPIC  ");
 	BUG_ON(!mpic);
 

--

^ permalink raw reply

* [patch 24/35] Work around errata 4628
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20070705170233.258351000@lixom.net>

Errata 4628 causes lockups during table walks that are recovered from
when a ptesync is received. So, issue a ptesync every timer interrupt,
and for CPUs that have not yet spun up, at regular intervals. This seems
sufficient to avoid hitting it.

Index: 2.6.21/arch/powerpc/kernel/head_64.S
===================================================================
--- 2.6.21.orig/arch/powerpc/kernel/head_64.S
+++ 2.6.21/arch/powerpc/kernel/head_64.S
@@ -123,10 +123,22 @@ _GLOBAL(__secondary_hold)
 	std	r24,__secondary_hold_acknowledge@l(0)
 	sync
 
+#ifdef CONFIG_SMP
 	/* All secondary cpus wait here until told to start. */
 100:	ld	r4,__secondary_hold_spinloop@l(0)
 	cmpdi	0,r4,1
 	bne	100b
+#else
+	lis	r3, 0x40
+	mtctr	r3
+100:	bdnz	.
+	ptesync
+	ptesync
+	lis	r3, 0x40
+	mtctr	r3
+	b	100b
+	
+#endif
 
 #if defined(CONFIG_SMP) || defined(CONFIG_KEXEC)
 	LOAD_REG_IMMEDIATE(r4, .generic_secondary_smp_init)
@@ -1582,16 +1594,32 @@ _GLOBAL(generic_secondary_smp_init)
 2:	mtspr	SPRN_SPRG3,r13		/* Save vaddr of paca in SPRG3	 */
 	/* From now on, r24 is expected to be logical cpuid */
 	mr	r24,r5
+
+	lis	r23, 0x40
+	mtctr	r23
+
 3:	HMT_LOW
 	lbz	r23,PACAPROCSTART(r13)	/* Test if this processor should */
-					/* start.			 */
-	sync
 
 #ifndef CONFIG_SMP
 	b	3b			/* Never go on non-SMP		 */
 #else
 	cmpwi	0,r23,0
-	beq	3b			/* Loop until told to go	 */
+	bne	5f			/* Loop until told to go	 */
+					/* start.			 */
+	isync
+
+4:	bdnz	3b
+	ptesync
+	isync
+	sync
+	ptesync
+	lis	r23, 0x40
+	mtctr	r23
+	b	3b
+
+5:
+
 
 	/* See if we need to call a cpu state restore handler */
 	LOAD_REG_IMMEDIATE(r23, cur_cpu_spec)
Index: 2.6.21/arch/powerpc/kernel/time.c
===================================================================
--- 2.6.21.orig/arch/powerpc/kernel/time.c
+++ 2.6.21/arch/powerpc/kernel/time.c
@@ -619,6 +619,8 @@ void timer_interrupt(struct pt_regs * re
 	unsigned long ticks;
 	u64 tb_next_jiffy;
 
+	asm("ptesync");
+
 #ifdef CONFIG_PPC32
 	if (atomic_read(&ppc_n_lost_interrupts) != 0)
 		do_IRQ(regs);

--

^ permalink raw reply

* [patch 17/35] CF driver for PA Semi Electra
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20070705170233.258351000@lixom.net>

Driver for the CompactFlash slot on the PA Semi Electra eval board. It's
a simple device sitting on localbus, with interrupts and detect/voltage
control over GPIO.

The driver is implemented as an of_platform driver, and adds localbus
as a bus being probed by the of_platform framework.


Signed-off-by: Olof Johansson <olof@lixom.net>

Index: mainline/drivers/pcmcia/Kconfig
===================================================================
--- mainline.orig/drivers/pcmcia/Kconfig
+++ mainline/drivers/pcmcia/Kconfig
@@ -270,6 +270,13 @@ config AT91_CF
 	  Say Y here to support the CompactFlash controller on AT91 chips.
 	  Or choose M to compile the driver as a module named "at91_cf".
 
+config ELECTRA_CF
+	bool "Electra CompactFlash Controller"
+	depends on PCMCIA=y && PPC_PASEMI
+	help
+	  Say Y here to support the CompactFlash controller on the
+	  PA Semi Electra eval board.
+
 config PCCARD_NONSTATIC
 	tristate
 
Index: mainline/drivers/pcmcia/Makefile
===================================================================
--- mainline.orig/drivers/pcmcia/Makefile
+++ mainline/drivers/pcmcia/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_PCMCIA_VRC4171)			+= vrc417
 obj-$(CONFIG_PCMCIA_VRC4173)			+= vrc4173_cardu.o
 obj-$(CONFIG_OMAP_CF)				+= omap_cf.o
 obj-$(CONFIG_AT91_CF)				+= at91_cf.o
+obj-$(CONFIG_ELECTRA_CF)			+= electra_cf.o
 
 sa11xx_core-y					+= soc_common.o sa11xx_base.o
 pxa2xx_core-y					+= soc_common.o pxa2xx_base.o
Index: mainline/drivers/pcmcia/electra_cf.c
===================================================================
--- /dev/null
+++ mainline/drivers/pcmcia/electra_cf.c
@@ -0,0 +1,374 @@
+/*
+ * Copyright (C) 2007 PA Semi, Inc
+ *
+ * Maintained by: Olof Johansson <olof@lixom.net>
+ *
+ * Based on drivers/pcmcia/omap_cf.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+
+#include <pcmcia/ss.h>
+#include <asm/of_platform.h>
+
+static const char driver_name[] = "electra-cf";
+
+struct electra_cf_socket {
+	struct pcmcia_socket	socket;
+
+	struct timer_list	timer;
+	unsigned		present:1;
+	unsigned		active:1;
+
+	struct of_device	*ofdev;
+	unsigned long		mem_phys;
+	void __iomem *		mem_base;
+	unsigned long		mem_size;
+	void __iomem *		io_virt;
+	unsigned int		io_base;
+	unsigned int		io_size;
+	u_int			irq;
+	struct resource		iomem;
+	void __iomem *		gpio_base;
+	int			gpio_detect;
+	int			gpio_vsense;
+	int			gpio_3v;
+	int			gpio_5v;
+};
+
+#define	POLL_INTERVAL		(2 * HZ)
+
+
+static int electra_cf_present(struct electra_cf_socket *cf)
+{
+	unsigned int gpio;
+
+	gpio = in_le32(cf->gpio_base+0x40);
+	return !(gpio & (1 << cf->gpio_detect));
+}
+
+static int electra_cf_ss_init(struct pcmcia_socket *s)
+{
+	return 0;
+}
+
+/* the timer is primarily to kick this socket's pccardd */
+static void electra_cf_timer(unsigned long _cf)
+{
+	struct electra_cf_socket *cf = (void *) _cf;
+	int present = electra_cf_present(cf);
+
+	if (present != cf->present) {
+		cf->present = present;
+		pcmcia_parse_events(&cf->socket, SS_DETECT);
+	}
+
+	if (cf->active)
+		mod_timer(&cf->timer, jiffies + POLL_INTERVAL);
+}
+
+static irqreturn_t electra_cf_irq(int irq, void *_cf)
+{
+	electra_cf_timer((unsigned long)_cf);
+	return IRQ_HANDLED;
+}
+
+static int electra_cf_get_status(struct pcmcia_socket *s, u_int *sp)
+{
+	struct electra_cf_socket *cf;
+
+	if (!sp)
+		return -EINVAL;
+
+	cf = container_of(s, struct electra_cf_socket, socket);
+
+	/* NOTE CF is always 3VCARD */
+	if (electra_cf_present(cf)) {
+		struct electra_cf_socket *cf;
+
+		*sp = SS_READY | SS_DETECT | SS_POWERON | SS_3VCARD;
+		cf = container_of(s, struct electra_cf_socket, socket);
+		s->pci_irq = cf->irq;
+	} else
+		*sp = 0;
+	return 0;
+}
+
+static int electra_cf_set_socket(struct pcmcia_socket *sock,
+				 struct socket_state_t *s)
+{
+	unsigned int gpio;
+	unsigned int vcc;
+	struct electra_cf_socket *cf;
+
+	cf = container_of(sock, struct electra_cf_socket, socket);
+
+	/* "reset" means no power in our case */
+	vcc = (s->flags & SS_RESET) ? 0 : s->Vcc;
+
+	switch (vcc) {
+	case 0:
+		gpio = 0;
+		break;
+	case 33:
+		gpio = (1 << cf->gpio_3v);
+		break;
+	default:
+		/* CF is 3.3V only */
+		return -EINVAL;
+	}
+
+	gpio |= 1 << (cf->gpio_3v + 16); /* enwr */
+	gpio |= 1 << (cf->gpio_5v + 16); /* enwr */
+	out_le32(cf->gpio_base+0x90, gpio);
+
+	pr_debug("%s: Vcc %d, io_irq %d, flags %04x csc %04x\n",
+		driver_name, s->Vcc, s->io_irq, s->flags, s->csc_mask);
+
+	return 0;
+}
+
+static int electra_cf_set_io_map(struct pcmcia_socket *s,
+				 struct pccard_io_map *io)
+{
+	return 0;
+}
+
+static int electra_cf_set_mem_map(struct pcmcia_socket *s,
+				  struct pccard_mem_map *map)
+{
+	struct electra_cf_socket *cf;
+
+	if (map->card_start)
+		return -EINVAL;
+	cf = container_of(s, struct electra_cf_socket, socket);
+	map->static_start = cf->mem_phys;
+	map->flags &= MAP_ACTIVE|MAP_ATTRIB;
+	if (!(map->flags & MAP_ATTRIB))
+		map->static_start += 0x800;
+	return 0;
+}
+
+static struct pccard_operations electra_cf_ops = {
+	.init			= electra_cf_ss_init,
+	.get_status		= electra_cf_get_status,
+	.set_socket		= electra_cf_set_socket,
+	.set_io_map		= electra_cf_set_io_map,
+	.set_mem_map		= electra_cf_set_mem_map,
+};
+
+static int __devinit electra_cf_probe(struct of_device *ofdev,
+				      const struct of_device_id *match)
+{
+	struct device *device = &ofdev->dev;
+	struct device_node *np = ofdev->node;
+	struct electra_cf_socket   *cf;
+	struct resource mem, io;
+	int status;
+	const unsigned int *prop;
+	int err;
+
+	err = of_address_to_resource(np, 0, &mem);
+	if (err)
+		return -EINVAL;
+
+	err = of_address_to_resource(np, 1, &io);
+	if (err)
+		return -EINVAL;
+
+	cf = kzalloc(sizeof *cf, GFP_KERNEL);
+	if (!cf)
+		return -ENOMEM;
+
+	init_timer(&cf->timer);
+	cf->timer.function = electra_cf_timer;
+	cf->timer.data = (unsigned long) cf;
+	cf->irq = NO_IRQ;
+
+	cf->ofdev = ofdev;
+	cf->mem_phys = mem.start;
+	cf->mem_base = ioremap(mem.start, mem.end - mem.start);
+	cf->io_size = PAGE_ALIGN(io.end - io.start);
+
+	cf->io_virt = reserve_phb_iospace(cf->io_size);
+
+	cf->gpio_base = ioremap(0xfc103000, 0x1000);
+	dev_set_drvdata(device, cf);
+
+	if (!cf->mem_base || !cf->io_virt || !cf->gpio_base) {
+		dev_err(device, "can't ioremap ranges\n");
+		status = -ENOMEM;
+		goto fail1;
+	}
+
+	__ioremap_explicit(io.start, (unsigned long)cf->io_virt, cf->io_size,
+			   _PAGE_NO_CACHE | _PAGE_GUARDED);
+
+	cf->io_base = (unsigned long)cf->io_virt - VMALLOC_END;
+
+	cf->iomem.start = (unsigned long)cf->mem_base;
+	cf->iomem.end = (unsigned long)cf->mem_base + (mem.end - mem.start);
+	cf->iomem.flags = IORESOURCE_MEM;
+
+	cf->irq = irq_of_parse_and_map(np, 0);
+
+	status = request_irq(cf->irq, electra_cf_irq, IRQF_SHARED,
+			     driver_name, cf);
+	if (status < 0) {
+		dev_err(device, "request_irq failed\n");
+		goto fail1;
+	}
+
+	cf->socket.pci_irq = cf->irq;
+
+	prop = of_get_property(np, "card-detect-gpio", NULL);
+	if (!prop)
+		goto fail1;
+	cf->gpio_detect = *prop;
+
+	prop = of_get_property(np, "card-vsense-gpio", NULL);
+	if (!prop)
+		goto fail1;
+	cf->gpio_vsense = *prop;
+
+	prop = of_get_property(np, "card-3v-gpio", NULL);
+	if (!prop)
+		goto fail1;
+	cf->gpio_3v = *prop;
+
+	prop = of_get_property(np, "card-5v-gpio", NULL);
+	if (!prop)
+		goto fail1;
+	cf->gpio_5v = *prop;
+
+	cf->socket.io_offset = cf->io_base;
+
+	/* reserve chip-select regions */
+	if (!request_mem_region(mem.start, mem.end + 1 - mem.start,
+				driver_name)) {
+		status = -ENXIO;
+		dev_err(device, "Can't claim memory region\n");
+		goto fail1;
+	}
+
+	if (!request_region(cf->io_base, cf->io_size, driver_name)) {
+		status = -ENXIO;
+		dev_err(device, "Can't claim I/O region\n");
+		goto fail2;
+	}
+
+	cf->socket.owner = THIS_MODULE;
+	cf->socket.dev.parent = &ofdev->dev;
+	cf->socket.ops = &electra_cf_ops;
+	cf->socket.resource_ops = &pccard_static_ops;
+	cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP |
+				SS_CAP_MEM_ALIGN;
+	cf->socket.map_size = 0x800;
+
+	status = pcmcia_register_socket(&cf->socket);
+	if (status < 0) {
+		dev_err(device, "pcmcia_register_socket failed\n");
+		goto fail3;
+	}
+
+	dev_info(device, "at mem 0x%lx io 0x%lx irq %d\n",
+		 mem.start, io.start, cf->irq);
+
+	cf->active = 1;
+	electra_cf_timer((unsigned long)cf);
+	return 0;
+
+fail3:
+	release_mem_region(io.start, io.end + 1 - io.start);
+fail2:
+	release_mem_region(mem.start, mem.end + 1 - mem.start);
+fail1:
+	if (cf->irq != NO_IRQ)
+		free_irq(cf->irq, cf);
+
+	/* XXX No way to undo the ioremap_explicit at this time */
+	if (cf->mem_base)
+		iounmap(cf->mem_base);
+	if (cf->gpio_base)
+		iounmap(cf->gpio_base);
+	device_init_wakeup(&ofdev->dev, 0);
+	kfree(cf);
+	return status;
+
+}
+
+static int __devexit electra_cf_remove(struct of_device *ofdev)
+{
+	struct device *device = &ofdev->dev;
+	struct electra_cf_socket *cf;
+
+	cf = dev_get_drvdata(device);
+
+	cf->active = 0;
+	pcmcia_unregister_socket(&cf->socket);
+	free_irq(cf->irq, cf);
+	del_timer_sync(&cf->timer);
+
+	iounmap(cf->mem_base);
+	iounmap(cf->gpio_base);
+	release_mem_region(cf->mem_phys, cf->mem_size);
+	release_region(cf->io_base, cf->io_size);
+
+	kfree(cf);
+
+	return 0;
+}
+
+static struct of_device_id electra_cf_match[] =
+{
+	{
+		.compatible   = "electra-cf",
+	},
+	{},
+};
+
+static struct of_platform_driver electra_cf_driver =
+{
+	.name	   = (char *)driver_name,
+	.match_table    = electra_cf_match,
+	.probe	  = electra_cf_probe,
+	.remove   = electra_cf_remove,
+};
+
+static int __init electra_cf_init(void)
+{
+	return of_register_platform_driver(&electra_cf_driver);
+}
+module_init(electra_cf_init);
+
+static void __exit electra_cf_exit(void)
+{
+	of_unregister_platform_driver(&electra_cf_driver);
+}
+module_exit(electra_cf_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR ("Olof Johansson <olof@lixom.net>");
+MODULE_DESCRIPTION("PA Semi Electra CF driver");
+
Index: mainline/arch/powerpc/platforms/pasemi/setup.c
===================================================================
--- mainline.orig/arch/powerpc/platforms/pasemi/setup.c
+++ mainline/arch/powerpc/platforms/pasemi/setup.c
@@ -37,6 +37,10 @@
 #include <asm/time.h>
 #include <asm/of_platform.h>
 
+#include <pcmcia/ss.h>
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ds.h>
+
 #include "pasemi.h"
 
 static void __iomem *reset_reg;
@@ -204,7 +208,57 @@ static void __init pas_init_early(void)
 	iommu_init_early_pasemi();
 }
 
+#ifdef CONFIG_PCMCIA
+static int pcmcia_notify(struct notifier_block *nb, unsigned long action,
+			 void *data)
+{
+	struct device *dev = data;
+	struct device *parent;
+	struct pcmcia_device *pdev = to_pcmcia_dev(dev);
+
+	/* We are only intereted in device addition */
+	if (action != BUS_NOTIFY_ADD_DEVICE)
+		return 0;
+
+	parent = pdev->socket->dev.parent;
+
+	/* We know electra_cf devices will always have of_node set, since
+	 * electra_cf is an of_platform driver.
+	 */
+	if (!parent->archdata.of_node)
+		return 0;
+
+	if (!of_device_is_compatible(parent->archdata.of_node, "electra-cf"))
+		return 0;
+
+	/* We use the direct ops for localbus */
+	dev->archdata.dma_ops = &dma_direct_ops;
+
+	return 0;
+}
+
+static struct notifier_block pcmcia_notifier = {
+	.notifier_call = pcmcia_notify,
+};
+
+static inline void pasemi_pcmcia_init(void)
+{
+	extern struct bus_type pcmcia_bus_type;
+
+	bus_register_notifier(&pcmcia_bus_type, &pcmcia_notifier);
+}
+
+#else
+
+static inline void pasemi_pcmcia_init(void)
+{
+}
+
+#endif
+
+
 static struct of_device_id pasemi_bus_ids[] = {
+	{ .type = "localbus", },
 	{ .type = "sdc", },
 	{},
 };
@@ -214,6 +268,8 @@ static int __init pasemi_publish_devices
 	if (!machine_is(pasemi))
 		return 0;
 
+	pasemi_pcmcia_init();
+
 	/* Publish OF platform devices for SDC and other non-PCI devices */
 	of_platform_bus_probe(NULL, pasemi_bus_ids, NULL);
 
@@ -239,7 +295,7 @@ static int __init pas_probe(void)
 	return 1;
 }
 
-define_machine(pas) {
+define_machine(pasemi) {
 	.name			= "PA Semi PA6T-1682M",
 	.probe			= pas_probe,
 	.setup_arch		= pas_setup_arch,

--

^ permalink raw reply

* [patch 35/35] Work around errata 5652
From: Olof Johansson @ 2007-07-05 17:03 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20070705170233.258351000@lixom.net>

Due to errata 5652 we might sometimes end up with duplicate SLB entries.

This causes a machine check, so detect it (and print debug info), but
recover instead of killing the process and/or crashing the machine.


Index: 2.6.21/arch/powerpc/platforms/pasemi/setup.c
===================================================================
--- 2.6.21.orig/arch/powerpc/platforms/pasemi/setup.c
+++ 2.6.21/arch/powerpc/platforms/pasemi/setup.c
@@ -36,6 +36,7 @@
 #include <asm/smp.h>
 #include <asm/time.h>
 #include <asm/of_platform.h>
+#include <asm/mmu-hash64.h>
 
 #include "pasemi.h"
 
@@ -176,7 +177,7 @@ static int pas_machine_check_handler(str
 {
 	int cpu = smp_processor_id();
 	unsigned long srr0, srr1, dsisr;
-	int dump_slb = 0;
+	int dump_slb = 0, flush_slb = 0;
 	int dump_memsta = 0;
 
 	srr0 = regs->nip;
@@ -200,6 +201,7 @@ static int pas_machine_check_handler(str
 		if (dsisr & 0x2000) {
 			printk(KERN_ERR "MMU SLB multi-hit or invalid B field\n");
 			dump_slb = 1;
+			flush_slb = 1;
 		}
 		if (dsisr & 0x1000)
 			printk(KERN_ERR "Recoverable Duptags\n");
@@ -215,6 +217,7 @@ static int pas_machine_check_handler(str
 	if (srr1 & 0x40000) {
 		printk(KERN_ERR "I-side SLB multiple hit\n");
 		dump_slb = 1;
+		flush_slb = 1;
 	}
 	if (srr1 & 0x20000) {
 		printk(KERN_ERR "I-cache parity error hit\n");
@@ -243,6 +246,10 @@ static int pas_machine_check_handler(str
 		}
 	}
 
+	if (flush_slb)
+		/* We really can recover from this. flush, rebolt and go. */
+		slb_flush_and_rebolt();
+
 	/* SRR1[62] is from MSR[62] if recoverable, so pass that back */
 	return !!(srr1 & 0x2);
 }

--

^ permalink raw reply

* [patch 25/35] Work around errata 4025
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20070705170233.258351000@lixom.net>

Errata 4025 workaround: A SLB load can in some cases be corrupted. As a workaround,
insert an instruction with sync side effects after the load (in this case it's the
mtmsrd).

Index: 2.6.21/arch/powerpc/kernel/entry_64.S
===================================================================
--- 2.6.21.orig/arch/powerpc/kernel/entry_64.S
+++ 2.6.21/arch/powerpc/kernel/entry_64.S
@@ -395,6 +395,8 @@ BEGIN_FTR_SECTION
 	slbie	r6
 	slbie	r6		/* Workaround POWER5 < DD2.1 issue */
 	slbmte	r7,r0
+	mfmsr	r7		/* PA6T Ax workaround */
+	mtmsrd	r7
 	isync
 
 2:
Index: 2.6.21/arch/powerpc/mm/slb.c
===================================================================
--- 2.6.21.orig/arch/powerpc/mm/slb.c
+++ 2.6.21/arch/powerpc/mm/slb.c
@@ -79,7 +79,7 @@ static inline void create_shadowed_slbe(
 	slb_shadow_update(mk_esid_data(ea, entry), mk_vsid_data(ea, flags),
 			  entry);
 
-	asm volatile("slbmte  %0,%1" :
+	asm volatile("slbmte  %0,%1 ; mfmsr %0 ; mtmsrd %0" :
 		     : "r" (mk_vsid_data(ea, flags)),
 		       "r" (mk_esid_data(ea, entry))
 		     : "memory" );
@@ -113,8 +113,14 @@ void slb_flush_and_rebolt(void)
 		     "slbia\n"
 		     /* Slot 1 - first VMALLOC segment */
 		     "slbmte	%0,%1\n"
+		     /* PA6T Ax workaround */
+		     "mfmsr	%0\n"
+		     "mtmsrd	%0\n"
 		     /* Slot 2 - kernel stack */
 		     "slbmte	%2,%3\n"
+		     /* PA6T Ax workaround */
+		     "mfmsr	%0\n"
+		     "mtmsrd	%0\n"
 		     "isync"
 		     :: "r"(mk_vsid_data(VMALLOC_START, vflags)),
 		        "r"(mk_esid_data(VMALLOC_START, 1)),
Index: 2.6.21/arch/powerpc/mm/slb_low.S
===================================================================
--- 2.6.21.orig/arch/powerpc/mm/slb_low.S
+++ 2.6.21/arch/powerpc/mm/slb_low.S
@@ -221,6 +221,8 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISER
 	 * we enter with and the rfid we exit with are context synchronizing.
 	 */
 	slbmte	r11,r10
+	mfmsr	r3
+	mtmsrd	r3
 
 	/* we're done for kernel addresses */
 	crclr	4*cr0+eq		/* set result to "success" */

--

^ permalink raw reply

* [patch 21/35] Use MSR_PMM to disable profiling of the idle loop
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20070705170233.258351000@lixom.net>

Use MSR_PMM to disable performance monitor counting while in idle,
instead of using the CTRL register like on the IBM implementation.

This needs further cleanup. It should be possible to switch over the
default behaviour to MSR_PMM on IBM hardware too.

Index: 2.6.21/arch/powerpc/kernel/process.c
===================================================================
--- 2.6.21.orig/arch/powerpc/kernel/process.c
+++ 2.6.21/arch/powerpc/kernel/process.c
@@ -972,13 +972,18 @@ void ppc64_runlatch_on(void)
 {
 	unsigned long ctrl;
 
-	if (cpu_has_feature(CPU_FTR_CTRL) && !test_thread_flag(TIF_RUNLATCH)) {
+//	if (cpu_has_feature(CPU_FTR_CTRL) && !test_thread_flag(TIF_RUNLATCH)) {
+	if (!test_thread_flag(TIF_RUNLATCH)) {
 		HMT_medium();
 
 		ctrl = mfspr(SPRN_CTRLF);
 		ctrl |= CTRL_RUNLATCH;
 		mtspr(SPRN_CTRLT, ctrl);
 
+		ctrl = mfmsr();
+		ctrl &= ~MSR_PMM;
+		mtmsrd(ctrl);
+
 		set_thread_flag(TIF_RUNLATCH);
 	}
 }
@@ -987,7 +992,8 @@ void ppc64_runlatch_off(void)
 {
 	unsigned long ctrl;
 
-	if (cpu_has_feature(CPU_FTR_CTRL) && test_thread_flag(TIF_RUNLATCH)) {
+//	if (cpu_has_feature(CPU_FTR_CTRL) && test_thread_flag(TIF_RUNLATCH)) {
+	if (test_thread_flag(TIF_RUNLATCH)) {
 		HMT_medium();
 
 		clear_thread_flag(TIF_RUNLATCH);
@@ -995,6 +1001,10 @@ void ppc64_runlatch_off(void)
 		ctrl = mfspr(SPRN_CTRLF);
 		ctrl &= ~CTRL_RUNLATCH;
 		mtspr(SPRN_CTRLT, ctrl);
+
+		ctrl = mfmsr();
+		ctrl |= MSR_PMM;
+		mtmsrd(ctrl);
 	}
 }
 #endif
Index: 2.6.21/arch/powerpc/oprofile/op_model_pa6t.c
===================================================================
--- 2.6.21.orig/arch/powerpc/oprofile/op_model_pa6t.c
+++ 2.6.21/arch/powerpc/oprofile/op_model_pa6t.c
@@ -109,6 +109,8 @@ static void pa6t_reg_setup(struct op_cou
 			pr_debug("turned off counter %u\n", pmc);
 		}
 
+	sys->mmcr0 |= PA6T_MMCR0_FCM1;
+
 	if (sys->enable_kernel)
 		sys->mmcr0 |= PA6T_MMCR0_SUPEN | PA6T_MMCR0_HYPEN;
 	else

--

^ permalink raw reply

* [patch 33/35] Work around errata 5667
From: Olof Johansson @ 2007-07-05 17:03 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20070705170233.258351000@lixom.net>

Always keep a page mapped at EA 0. Right now it is shared among all
processes, as long as noone does a NULL pointer deref and uses the data
there, there should be no security implications. Still, this is better
not used in any kind of environment where users can't be trusted.


Index: mainline/arch/powerpc/kernel/process.c
===================================================================
--- mainline.orig/arch/powerpc/kernel/process.c
+++ mainline/arch/powerpc/kernel/process.c
@@ -330,6 +330,14 @@ struct task_struct *__switch_to(struct t
 	calculate_steal_time();
 
 	last = _switch(old_thread, new_thread);
+	/* current is still really us, just a different us :-) */
+	if (current->mm) {
+#ifdef CONFIG_PPC_HAS_HASH_64K
+		__hash_page_64K(0, _PAGE_USER|_PAGE_RW, get_vsid(current->mm->context.id, 0), &current->zero_pte.pte, 0x300, 1);
+#else
+		__hash_page_4K(0, _PAGE_USER|_PAGE_RW, get_vsid(current->mm->context.id, 0), &current->zero_pte, 0x300, 1);
+#endif
+	}
 
 	local_irq_restore(flags);
 
Index: mainline/kernel/fork.c
===================================================================
--- mainline.orig/kernel/fork.c
+++ mainline/kernel/fork.c
@@ -104,8 +104,12 @@ struct kmem_cache *vm_area_cachep;
 /* SLAB cache for mm_struct structures (tsk->mm) */
 static struct kmem_cache *mm_cachep;
 
+static struct page *zero_page;
+
 void free_task(struct task_struct *tsk)
 {
+	if (tsk->mm)
+		flush_hash_page(get_vsid(tsk->mm->context.id, 0) << 28, tsk->zero_pte, MMU_PAGE_4K, 0);
 	free_thread_info(tsk->stack);
 	rt_mutex_debug_task_free(tsk);
 	free_task_struct(tsk);
@@ -156,6 +160,8 @@ void __init fork_init(unsigned long memp
 	init_task.signal->rlim[RLIMIT_NPROC].rlim_max = max_threads/2;
 	init_task.signal->rlim[RLIMIT_SIGPENDING] =
 		init_task.signal->rlim[RLIMIT_NPROC];
+
+	zero_page = alloc_page(GFP_KERNEL);
 }
 
 static struct task_struct *dup_task_struct(struct task_struct *orig)
@@ -182,6 +188,11 @@ static struct task_struct *dup_task_stru
 #ifdef CONFIG_CC_STACKPROTECTOR
 	tsk->stack_canary = get_random_int();
 #endif
+#ifdef CONFIG_PPC_64K_PAGES
+	tsk->zero_pte.pte = mk_pte(zero_page,_PAGE_BASE|_PAGE_RW|_PAGE_USER|_PAGE_EXEC);
+#else
+	tsk->zero_pte = mk_pte(zero_page,_PAGE_BASE|_PAGE_RW|_PAGE_USER|_PAGE_EXEC);
+#endif
 
 	/* One for us, one for whoever does the "release_task()" (usually parent) */
 	atomic_set(&tsk->usage,2);
Index: mainline/include/linux/sched.h
===================================================================
--- mainline.orig/include/linux/sched.h
+++ mainline/include/linux/sched.h
@@ -863,6 +863,7 @@ struct task_struct {
 	struct list_head ptrace_list;
 
 	struct mm_struct *mm, *active_mm;
+	real_pte_t zero_pte;
 
 /* task state */
 	struct linux_binfmt *binfmt;

--

^ permalink raw reply

* [patch 26/35] Work around errata 4713
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20070705170233.258351000@lixom.net>

Workaround for errata 4713: Concurrent access to some of the devices
in the SOC will result in a bus hang.

To avoid this, we introduce the lbi_lock, and grab it in the drivers
in question. Not a pretty solution, but adequate for now.


Index: mainline/arch/powerpc/platforms/pasemi/setup.c
===================================================================
--- mainline.orig/arch/powerpc/platforms/pasemi/setup.c
+++ mainline/arch/powerpc/platforms/pasemi/setup.c
@@ -42,6 +42,8 @@
 static void __iomem *reset_reg;
 void __iomem *mem_errsta0, *mem_errsta1;
 
+DEFINE_SPINLOCK(lbi_lock);
+
 static void pas_restart(char *cmd)
 {
 	printk("Restarting...\n");
Index: mainline/drivers/i2c/busses/i2c-pasemi.c
===================================================================
--- mainline.orig/drivers/i2c/busses/i2c-pasemi.c
+++ mainline/drivers/i2c/busses/i2c-pasemi.c
@@ -59,17 +59,24 @@ struct pasemi_smbus {
 #define CLK_100K_DIV	84
 #define CLK_400K_DIV	21
 
+extern spinlock_t lbi_lock;
+
 static inline void reg_write(struct pasemi_smbus *smbus, int reg, int val)
 {
+	int flags;
 	dev_dbg(&smbus->dev->dev, "smbus write reg %lx val %08x\n",
 		smbus->base + reg, val);
+	spin_lock_irqsave(&lbi_lock, flags);
 	outl(val, smbus->base + reg);
+	spin_unlock_irqrestore(&lbi_lock, flags);
 }
 
 static inline int reg_read(struct pasemi_smbus *smbus, int reg)
 {
-	int ret;
+	int ret, flags;
+	spin_lock_irqsave(&lbi_lock, flags);
 	ret = inl(smbus->base + reg);
+	spin_unlock_irqrestore(&lbi_lock, flags);
 	dev_dbg(&smbus->dev->dev, "smbus read reg %lx val %08x\n",
 		smbus->base + reg, ret);
 	return ret;
Index: mainline/drivers/serial/8250.c
===================================================================
--- mainline.orig/drivers/serial/8250.c
+++ mainline/drivers/serial/8250.c
@@ -342,39 +342,51 @@ static inline int map_8250_out_reg(struc
 
 #endif
 
+extern spinlock_t lbi_lock;
+
 static unsigned int serial_in(struct uart_8250_port *up, int offset)
 {
 	unsigned int tmp;
+	int ret, flags;
 	offset = map_8250_in_reg(up, offset) << up->port.regshift;
 
+	spin_lock_irqsave(&lbi_lock, flags);
 	switch (up->port.iotype) {
 	case UPIO_HUB6:
 		outb(up->port.hub6 - 1 + offset, up->port.iobase);
-		return inb(up->port.iobase + 1);
+		ret = inb(up->port.iobase + 1);
+		break;
 
 	case UPIO_MEM:
 	case UPIO_DWAPB:
-		return readb(up->port.membase + offset);
+		ret = readb(up->port.membase + offset);
+		break;
 
 	case UPIO_RM9000:
 	case UPIO_MEM32:
-		return readl(up->port.membase + offset);
+		ret = readl(up->port.membase + offset);
+		break;
 
 #ifdef CONFIG_SERIAL_8250_AU1X00
 	case UPIO_AU:
-		return __raw_readl(up->port.membase + offset);
+		ret = __raw_readl(up->port.membase + offset);
+		break;
 #endif
 
 	case UPIO_TSI:
 		if (offset == UART_IIR) {
 			tmp = readl(up->port.membase + (UART_IIR & ~3));
-			return (tmp >> 16) & 0xff; /* UART_IIR % 4 == 2 */
+			ret = (tmp >> 16) & 0xff; /* UART_IIR % 4 == 2 */
 		} else
-			return readb(up->port.membase + offset);
+			ret = readb(up->port.membase + offset);
+		break;
 
 	default:
-		return inb(up->port.iobase + offset);
+		ret = inb(up->port.iobase + offset);
+		break;
 	}
+	spin_unlock_irqrestore(&lbi_lock, flags);
+	return ret;
 }
 
 static void
@@ -382,8 +394,10 @@ serial_out(struct uart_8250_port *up, in
 {
 	/* Save the offset before it's remapped */
 	int save_offset = offset;
+	int flags;
 	offset = map_8250_out_reg(up, offset) << up->port.regshift;
 
+	spin_lock_irqsave(&lbi_lock, flags);
 	switch (up->port.iotype) {
 	case UPIO_HUB6:
 		outb(up->port.hub6 - 1 + offset, up->port.iobase);
@@ -424,6 +438,7 @@ serial_out(struct uart_8250_port *up, in
 	default:
 		outb(value, up->port.iobase + offset);
 	}
+	spin_unlock_irqrestore(&lbi_lock, flags);
 }
 
 static void
@@ -1239,10 +1254,7 @@ static void serial8250_start_tx(struct u
 			unsigned char lsr, iir;
 			lsr = serial_in(up, UART_LSR);
 			iir = serial_in(up, UART_IIR) & 0x0f;
-			if ((up->port.type == PORT_RM9000) ?
-				(lsr & UART_LSR_THRE &&
-				(iir == UART_IIR_NO_INT || iir == UART_IIR_THRI)) :
-				(lsr & UART_LSR_TEMT && !(iir & UART_IIR_NO_INT)))
+			if (lsr & UART_LSR_TEMT && !(iir & UART_IIR_NO_INT))
 				transmit_chars(up);
 		}
 	}
@@ -1879,7 +1891,7 @@ static int serial8250_startup(struct uar
 	if (lsr & UART_LSR_TEMT && !(iir & UART_IIR_NO_INT)) {
 		if (!(up->bugs & UART_BUG_TXEN)) {
 			up->bugs |= UART_BUG_TXEN;
-			pr_debug("ttyS%d - enabling bad tx status workarounds\n",
+			printk("ttyS%d - enabling bad tx status workarounds\n",
 				 port->line);
 		}
 	} else {
Index: mainline/arch/powerpc/kernel/iomap.c
===================================================================
--- mainline.orig/arch/powerpc/kernel/iomap.c
+++ mainline/arch/powerpc/kernel/iomap.c
@@ -8,29 +8,51 @@
 #include <linux/mm.h>
 #include <asm/io.h>
 
+extern spinlock_t lbi_lock;
+
 /*
  * Here comes the ppc64 implementation of the IOMAP 
  * interfaces.
  */
 unsigned int ioread8(void __iomem *addr)
 {
-	return readb(addr);
+	int ret, flags;
+	spin_lock_irqsave(&lbi_lock, flags);
+	ret = readb(addr);
+	spin_unlock_irqrestore(&lbi_lock, flags);
+	return ret;
 }
 unsigned int ioread16(void __iomem *addr)
 {
-	return readw(addr);
+	int ret, flags;
+	spin_lock_irqsave(&lbi_lock, flags);
+	ret = readw(addr);
+	spin_unlock_irqrestore(&lbi_lock, flags);
+	return ret;
 }
 unsigned int ioread16be(void __iomem *addr)
 {
-	return in_be16(addr);
+	int ret, flags;
+	spin_lock_irqsave(&lbi_lock, flags);
+	ret = in_be16(addr);
+	spin_unlock_irqrestore(&lbi_lock, flags);
+	return ret;
 }
 unsigned int ioread32(void __iomem *addr)
 {
-	return readl(addr);
+	int ret, flags;
+	spin_lock_irqsave(&lbi_lock, flags);
+	ret = readl(addr);
+	spin_unlock_irqrestore(&lbi_lock, flags);
+	return ret;
 }
 unsigned int ioread32be(void __iomem *addr)
 {
-	return in_be32(addr);
+	int ret, flags;
+	spin_lock_irqsave(&lbi_lock, flags);
+	ret = in_be32(addr);
+	spin_unlock_irqrestore(&lbi_lock, flags);
+	return ret;
 }
 EXPORT_SYMBOL(ioread8);
 EXPORT_SYMBOL(ioread16);
@@ -40,23 +62,38 @@ EXPORT_SYMBOL(ioread32be);
 
 void iowrite8(u8 val, void __iomem *addr)
 {
+	int flags;
+	spin_lock_irqsave(&lbi_lock, flags);
 	writeb(val, addr);
+	spin_unlock_irqrestore(&lbi_lock, flags);
 }
 void iowrite16(u16 val, void __iomem *addr)
 {
+	int ret, flags;
+	spin_lock_irqsave(&lbi_lock, flags);
 	writew(val, addr);
+	spin_unlock_irqrestore(&lbi_lock, flags);
 }
 void iowrite16be(u16 val, void __iomem *addr)
 {
+	int flags;
+	spin_lock_irqsave(&lbi_lock, flags);
 	out_be16(addr, val);
+	spin_unlock_irqrestore(&lbi_lock, flags);
 }
 void iowrite32(u32 val, void __iomem *addr)
 {
+	int flags;
+	spin_lock_irqsave(&lbi_lock, flags);
 	writel(val, addr);
+	spin_unlock_irqrestore(&lbi_lock, flags);
 }
 void iowrite32be(u32 val, void __iomem *addr)
 {
+	int flags;
+	spin_lock_irqsave(&lbi_lock, flags);
 	out_be32(addr, val);
+	spin_unlock_irqrestore(&lbi_lock, flags);
 }
 EXPORT_SYMBOL(iowrite8);
 EXPORT_SYMBOL(iowrite16);
@@ -74,15 +111,24 @@ EXPORT_SYMBOL(iowrite32be);
  */
 void ioread8_rep(void __iomem *addr, void *dst, unsigned long count)
 {
+	int flags;
+	spin_lock_irqsave(&lbi_lock, flags);
 	_insb((u8 __iomem *) addr, dst, count);
+	spin_unlock_irqrestore(&lbi_lock, flags);
 }
 void ioread16_rep(void __iomem *addr, void *dst, unsigned long count)
 {
+	int flags;
+	spin_lock_irqsave(&lbi_lock, flags);
 	_insw_ns((u16 __iomem *) addr, dst, count);
+	spin_unlock_irqrestore(&lbi_lock, flags);
 }
 void ioread32_rep(void __iomem *addr, void *dst, unsigned long count)
 {
+	int flags;
+	spin_lock_irqsave(&lbi_lock, flags);
 	_insl_ns((u32 __iomem *) addr, dst, count);
+	spin_unlock_irqrestore(&lbi_lock, flags);
 }
 EXPORT_SYMBOL(ioread8_rep);
 EXPORT_SYMBOL(ioread16_rep);
@@ -90,15 +136,24 @@ EXPORT_SYMBOL(ioread32_rep);
 
 void iowrite8_rep(void __iomem *addr, const void *src, unsigned long count)
 {
+	int flags;
+	spin_lock_irqsave(&lbi_lock, flags);
 	_outsb((u8 __iomem *) addr, src, count);
+	spin_unlock_irqrestore(&lbi_lock, flags);
 }
 void iowrite16_rep(void __iomem *addr, const void *src, unsigned long count)
 {
+	int flags;
+	spin_lock_irqsave(&lbi_lock, flags);
 	_outsw_ns((u16 __iomem *) addr, src, count);
+	spin_unlock_irqrestore(&lbi_lock, flags);
 }
 void iowrite32_rep(void __iomem *addr, const void *src, unsigned long count)
 {
+	int flags;
+	spin_lock_irqsave(&lbi_lock, flags);
 	_outsl_ns((u32 __iomem *) addr, src, count);
+	spin_unlock_irqrestore(&lbi_lock, flags);
 }
 EXPORT_SYMBOL(iowrite8_rep);
 EXPORT_SYMBOL(iowrite16_rep);

--

^ permalink raw reply

* [patch 29/35] Work around errata 4910
From: Olof Johansson @ 2007-07-05 17:03 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20070705170233.258351000@lixom.net>

Don't allow unguarded mappings in PCI-express space. This is resolves
problems with frame buffers having garbage on them due to failing
write merges.


Index: 2.6.21/arch/powerpc/mm/hash_native_64.c
===================================================================
--- 2.6.21.orig/arch/powerpc/mm/hash_native_64.c
+++ 2.6.21/arch/powerpc/mm/hash_native_64.c
@@ -152,6 +152,10 @@ static long native_hpte_insert(unsigned 
 	if (i == HPTES_PER_GROUP)
 		return -1;
 
+	/* Workaround for bug 4910: No non-guarded access over IOB */
+	if (pa >= 0x80000000 && pa < 0x100000000)
+		rflags |= _PAGE_GUARDED;
+
 	hpte_v = hpte_encode_v(va, psize) | vflags | HPTE_V_VALID;
 	hpte_r = hpte_encode_r(pa, psize) | rflags;
 

--

^ permalink raw reply

* [patch 30/35] Disable PURR on pa6t
From: Olof Johansson @ 2007-07-05 17:03 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20070705170233.258351000@lixom.net>

Our PURR ticks at the wrong rate (same as the decrementer). Since it
doesn't really have any value-add besides on partitioned and multithreaded
systems, refrain from using it at the moment.


Index: 2.6.21/include/asm-powerpc/cputable.h
===================================================================
--- 2.6.21.orig/include/asm-powerpc/cputable.h
+++ 2.6.21/include/asm-powerpc/cputable.h
@@ -356,7 +356,7 @@ extern void do_feature_fixups(unsigned l
 #define CPU_FTRS_PA6T (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
 	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_CI_LARGE_PAGE | \
-	    CPU_FTR_PURR | CPU_FTR_REAL_LE)
+	    CPU_FTR_REAL_LE)
 #define CPU_FTRS_COMPATIBLE	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2)
 

--

^ permalink raw reply

* [patch 34/35] Work around errata 4505
From: Olof Johansson @ 2007-07-05 17:03 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20070705170233.258351000@lixom.net>

Workaround for Errata 4504: PMC0 doesn't seem to set SIARLOG when
an exception occurs. Instead, log the PC for when we took the actual
exception.



Index: 2.6.21/arch/powerpc/oprofile/op_model_pa6t.c
===================================================================
--- 2.6.21.orig/arch/powerpc/oprofile/op_model_pa6t.c
+++ 2.6.21/arch/powerpc/oprofile/op_model_pa6t.c
@@ -215,6 +215,9 @@ static void pa6t_handle_interrupt(struct
 			if (oprofile_running && ctr[i].enabled) {
 				if (mmcr0 & PA6T_MMCR0_SIARLOG)
 					oprofile_add_ext_sample(pc, regs, i, is_kernel);
+				else if (i < 2)
+					/* PMC0/1 might not set SIARLOG, just log PC at time of fault */
+					oprofile_add_ext_sample(regs->nip, regs, i, is_kernel);
 				ctr_write(i, reset_value[i]);
 			} else {
 				ctr_write(i, 0UL);

--

^ permalink raw reply

* Re: PowerPC equivalent to dma_mmap_writecombine()?
From: Arnd Bergmann @ 2007-07-05 16:13 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Timur Tabi
In-Reply-To: <468D1F23.6000803@freescale.com>

T24gVGh1cnNkYXkgMDUgSnVseSAyMDA3LCBUaW11ciBUYWJpIHdyb3RlOgo+IHN0YXRpYyBpbnQg
YXQ5MV9wY21fbW1hcChzdHJ1Y3Qgc25kX3BjbV9zdWJzdHJlYW0gKnN1YnN0cmVhbSwKPiCgoKCg
oKCgoHN0cnVjdCB2bV9hcmVhX3N0cnVjdCAqdm1hKQo+IHsKPiCgoKCgoKCgoHN0cnVjdCBzbmRf
cGNtX3J1bnRpbWUgKnJ1bnRpbWUgPSBzdWJzdHJlYW0tPnJ1bnRpbWU7Cj4gCj4goKCgoKCgoKBy
ZXR1cm4gZG1hX21tYXBfd3JpdGVjb21iaW5lKHN1YnN0cmVhbS0+cGNtLT5jYXJkLT5kZXYsIHZt
YSwKPiCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoCCgIKAgcnVudGltZS0+ZG1hX2Fy
ZWEsCj4goKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKAgoCCgIHJ1bnRpbWUtPmRtYV9h
ZGRyLAo+IKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgIKAgoCBydW50aW1lLT5kbWFf
Ynl0ZXMpOwo+IH0KPiAKPiBUaGVyZSBhcmUgbm8gZG1hX21tYXBfeCgpIGZ1bmN0aW9ucyBpbiBh
cmNoL3Bvd2VycGMuIKBDYW4gc29tZW9uZSB0ZWxsIG1lIHdoYXQgdGhlIHBvd2VycGMgCj4gZXF1
aXZhbGVudCB0byBkbWFfbW1hcF93cml0ZWNvbWJpbmUoKSBpcz8KCk5vdCBzdXJlIGV4YWN0bHkg
d2hhdCBhcm0gZG9lcyBoZXJlLCBidXQgaXQgc291bmRzIGxpa2UgeW91IHdhbnQKdG8gY2FsbCBy
ZW1hcF9wZm5fcmFuZ2Ugd2l0aCB0aGUgX1BBR0VfTk9fQ0FDSEUgYml0IHNldCBpbiB0aGUKcHJv
dGVjdGlvbiBmbGFncywgYW5kIF9QQUdFX0dVQVJERUQgbm90IHNldC4KCglBcm5kIDw+PAo=

^ permalink raw reply

* Re: OF devices and non OF devices
From: John Rigby @ 2007-07-05 17:20 UTC (permalink / raw)
  To: Kári Davíðsson; +Cc: linuxppc-embedded
In-Reply-To: <4b73d43f0707050628qd9db2afu3b63dd654be32646@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 6725 bytes --]

There must be something else wrong with your configuration.
On my Lite5200B fsl_i2c_probe gets called with no changes to the driver.

The kernel version is 2.6.22-rc7

The relevant part of my device tree is:

        i2c@3d00 {
            device_type = "i2c";
            compatible = "mpc5200b-i2c\0mpc5200-i2c\0fsl-i2c";
            cell-index = <0>;
            reg = <3d00 40>;
            interrupts = <2 f 0>;
            interrupt-parent = <&mpc5200_pic>;
            fsl5200-clocking;
        };

        i2c@3d40 {
            device_type = "i2c";
            compatible = "mpc5200b-i2c\0mpc5200-i2c\0fsl-i2c";
            cell-index = <1>;
            reg = <3d40 40>;
            interrupts = <2 10 0>;
            interrupt-parent = <&mpc5200_pic>;
            fsl5200-clocking;
        };

I turned on DEBUG in drivers/base/dd.c and a call to pr_debug in the probe
routine
and here are the relevant log messages:

[   27.258245] platform: Matched Device fsl-i2c.0 with Driver fsl-i2c
[   27.258269] platform: Probing driver fsl-i2c with device fsl-i2c.0
[   27.258299] I2C: here in fsl_i2c_probe
[   27.258732] bound device 'fsl-i2c.0' to driver 'fsl-i2c'
[   27.258756] platform: Bound Device fsl-i2c.0 to Driver fsl-i2c
[   27.258776] platform: Matched Device fsl-i2c.1 with Driver fsl-i2c
[   27.258789] platform: Probing driver fsl-i2c with device fsl-i2c.1
[   27.258821] I2C: here in fsl_i2c_probe
[   27.259269] bound device 'fsl-i2c.1' to driver 'fsl-i2c'
[   27.259293] platform: Bound Device fsl-i2c.1 to Driver fsl-i2c

John

On 7/5/07, John Rigby <jcrigby@gmail.com> wrote:
>
> kd,
>
> Ok, obviously It doesn't work the way I thought.  Hopefully someone who
> does
> understand this will comment.
>
> John
>
> On 7/4/07, Kári Davíðsson <kari.davidsson@marel.is> wrote:
> >
> > John, thank you for your answare.
> >
> > Enabling CONFIG_FSL_SOC only enabled the execution of the init function
> > (fsl_i2c_init())
> > of the fsl-i2c driver (i2c-mpc.c). The .probe function of the driver was
> > never called
> > until I converted the driver to the OF model and added the .match_table
> > to the driver structure.
> >
> > Then I get the .probe function (fsl_i2c_probe()) called and the i2c bus
> > set up.
> >
> > Similar thing happens for the i2c device PCF8563 i.e., the init functin
> > of the driver (pcf8563_init())
> > is called the driver is registered with the kernel, but the .probe
> > (pcf8563_probe()) is never called.
> >
> > The driver pcf8563 has _NO_ exported structures or functions so I
> > basically have no handle on it
> > that I can utilize in board specific setup.
> >
> > The way I suspect this is supposed to work is that from the board settup
> > files I would do
> > rtc_dev = platform_device_register_simple("pcf8563", -1, NULL, 0);
> > which should later trigger the calling of the pcf8563_probe() function.
> >
> > This is doing things in the same way as the fsl i2c code, i.e.
> > i2c_dev = platform_device_register_simple("i2c", i, r, 2);
> > which by the way does not work untill I have converted the fsl_i2c (
> > i2c-mpc.c) driver to the OF structure.
> >
> > So still the method of gluing together the OF drivers and non OF drivers
> > eludes me.
> >
> > rg
> > kd
> >
> > P.S. I did check the 2.6.21-RC7-git3 and found that the i2c-mpc.c and
> > the rtc-pcf85763.c are basically the same
> > as what I am working with in 2.6.20+
> > ________________________________
> >
> > From: John Rigby [mailto: jcrigby@gmail.com]
> > Sent: 3. júlí 2007 16:31
> > To: Kári Davíðsson
> > Cc: linuxppc-embedded@ozlabs.org
> > Subject: Re: OF devices and non OF devices
> >
> >
> > One place to find binding between OF devices and non OF devices is in
> > arch/powerpc/sysdev/fsl_soc.c
> > The typical pattern is:
> >     if of_find_compatible_node "of-device-name"
> >         platform_device_register_simple ""platform-device-name"
> >         platform_device_add_data ...
> >
> >
> >
> > On 7/3/07, Kári Davíðsson <kari.davidsson@marel.is> wrote:
> >
> >         Hi,
> >
> >         I am attempting to get some non OF devices working for an mpc
> > 5200 board, in particular
> >         PCF8563 RTC.
> >
> >         This device has an non OF device interface which I believe is
> > correct. After all it should work
> >         on non OF platforms.
> >
> >         I have managed to get the board to run the i2c initialization
> > (and probe) for the fsl-mpc i2c driver by
> >         converting the fsl-mpc i2c driver to OF driver (I found some
> > patch here that I based this work on).
> >
> >
> > fsl-i2c is one of the devices handled by fsl_soc.c so you shouldn't need
> > to change anything to
> > make it work in the latest kernel.  CONFIG_FSL_SOC was only added to
> > lite5200_defconfig recently so
> > that may explain why it's not on in your kernel.
> >
> >
> >
> >         Since the PCF8563 driver is not OF driver only its
> > initaliziation code is run but the .probe function
> >         of the driver is never run. Basically (as far as I can
> > understand) the .probe is never run because the
> >         driver is not an OF driver.
> >
> >         I could convert the PCF8563 driver to OF driver and make it work
> > for our puposes but I feel this is
> >         1) Wrong
> >         2) therefore wasted work.
> >
> >
> > Since the driver must run on non OF platforms then it should not be
> > converted.  You just need to add a platform_device_register somewhere.
> > I don't think fsl_soc.c is  the right place since it is not part of an
> > freescale SOC.
> > You could probably put it in a board specific startup routine.
> >
> >
> >
> >         What seems to elude me is some glue that glues together the OF
> > part of the driver space to the non OF part
> >         of the driver space.
> >
> >         Any hints or pointers on where to find this glue?
> >
> >         Regards,
> >         kd
> >
> >         P.S. Kernel is post 2.6.20.
> >
> >         --
> >         Kári Davíðsson                   | kari.davidsson@marel.is
> >         Hugbúnaðargerð                   | www.marel.com
> >         Tel: 563-8156 Fax: +354 563 8001
> >         Iceland
> >         _______________________________________________
> >         Linuxppc-embedded mailing list
> >         Linuxppc-embedded@ozlabs.org
> >         https://ozlabs.org/mailman/listinfo/linuxppc-embedded
> >
> >
> >
> > _______________________________________________
> > Linuxppc-embedded mailing list
> > Linuxppc-embedded@ozlabs.org
> > https://ozlabs.org/mailman/listinfo/linuxppc-embedded
> >
>
>

[-- Attachment #2: Type: text/html, Size: 10840 bytes --]

^ permalink raw reply

* Re: [PATCH]: PCI Error Recovery: Symbios SCSI device driver
From: Andrew Morton @ 2007-07-05 18:28 UTC (permalink / raw)
  To: Linas Vepstas
  Cc: James.Bottomley, linux-scsi, matthew, willy, linux-kernel,
	linuxppc-dev, Paul Mackerras, linux-pci
In-Reply-To: <20070702183917.GJ4501@austin.ibm.com>

On Mon, 2 Jul 2007 13:39:17 -0500
linas@austin.ibm.com (Linas Vepstas) wrote:

> 
> Various PCI bus errors can be signaled by newer PCI controllers.  
> This patch adds the PCI error recovery callbacks to the Symbios 
> SCSI device driver.  The patch has been tested, and appears to 
> work well.
> 

yup, this is identical to -mm's
pci-error-recovery-symbios-scsi-base-support.patch

What is the status of
ftp://ftp.kernel.org/pub/linux/kernel/people/akpm/patches/2.6/2.6.22-rc6/2.6.22-rc6-mm1/broken-out/pci-error-recovery-symbios-scsi-first-failure.patch?

> 
> ----
> 
> Hi,
> 
> This patch has been bouncing around for a long time, and has made
> appearences in various -mm trees since 2.6.something-teen. However,
> it has never made it into mainline, and I'm starting to get concerned
> that it will miss 2.6.23 as well. 

Well you've sent it a couple of times, and I've sent it in five more times
over the past year.  Once we were told "awaiting maintainer ack".

This situation is fairly stupid.  How about we make you the maintainer?

^ permalink raw reply

* Re: [patch 27/35] Work around errata 4290
From: Gabriel Paubert @ 2007-07-05 18:50 UTC (permalink / raw)
  To: Olof Johansson; +Cc: linuxppc-dev
In-Reply-To: <20070705170240.803460000@lixom.net>

On Thu, Jul 05, 2007 at 12:03:00PM -0500, Olof Johansson wrote:
> Workaround for errata 4290: The decrementer ticks at half the expected rate
> so load it with half the value it would otherwise be loaded with.
> 
> 
> Index: 2.6.21/include/asm-powerpc/time.h
> ===================================================================
> --- 2.6.21.orig/include/asm-powerpc/time.h
> +++ 2.6.21/include/asm-powerpc/time.h
> @@ -173,6 +173,13 @@ static inline unsigned int get_dec(void)
>  
>  static inline void set_dec(int val)
>  {
> +#ifdef CONFIG_PPC_PASEMI
> +	/* PA6T rev Ax have decrementer ticking at 1/2 tb rate */
> +	val >>= 2;

Comment does not match code: looks like a divide by 4 to me!

> +	if (!val)
> +		val = 1;
> +#endif
> +
>  #if defined(CONFIG_40x)
>  	return;		/* Have to let it auto-reload */
>  #elif defined(CONFIG_8xx_CPU6)

	Gabriel

^ permalink raw reply

* Re: [patch 27/35] Work around errata 4290
From: Olof Johansson @ 2007-07-05 19:26 UTC (permalink / raw)
  To: Gabriel Paubert; +Cc: linuxppc-dev
In-Reply-To: <20070705185021.GA26069@iram.es>

On Thu, Jul 05, 2007 at 08:50:21PM +0200, Gabriel Paubert wrote:
> On Thu, Jul 05, 2007 at 12:03:00PM -0500, Olof Johansson wrote:
> > Workaround for errata 4290: The decrementer ticks at half the expected rate
> > so load it with half the value it would otherwise be loaded with.
> > 
> > 
> > Index: 2.6.21/include/asm-powerpc/time.h
> > ===================================================================
> > --- 2.6.21.orig/include/asm-powerpc/time.h
> > +++ 2.6.21/include/asm-powerpc/time.h
> > @@ -173,6 +173,13 @@ static inline unsigned int get_dec(void)
> >  
> >  static inline void set_dec(int val)
> >  {
> > +#ifdef CONFIG_PPC_PASEMI
> > +	/* PA6T rev Ax have decrementer ticking at 1/2 tb rate */
> > +	val >>= 2;
> 
> Comment does not match code: looks like a divide by 4 to me!

You're right. Thanks for catching it.

Never caught it because the timer code behaves just fine anyway, but
it'll waste power by waking up twice as often when idle.


-Olof

^ permalink raw reply

* Re: [PATCH]: PCI Error Recovery: Symbios SCSI device driver
From: Matthew Wilcox @ 2007-07-05 18:54 UTC (permalink / raw)
  To: Andrew Morton
  Cc: James.Bottomley, linux-scsi, willy, linux-kernel, linuxppc-dev,
	Paul Mackerras, linux-pci
In-Reply-To: <20070705112838.2d8c959b.akpm@linux-foundation.org>

On Thu, Jul 05, 2007 at 11:28:38AM -0700, Andrew Morton wrote:
> Well you've sent it a couple of times, and I've sent it in five more times
> over the past year.  Once we were told "awaiting maintainer ack".
> 
> This situation is fairly stupid.  How about we make you the maintainer?

Last time I looked at it, I still wasn't comfortable with it.  I'm going
to look at it again.

I'm fairly sure Linas doesn't want to be the sym2 maintainer.  It's
still an ugly pile of junk that needs cleaning up.

-- 
"Bill, look, we understand that you're interested in selling us this
operating system, but compare it to ours.  We can't possibly take such
a retrograde step."

^ permalink raw reply

* Re: powerpc stacktrace and lockdep support
From: Sergei Shtylyov @ 2007-07-05 19:26 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linuxppc-dev, Christoph Hellwig
In-Reply-To: <1183047642.3735.0.camel@johannes.berg>

Johannes Berg wrote:
> This one doesn't break 32-bit build by simply disabling irqtrace for
> 32-bit.

> --- linux-2.6-git32.orig/include/asm-powerpc/hw_irq.h	2007-06-28 14:53:58.730430447 +0200
> +++ linux-2.6-git32/include/asm-powerpc/hw_irq.h	2007-06-28 14:58:41.508430447 +0200
> @@ -27,7 +27,7 @@ static inline unsigned long local_get_fl
>  	return flags;
>  }
>  
> -static inline unsigned long local_irq_disable(void)
> +static inline unsigned long raw_local_irq_disable(void)
>  {
>  	unsigned long flags, zero;
>  
> @@ -39,14 +39,15 @@ static inline unsigned long local_irq_di
>  	return flags;
>  }
>  
> -extern void local_irq_restore(unsigned long);
> +extern void raw_local_irq_restore(unsigned long);
>  extern void iseries_handle_interrupts(void);
>  
> -#define local_irq_enable()	local_irq_restore(1)
> -#define local_save_flags(flags)	((flags) = local_get_flags())
> -#define local_irq_save(flags)	((flags) = local_irq_disable())
> +#define raw_local_irq_enable()	raw_local_irq_restore(1)
> +#define raw_local_save_flags(flags)	((flags) = local_get_flags())
> +#define raw_local_irq_save(flags)	((flags) = raw_local_irq_disable())
>  
> -#define irqs_disabled()		(local_get_flags() == 0)
> +#define raw_irqs_disabled()		(local_get_flags() == 0)
> +#define raw_irqs_disabled_flags(flags)		((flags) == 0)
>  
>  #define __hard_irq_enable()	__mtmsrd(mfmsr() | MSR_EE, 1)
>  #define __hard_irq_disable()	__mtmsrd(mfmsr() & ~MSR_EE, 1)
> @@ -108,6 +109,7 @@ static inline void local_irq_save_ptr(un
>  #define local_save_flags(flags)	((flags) = mfmsr())
>  #define local_irq_save(flags)	local_irq_save_ptr(&flags)
>  #define irqs_disabled()		((mfmsr() & MSR_EE) == 0)
> +#define irqs_disabled_flags(flags)		(((flags) & MSR_EE) == 0)
>  
>  #define hard_irq_enable()	local_irq_enable()
>  #define hard_irq_disable()	local_irq_disable()
> --- linux-2.6-git32.orig/include/asm-powerpc/irqflags.h	2007-06-28 14:53:58.779430447 +0200
> +++ linux-2.6-git32/include/asm-powerpc/irqflags.h	2007-06-28 14:52:51.821430447 +0200
> @@ -15,17 +15,4 @@
>   */
>  #include <asm-powerpc/hw_irq.h>
>  
> -/*
> - * Do the CPU's IRQ-state tracing from assembly code. We call a
> - * C function, so save all the C-clobbered registers:
> - */
> -#ifdef CONFIG_TRACE_IRQFLAGS
> -
> -#error No support on PowerPC yet for CONFIG_TRACE_IRQFLAGS
> -
> -#else
> -# define TRACE_IRQS_ON
> -# define TRACE_IRQS_OFF
> -#endif
> -
>  #endif

    I suggest to also remove these 3 lines from the heading comment in this 
file -- they're not true anyway:

  * This file gets included from lowlevel asm headers too, to provide
  * wrapped versions of the local_irq_*() APIs, based on the
  * raw_local_irq_*() macros from the lowlevel headers.

> --- linux-2.6-git32.orig/arch/powerpc/kernel/head_64.S	2007-06-28 14:53:58.679430447 +0200
> +++ linux-2.6-git32/arch/powerpc/kernel/head_64.S	2007-06-28 14:48:33.858430447 +0200
> @@ -394,6 +394,12 @@ label##_iSeries:							\
>  	EXCEPTION_PROLOG_ISERIES_2;					\
>  	b	label##_common;						\
>  
> +#ifdef CONFIG_TRACE_IRQFLAGS
> +#define TRACE_DISABLE_INTS bl .powerpc_trace_hardirqs_off
> +#else
> +#define TRACE_DISABLE_INTS
> +#endif
> +

    Erm, weren't those supposed to be in <asm-powerpc/irqflags.h>?

>  #ifdef CONFIG_PPC_ISERIES
>  #define DISABLE_INTS				\
>  	li	r11,0;				\
> @@ -405,14 +411,15 @@ BEGIN_FW_FTR_SECTION;				\
>  	mfmsr	r10;				\
>  	ori	r10,r10,MSR_EE;			\
>  	mtmsrd	r10,1;				\
> -END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
> +END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES);	\
> +	TRACE_DISABLE_INTS
>  
>  #else
>  #define DISABLE_INTS				\
>  	li	r11,0;				\
>  	stb	r11,PACASOFTIRQEN(r13);		\
> -	stb	r11,PACAHARDIRQEN(r13)
> -
> +	stb	r11,PACAHARDIRQEN(r13);		\
> +	TRACE_DISABLE_INTS
>  #endif /* CONFIG_PPC_ISERIES */
>  
>  #define ENABLE_INTS				\
> @@ -965,24 +972,38 @@ bad_stack:

    The following code seemed over-engineered:

>   */
>  fast_exc_return_irq:			/* restores irq state too */
>  	ld	r3,SOFTE(r1)
> -	ld	r12,_MSR(r1)
> +#ifdef CONFIG_TRACE_IRQFLAGS
> +	cmpdi	r3,0
> +	beq	1f
> +	bl	.trace_hardirqs_on

	b 	2f
1:

> +	bl	.trace_hardirqs_off

2:

> +	ld	r3,SOFTE(r1)
> +#endif
	stb	r3,PACASOFTIRQEN(r13)	/* restore paca->soft_enabled */
> +	ld	r12,_MSR(r1)
>  	rldicl	r4,r12,49,63		/* get MSR_EE to LSB */
>  	stb	r4,PACAHARDIRQEN(r13)	/* restore paca->hard_enabled */
> -	b	1f
> +	b	3f

[...]

> --- linux-2.6-git32.orig/arch/powerpc/kernel/entry_64.S	2007-06-28 14:53:58.729430447 +0200
> +++ linux-2.6-git32/arch/powerpc/kernel/entry_64.S	2007-06-28 14:49:13.125430447 +0200
[...]
> @@ -491,8 +498,20 @@ BEGIN_FW_FTR_SECTION
>  4:
>  END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
>  #endif
> +#ifdef CONFIG_TRACE_IRQFLAGS
> +	cmpdi	r5,0
> +	beq	5f
> +	bl	.trace_hardirqs_on
> +	ld	r5,SOFTE(r1)
>  	stb	r5,PACASOFTIRQEN(r13)
> -
> +	b	6f
> +5:
> +	stb	r5,PACASOFTIRQEN(r13)
> +	bl	.trace_hardirqs_off
> +6:
> +#else
> +	stb	r5,PACASOFTIRQEN(r13)
> +#endif

    Again, could have been more compact... unless trace_hardirqs_*() calls 
need to be in certain order WRT writes to PACASOFTIRQEN -- if so, in the 1st 
case that I've pointed out the order was not identical (probably wrong?)...

> --- /dev/null	1970-01-01 00:00:00.000000000 +0000
> +++ linux-2.6-git32/arch/powerpc/kernel/irqtrace.S	2007-06-28 14:49:25.754430447 +0200
> @@ -0,0 +1,47 @@
> +/*
> + * crappy helper for irq-trace
> + */
> +
> +#include <asm/ppc_asm.h>
> +#include <asm/asm-offsets.h>
> +
> +#define STACKSPACE	GPR0 + 16*8

    I guess this should be 16*4 for PPC32.

> +
> +#ifdef __powerpc64__
> +#define ST	std
> +#define L	ld
> +#else
> +#define ST	stw
> +#define L	lw
> +#endif
> +
> +#define PRE				\
> +	subi	r1,r1,STACKSPACE ;	\
> +	SAVE_GPR(0, r1) ;		\
> +	SAVE_8GPRS(2, r1) ;		\
> +	SAVE_4GPRS(10, r1) ;		\
> +	mfcr	r0 ;			\
> +	ST	r0, (14*8)(r1) ;	\
> +	mflr	r0 ;			\
> +	ST	r0, (15*8)(r1)

    Didn't you forget to add GPR0 to the offsets here?

> +#define POST				\
> +	REST_8GPRS(2, r1) ;		\
> +	REST_4GPRS(10, r1) ;		\
> +	L	r0, (14*8)(r1) ;	\
> +	mtcr	r0 ;			\
> +	L	r0, (15*8)(r1) ;	\
> +	mtlr	r0 ;			\
> +	REST_GPR(0, r1) ;		\
> +	addi	r1,r1,STACKSPACE

    You certainly did. I bet you're clobbering GPR11/12 (if I didn't miscount)...

WBR, Sergei

^ permalink raw reply

* Re: PowerPC equivalent to dma_mmap_writecombine()?
From: Segher Boessenkool @ 2007-07-05 20:11 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: linuxppc-dev, Timur Tabi
In-Reply-To: <200707051813.53762.arnd@arndb.de>

>> There are no dma_mmap_x() functions in arch/powerpc.  Can someone  
>> tell me what the powerpc
>> equivalent to dma_mmap_writecombine() is?
>
> Not sure exactly what arm does here, but it sounds like you want
> to call remap_pfn_range with the _PAGE_NO_CACHE bit set in the
> protection flags, and _PAGE_GUARDED not set.

Either that, or just map it as normal cache-coherent DMA
memory.


Segher

^ permalink raw reply

* Re: Porting Linux to Xilinx ML410
From: khollan @ 2007-07-05 20:23 UTC (permalink / raw)
  To: linuxppc-embedded
In-Reply-To: <fa686aa40707021551y469e1b7fv3b8c329b904b3d6@mail.gmail.com>


Thanks I fixed the error, my system ace hardware wasn't working correctly.
Now I have a new problem during the init process.  It gives me this message

Starting pid 213 tty '': '/sbin/getty'
process '/sbin/getty 9600 ttyUL0 (pid 213) exited. Scheduling it for
restart.

And it tries to respawn it indefinetly.
If I pass the kernel command Init=/bin/sh I can get into the shell correctly
Any Ideas what this problem is?
Thanks for your help
Kevin
-- 
View this message in context: http://www.nabble.com/Porting-Linux-to-Xilinx-ML410-tf3989483.html#a11453962
Sent from the linuxppc-embedded mailing list archive at Nabble.com.

^ permalink raw reply

* + add-missing-data_data-in-powerpc.patch added to -mm tree
From: akpm @ 2007-07-05 20:23 UTC (permalink / raw)
  To: mm-commits; +Cc: linuxppc-dev, mathieu.desnoyers, paulus


The patch titled
     powerpc: add missing DATA_DATA
has been added to the -mm tree.  Its filename is
     add-missing-data_data-in-powerpc.patch

*** Remember to use Documentation/SubmitChecklist when testing your code ***

See http://www.zip.com.au/~akpm/linux/patches/stuff/added-to-mm.txt to find
out what to do about this

------------------------------------------------------
Subject: powerpc: add missing DATA_DATA
From: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Cc: <paulus@samba.org>
Cc: <linuxppc-dev@ozlabs.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---

 arch/powerpc/kernel/vmlinux.lds.S |    4 +++-
 1 files changed, 3 insertions(+), 1 deletion(-)

diff -puN arch/powerpc/kernel/vmlinux.lds.S~add-missing-data_data-in-powerpc arch/powerpc/kernel/vmlinux.lds.S
--- a/arch/powerpc/kernel/vmlinux.lds.S~add-missing-data_data-in-powerpc
+++ a/arch/powerpc/kernel/vmlinux.lds.S
@@ -174,7 +174,9 @@ SECTIONS
 	}
 #else
 	.data : {
-		*(.data .data.rel* .toc1)
+		DATA_DATA
+		*(.data.rel*)
+		*(.toc1)
 		*(.branch_lt)
 	}
 
_

Patches currently in -mm which might be from mathieu.desnoyers@polymtl.ca are

powerpc-promc-remove-undef-printk.patch
i386-text-edit-lock.patch
i386-text-edit-lock-alternative-instructions.patch
i386-text-edit-lock-kprobes.patch
immediate-values-global-modules-list-and-module-mutex.patch
immediate-value-architecture-independent-code.patch
immediate-values-non-optimized-architectures.patch
immediate-value-add-kconfig-menus.patch
immediate-values-kprobe-header-fix.patch
immediate-value-i386-optimization.patch
immediate-value-powerpc-optimization.patch
immediate-value-documentation.patch
f00f-bug-fixup-for-i386-use-immediate-values.patch
scheduler-profiling-use-immediate-values.patch
use-data_data-in-cris.patch
add-missing-data_data-in-powerpc.patch
use-data_data-in-xtensa.patch

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox