LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] PCI Error Recovery: e100 network device driver
From: Linas Vepstas @ 2006-04-06 22:24 UTC (permalink / raw)
  To: Jeff Garzik, netdev, linux-pci
  Cc: linuxppc-dev, john.ronciak, linux-kernel, jeffrey.t.kirsher,
	jesse.brandeburg


Please apply and forward upstream.

--linas

[PATCH] PCI Error Recovery: e100 network device driver

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

Signed-off-by: Linas Vepstas <linas@linas.org>
Acked-by: Jesse Brandeburg <jesse.brandeburg@intel.com>

----

 drivers/net/e100.c |   65 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 65 insertions(+)

Index: linux-2.6.17-rc1/drivers/net/e100.c
===================================================================
--- linux-2.6.17-rc1.orig/drivers/net/e100.c	2006-04-05 09:56:06.000000000 -0500
+++ linux-2.6.17-rc1/drivers/net/e100.c	2006-04-06 15:17:29.000000000 -0500
@@ -2781,6 +2781,70 @@ static void e100_shutdown(struct pci_dev
 }
 
 
+/* ------------------ PCI Error Recovery infrastructure  -------------- */
+/** e100_io_error_detected() is called when PCI error is detected */
+static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+
+	/* Same as calling e100_down(netdev_priv(netdev)), but generic */
+	netdev->stop(netdev);
+
+	/* Detach; put netif into state similar to hotplug unplug */
+	netif_poll_enable(netdev);
+	netif_device_detach(netdev);
+
+	/* Request a slot reset. */
+	return PCI_ERS_RESULT_NEED_RESET;
+}
+
+/** e100_io_slot_reset is called after the pci bus has been reset.
+ *  Restart the card from scratch. */
+static pci_ers_result_t e100_io_slot_reset(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct nic *nic = netdev_priv(netdev);
+
+	if(pci_enable_device(pdev)) {
+		printk(KERN_ERR "e100: Cannot re-enable PCI device after reset.\n");
+		return PCI_ERS_RESULT_DISCONNECT;
+	}
+	pci_set_master(pdev);
+
+	/* Only one device per card can do a reset */
+	if (0 != PCI_FUNC (pdev->devfn))
+		return PCI_ERS_RESULT_RECOVERED;
+	e100_hw_reset(nic);
+	e100_phy_init(nic);
+
+	return PCI_ERS_RESULT_RECOVERED;
+}
+
+/** e100_io_resume is called when the error recovery driver
+ *  tells us that its OK to resume normal operation.
+ */
+static void e100_io_resume(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct nic *nic = netdev_priv(netdev);
+
+	/* ack any pending wake events, disable PME */
+	pci_enable_wake(pdev, 0, 0);
+
+	netif_device_attach(netdev);
+	if(netif_running(netdev)) {
+		e100_open (netdev);
+		mod_timer(&nic->watchdog, jiffies);
+	}
+}
+
+static struct pci_error_handlers e100_err_handler = {
+	.error_detected = e100_io_error_detected,
+	.slot_reset = e100_io_slot_reset,
+	.resume = e100_io_resume,
+};
+
+
 static struct pci_driver e100_driver = {
 	.name =         DRV_NAME,
 	.id_table =     e100_id_table,
@@ -2791,6 +2855,7 @@ static struct pci_driver e100_driver = {
 	.resume =       e100_resume,
 #endif
 	.shutdown =     e100_shutdown,
+	.err_handler = &e100_err_handler,
 };
 
 static int __init e100_init_module(void)

^ permalink raw reply

* [PATCH/RFC] powerpc: could not stop CPU(s) even with soft-reset when debugger enabled
From: Haren Myneni @ 2006-04-06 20:47 UTC (permalink / raw)
  To: linuxppc-dev, fastboot; +Cc: michael, David Wilder, paulus, miltonm

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

- During CPU(s) hang scenarios, kdump could not stop these CPUs. However, 
the user could invoke soft-reset to shoot down CPUs reliably. But, when 
the debugger is enabled, these CPUs are returned to hang state after they 
exited from the debugger. This patch fixes this issue by calling 
crash_kexec_secondary() before returns to previous state. 


Signed-off-by: Haren Myneni <haren@us.ibm.com>

--- 2617-rc1/arch/powerpc/kernel/traps.c.orig            2006-04-05 
13:25:22.000000000 -0700
+++ 2617-rc1/arch/powerpc/kernel/traps.c                 2006-04-05 
13:25:33.000000000 -0700
@@ -206,6 +206,16 @@ void system_reset_exception(struct pt_re
 
                 die("System Reset", regs, SIGABRT);
 
+                /*
+                 * Some CPUs which got released from debugger will 
execute this path.
+                 * These CPUs entered debugger first time via soft-reset 
- Means,
+                 * could be possible that these CPUs may not repond to an 
IPI later.
+                 * Therefore, has to call kdump func directly.
+                 * Not a problem if we exited from debugger to recover. 
In this case
+                 * there will not be any primary kexec CPU. Hence, will 
be returned.
+                 */
+                crash_kexec_secondary(regs);
+
                 /* Must die if the interrupt is not recoverable */
                 if (!(regs->msr & MSR_RI))
                                 panic("Unrecoverable System Reset");

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

^ permalink raw reply

* Re: Porting new MPC5200 based Board to linux kernel
From: Wolfgang Denk @ 2006-04-06 22:48 UTC (permalink / raw)
  To: Amir Bukhari; +Cc: Linuxppc-embedded
In-Reply-To: <EE3E34EBE104B24DA5DF5DBC1EA998D528801E@loretta.fzi.de>

In message <EE3E34EBE104B24DA5DF5DBC1EA998D528801E@loretta.fzi.de> you wrote:
> We have a MEN mpc5200 base board and we want to get linux running on it.
> MEN has a bios and can load linux kernel and passing to parameters. I have
> tried to configure kernel manualy but without success. MEN bios load kernel,
> but nothing happend after that, I don't see anything on console.

Is this by any chance a PP01 board? If yes, then see our
linuxppc_2_4_devel kernel tree which supports this board.

Best regards,

Wolfgang Denk

-- 
Software Engineering:  Embedded and Realtime Systems,  Embedded Linux
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
"...and the fully armed nuclear warheads, are, of  course,  merely  a
courtesy detail."

^ permalink raw reply

* Re: [PATCH] PCI Error Recovery: e100 network device driver
From: Greg KH @ 2006-04-06 22:46 UTC (permalink / raw)
  To: Linas Vepstas
  Cc: netdev, linux-kernel, jesse.brandeburg, linuxppc-dev,
	john.ronciak, jeffrey.t.kirsher, linux-pci, Jeff Garzik
In-Reply-To: <20060406222359.GA30037@austin.ibm.com>

On Thu, Apr 06, 2006 at 05:24:00PM -0500, Linas Vepstas wrote:
> +	if(pci_enable_device(pdev)) {

Add a space after "if" and before "(" please.

You do this in a few different places.

thanks,

greg k-h

^ permalink raw reply

* Re: Porting new MPC5200 based Board to linux kernel
From: Wolfgang Denk @ 2006-04-06 22:50 UTC (permalink / raw)
  To: bukhari; +Cc: Linuxppc-embedded
In-Reply-To: <20060406205251.7511E67B16@ozlabs.org>

In message <20060406205251.7511E67B16@ozlabs.org> you wrote:
>  
> Is that config file what I need to get linux running, didn't I need any
> board special code. Like tqm5xxx.c etc. which located on arch\ppc\platforms

What has the TQM code (fot TQ boards) to do with MEN boards? You must
be missing something.

Best regards,

Wolfgang Denk

-- 
Software Engineering:  Embedded and Realtime Systems,  Embedded Linux
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
"Though a program be but three lines long,
someday it will have to be maintained."
- The Tao of Programming

^ permalink raw reply

* Re: [RFC/PATCH] powerpc: Use rtas query-cpu-stopped-state in smp spinup
From: Nathan Lynch @ 2006-04-07  1:10 UTC (permalink / raw)
  To: Michael Ellerman; +Cc: linuxppc-dev, Paul Mackerras, Arnd Bergmann
In-Reply-To: <1144236210.6788.6.camel@localhost.localdomain>

Michael Ellerman wrote:
> On Tue, 2006-04-04 at 12:25 -0500, Nathan Lynch wrote:
> 
> > 2. I've tried it before.  Hope I'm remembering this correctly, but I
> >    think my experience was that query-cpu-stopped-state reported
> >    nonsense for cpus that were started by OF.  This was on Power5,
> >    btw.
> 
> That's not what I see, perhaps I have newer firmware?

I tried your patch (non-kexec boot) on a 1-way SMT power5 with
2.6.17-rc1 and got the badness below, and I think it matches what I
ran into in the past.  Maybe doing query-cpu-stopped-state on a thread
that has yet to be started by RTAS mucks things up?

Memory: 2047640k/2097152k available (5356k kernel code, 49512k
reserved, 1412k data, 900k bss, 240k init)
Calibrating delay loop... 375.80 BogoMIPS (lpj=751616)
Security Framework v1.0.0 initialized
SELinux:  Disabled at boot.
Mount-cache hash table entries: 256
Processor 1 is stuck.               <<<<<<<<
Brought up 1 CPUs
Node 0 CPUs: 0
migration_cost=0

^ permalink raw reply

* Re: [PATCH] powerpc: Fix machine detection in prom_init.c
From: Michael Neuling @ 2006-04-07  3:46 UTC (permalink / raw)
  To: Michael Ellerman; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <20060405161830.CFD28679EB@ozlabs.org>

> In e8222502ee6157e2713da9e0792c21f4ad458d50 the detection of machine
> types in prom_init broke for some machines. We should be checking
> /device_type instead of /model. This should make Power3 and Power4
> boot again. Haven't been able to test this.

We also need to relocate the string before comparing.

Combined patch below.  Tested on POWER3.  

Mikey


From: Michael Ellerman <michael@ellerman.id.au>

In e8222502ee6157e2713da9e0792c21f4ad458d50 the detection of machine types
in prom_init broke for some machines. We should be checking /device_type
instead of /model. This should make Power3 and Power4 boot again. Haven't
been able to test this.  We also need to relocate before comparing. 

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Michael Neuling <mikey@neuling.org>
---

 arch/powerpc/kernel/prom_init.c |    5 ++---
 1 files changed, 2 insertions(+), 3 deletions(-)

Index: linux-2.6-powerpc/arch/powerpc/kernel/prom_init.c
===================================================================
--- linux-2.6-powerpc.orig/arch/powerpc/kernel/prom_init.c
+++ linux-2.6-powerpc/arch/powerpc/kernel/prom_init.c
@@ -1528,12 +1528,11 @@ static int __init prom_find_machine_type
 	 *    non-IBM designs !
 	 *  - it has /rtas
 	 */
-	len = prom_getprop(_prom->root, "model",
+	len = prom_getprop(_prom->root, "device_type",
 			   compat, sizeof(compat)-1);
 	if (len <= 0)
 		return PLATFORM_GENERIC;
-	compat[len] = 0;
-	if (strcmp(compat, "chrp"))
+	if (strcmp(compat, RELOC("chrp")))
 		return PLATFORM_GENERIC;
 
 	/* Default to pSeries. We need to know if we are running LPAR */

^ permalink raw reply

* Re: [PATCH] powerpc: Fix machine detection in prom_init.c
From: Michael Neuling @ 2006-04-07  3:56 UTC (permalink / raw)
  To: Michael Ellerman, Paul Mackerras, linuxppc-dev

From: Michael Ellerman <michael@ellerman.id.au>

In e8222502ee6157e2713da9e0792c21f4ad458d50 the detection of machine types
in prom_init broke for some machines. We should be checking /device_type
instead of /model. This should make Power3 and Power4 boot again. Haven't
been able to test this.  We also need to relocate before comparing. 

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
> > In e8222502ee6157e2713da9e0792c21f4ad458d50 the detection of machine
> > types in prom_init broke for some machines. We should be checking
> > /device_type instead of /model. This should make Power3 and Power4
> > boot again. Haven't been able to test this.
> 
> We also need to relocate the string before comparing.
> 
> Combined patch below.  Tested on POWER3.  

Oops, let's be a little more careful walking off into nowhere.

Again, combined patch below.  Tested on POWER3.  

 arch/powerpc/kernel/prom_init.c |    5 ++---
 1 files changed, 2 insertions(+), 3 deletions(-)

Index: linux-2.6-powerpc/arch/powerpc/kernel/prom_init.c
===================================================================
--- linux-2.6-powerpc.orig/arch/powerpc/kernel/prom_init.c
+++ linux-2.6-powerpc/arch/powerpc/kernel/prom_init.c
@@ -1528,12 +1528,11 @@ static int __init prom_find_machine_type
 	 *    non-IBM designs !
 	 *  - it has /rtas
 	 */
-	len = prom_getprop(_prom->root, "model",
+	len = prom_getprop(_prom->root, "device_type",
 			   compat, sizeof(compat)-1);
 	if (len <= 0)
 		return PLATFORM_GENERIC;
-	compat[len] = 0;
-	if (strcmp(compat, "chrp"))
+	if (strncmp(compat, RELOC("chrp"), 4))
 		return PLATFORM_GENERIC;
 
 	/* Default to pSeries. We need to know if we are running LPAR */

^ permalink raw reply

* [PATCH] powerpc: remove io_page_mask
From: Michael Neuling @ 2006-04-07  5:23 UTC (permalink / raw)
  To: paulus, linuxppc-dev

From: Anton Blanchard <anton@samba.org>

Cleanup patch which removes the io_page_mask.  It fixes the reset on
some e1000 devices which is needed for clean kexec reboots.  The legacy
devices which broke with this patch (parallel port and PC speaker) have
now been fixed in Linus' tree.  

Signed-off-by: Anton Blanchard <anton@samba.org>
Ack-by: Michael Neuling <mikey@neuling.org>

---
 arch/powerpc/kernel/iomap.c           |    2 --
 arch/powerpc/kernel/pci_64.c          |   30 +++---------------------------
 arch/powerpc/platforms/iseries/pci.c  |    3 ---
 arch/powerpc/platforms/maple/pci.c    |    3 ---
 arch/powerpc/platforms/powermac/pci.c |    3 ---
 include/asm-powerpc/eeh.h             |   15 +++------------
 include/asm-powerpc/io.h              |    6 ------
 7 files changed, 6 insertions(+), 56 deletions(-)

Index: linux-2.6-powerpc/arch/powerpc/kernel/iomap.c
===================================================================
--- linux-2.6-powerpc.orig/arch/powerpc/kernel/iomap.c
+++ linux-2.6-powerpc/arch/powerpc/kernel/iomap.c
@@ -106,8 +106,6 @@ EXPORT_SYMBOL(iowrite32_rep);
 
 void __iomem *ioport_map(unsigned long port, unsigned int len)
 {
-	if (!_IO_IS_VALID(port))
-		return NULL;
 	return (void __iomem *) (port+pci_io_base);
 }
 
Index: linux-2.6-powerpc/arch/powerpc/kernel/pci_64.c
===================================================================
--- linux-2.6-powerpc.orig/arch/powerpc/kernel/pci_64.c
+++ linux-2.6-powerpc/arch/powerpc/kernel/pci_64.c
@@ -42,14 +42,6 @@
 unsigned long pci_probe_only = 1;
 int pci_assign_all_buses = 0;
 
-/*
- * legal IO pages under MAX_ISA_PORT.  This is to ensure we don't touch
- * devices we don't have access to.
- */
-unsigned long io_page_mask;
-
-EXPORT_SYMBOL(io_page_mask);
-
 #ifdef CONFIG_PPC_MULTIPLATFORM
 static void fixup_resource(struct resource *res, struct pci_dev *dev);
 static void do_bus_setup(struct pci_bus *bus);
@@ -1104,8 +1096,6 @@ void __init pci_setup_phb_io(struct pci_
 			pci_process_ISA_OF_ranges(isa_dn, hose->io_base_phys,
 						hose->io_base_virt);
 			of_node_put(isa_dn);
-			/* Allow all IO */
-			io_page_mask = -1;
 		}
 	}
 
@@ -1232,27 +1222,13 @@ static void phbs_remap_io(void)
 static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev)
 {
 	struct pci_controller *hose = pci_bus_to_host(dev->bus);
-	unsigned long start, end, mask, offset;
+	unsigned long offset;
 
 	if (res->flags & IORESOURCE_IO) {
 		offset = (unsigned long)hose->io_base_virt - pci_io_base;
 
-		start = res->start += offset;
-		end = res->end += offset;
-
-		/* Need to allow IO access to pages that are in the
-		   ISA range */
-		if (start < MAX_ISA_PORT) {
-			if (end > MAX_ISA_PORT)
-				end = MAX_ISA_PORT;
-
-			start >>= PAGE_SHIFT;
-			end >>= PAGE_SHIFT;
-
-			/* get the range of pages for the map */
-			mask = ((1 << (end+1)) - 1) ^ ((1 << start) - 1);
-			io_page_mask |= mask;
-		}
+		res->start += offset;
+		res->end += offset;
 	} else if (res->flags & IORESOURCE_MEM) {
 		res->start += hose->pci_mem_offset;
 		res->end += hose->pci_mem_offset;
Index: linux-2.6-powerpc/arch/powerpc/platforms/iseries/pci.c
===================================================================
--- linux-2.6-powerpc.orig/arch/powerpc/platforms/iseries/pci.c
+++ linux-2.6-powerpc/arch/powerpc/platforms/iseries/pci.c
@@ -45,8 +45,6 @@
 #include "call_pci.h"
 #include "iommu.h"
 
-extern unsigned long io_page_mask;
-
 /*
  * Forward declares of prototypes.
  */
@@ -277,7 +275,6 @@ void iSeries_pcibios_init(void)
 {
 	iomm_table_initialize();
 	find_and_init_phbs();
-	io_page_mask = -1;
 }
 
 /*
Index: linux-2.6-powerpc/arch/powerpc/platforms/maple/pci.c
===================================================================
--- linux-2.6-powerpc.orig/arch/powerpc/platforms/maple/pci.c
+++ linux-2.6-powerpc/arch/powerpc/platforms/maple/pci.c
@@ -437,9 +437,6 @@ void __init maple_pci_init(void)
 
 	/* Tell pci.c to not change any resource allocations.  */
 	pci_probe_only = 1;
-	
-	/* Allow all IO */
-	io_page_mask = -1;
 }
 
 int maple_pci_get_legacy_ide_irq(struct pci_dev *pdev, int channel)
Index: linux-2.6-powerpc/arch/powerpc/platforms/powermac/pci.c
===================================================================
--- linux-2.6-powerpc.orig/arch/powerpc/platforms/powermac/pci.c
+++ linux-2.6-powerpc/arch/powerpc/platforms/powermac/pci.c
@@ -1068,9 +1068,6 @@ void __init pmac_pci_init(void)
 	/* Tell pci.c to not use the common resource allocation mechanism */
 	pci_probe_only = 1;
 
-	/* Allow all IO */
-	io_page_mask = -1;
-
 #else /* CONFIG_PPC64 */
 	init_p2pbridge();
 	fixup_nec_usb2();
Index: linux-2.6-powerpc/include/asm-powerpc/eeh.h
===================================================================
--- linux-2.6-powerpc.orig/include/asm-powerpc/eeh.h
+++ linux-2.6-powerpc/include/asm-powerpc/eeh.h
@@ -293,8 +293,6 @@ static inline void eeh_memcpy_toio(volat
 static inline u8 eeh_inb(unsigned long port)
 {
 	u8 val;
-	if (!_IO_IS_VALID(port))
-		return ~0;
 	val = in_8((u8 __iomem *)(port+pci_io_base));
 	if (EEH_POSSIBLE_ERROR(val, u8))
 		return eeh_check_failure((void __iomem *)(port), val);
@@ -303,15 +301,12 @@ static inline u8 eeh_inb(unsigned long p
 
 static inline void eeh_outb(u8 val, unsigned long port)
 {
-	if (_IO_IS_VALID(port))
-		out_8((u8 __iomem *)(port+pci_io_base), val);
+	out_8((u8 __iomem *)(port+pci_io_base), val);
 }
 
 static inline u16 eeh_inw(unsigned long port)
 {
 	u16 val;
-	if (!_IO_IS_VALID(port))
-		return ~0;
 	val = in_le16((u16 __iomem *)(port+pci_io_base));
 	if (EEH_POSSIBLE_ERROR(val, u16))
 		return eeh_check_failure((void __iomem *)(port), val);
@@ -320,15 +315,12 @@ static inline u16 eeh_inw(unsigned long 
 
 static inline void eeh_outw(u16 val, unsigned long port)
 {
-	if (_IO_IS_VALID(port))
-		out_le16((u16 __iomem *)(port+pci_io_base), val);
+	out_le16((u16 __iomem *)(port+pci_io_base), val);
 }
 
 static inline u32 eeh_inl(unsigned long port)
 {
 	u32 val;
-	if (!_IO_IS_VALID(port))
-		return ~0;
 	val = in_le32((u32 __iomem *)(port+pci_io_base));
 	if (EEH_POSSIBLE_ERROR(val, u32))
 		return eeh_check_failure((void __iomem *)(port), val);
@@ -337,8 +329,7 @@ static inline u32 eeh_inl(unsigned long 
 
 static inline void eeh_outl(u32 val, unsigned long port)
 {
-	if (_IO_IS_VALID(port))
-		out_le32((u32 __iomem *)(port+pci_io_base), val);
+	out_le32((u32 __iomem *)(port+pci_io_base), val);
 }
 
 /* in-string eeh macros */
Index: linux-2.6-powerpc/include/asm-powerpc/io.h
===================================================================
--- linux-2.6-powerpc.orig/include/asm-powerpc/io.h
+++ linux-2.6-powerpc/include/asm-powerpc/io.h
@@ -37,12 +37,6 @@
 
 extern unsigned long isa_io_base;
 extern unsigned long pci_io_base;
-extern unsigned long io_page_mask;
-
-#define MAX_ISA_PORT 0x10000
-
-#define _IO_IS_VALID(port) ((port) >= MAX_ISA_PORT || (1 << (port>>PAGE_SHIFT)) \
-			    & io_page_mask)
 
 #ifdef CONFIG_PPC_ISERIES
 /* __raw_* accessors aren't supported on iSeries */

This is a 

^ permalink raw reply

* [PATCH 3/4] tickless idle cpus: sysctl support
From: Srivatsa Vaddagiri @ 2006-04-07  6:32 UTC (permalink / raw)
  To: anton, benh, paulus; +Cc: linuxppc-dev, sri_vatsa_v

During initial phase, it is useful to have sysctl control to turn on/off
tickless idle CPU feature at run time. Patch below, against
2.6.17-rc1-mm1, provides that support for all architectures.

Signed-off-by: Srivatsa Vaddagiri <vatsa@in.ibm.com>

---

 linux-2.6.17-rc1-root/kernel/sysctl.c |   20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff -puN kernel/sysctl.c~sysctl kernel/sysctl.c
--- linux-2.6.17-rc1/kernel/sysctl.c~sysctl	2006-04-07 11:29:28.000000000 +0530
+++ linux-2.6.17-rc1-root/kernel/sysctl.c	2006-04-07 11:29:28.000000000 +0530
@@ -554,6 +554,16 @@ static ctl_table kern_table[] = {
 		.extra1		= &minolduid,
 		.extra2		= &maxolduid,
 	},
+#ifdef CONFIG_NO_IDLE_HZ
+	{
+		.ctl_name       = KERN_HZ_TIMER,
+		.procname       = "hz_timer",
+		.data           = &sysctl_hz_timer,
+		.maxlen         = sizeof(int),
+		.mode           = 0644,
+		.proc_handler   = &proc_dointvec,
+	},
+#endif
 #ifdef CONFIG_S390
 #ifdef CONFIG_MATHEMU
 	{
@@ -565,16 +575,6 @@ static ctl_table kern_table[] = {
 		.proc_handler	= &proc_dointvec,
 	},
 #endif
-#ifdef CONFIG_NO_IDLE_HZ
-	{
-		.ctl_name       = KERN_HZ_TIMER,
-		.procname       = "hz_timer",
-		.data           = &sysctl_hz_timer,
-		.maxlen         = sizeof(int),
-		.mode           = 0644,
-		.proc_handler   = &proc_dointvec,
-	},
-#endif
 	{
 		.ctl_name	= KERN_S390_USER_DEBUG_LOGGING,
 		.procname	= "userprocess_debug",

_
-- 
Regards,
vatsa

^ permalink raw reply

* [PATCH 4/4] tickless idle cpus: decrementer statistics - NOT MEANT FOR INCLUSION
From: Srivatsa Vaddagiri @ 2006-04-07  6:32 UTC (permalink / raw)
  To: anton, benh, paulus; +Cc: linuxppc-dev, sri_vatsa_v

This patch (a hack) provides some statistics of decrementer exception on
each CPU. I used this purely to verify that tickless feature is working.

Anton, would this be useful statistics to be exposed (maybe in
/proc/interrupts)? If so, I could work out a more cleaner way of
providing this statistics to user.

Signed-off-by: Srivatsa Vaddagiri <vatsa@in.ibm.com>

---

 linux-2.6.17-rc1-root/arch/powerpc/kernel/time.c |    4 ++++
 linux-2.6.17-rc1-root/fs/proc/proc_misc.c        |   17 +++++++++++++++++
 2 files changed, 21 insertions(+)

diff -puN arch/powerpc/kernel/time.c~stat arch/powerpc/kernel/time.c
--- linux-2.6.17-rc1/arch/powerpc/kernel/time.c~stat	2006-04-07 11:29:20.000000000 +0530
+++ linux-2.6.17-rc1-root/arch/powerpc/kernel/time.c	2006-04-07 11:29:20.000000000 +0530
@@ -757,6 +757,8 @@ void start_hz_timer(struct pt_regs *regs
 static inline int clear_hzless_mask(void) { return 0;}
 #endif
 
+DEFINE_PER_CPU(int, dec_ticks);
+
 /*
  * For iSeries shared processors, we have to let the hypervisor
  * set the hardware decrementer.  We set a virtual decrementer
@@ -780,6 +782,8 @@ void timer_interrupt(struct pt_regs * re
 
 	irq_enter();
 
+	__get_cpu_var(dec_ticks) += 1;
+
 	clear_hzless_mask();
 
 	profile_tick(CPU_PROFILING, regs);
diff -puN fs/proc/proc_misc.c~stat fs/proc/proc_misc.c
--- linux-2.6.17-rc1/fs/proc/proc_misc.c~stat	2006-04-07 11:29:20.000000000 +0530
+++ linux-2.6.17-rc1-root/fs/proc/proc_misc.c	2006-04-07 11:29:20.000000000 +0530
@@ -243,6 +243,22 @@ static int version_read_proc(char *page,
 	return proc_calc_metrics(page, start, off, count, eof, len);
 }
 
+DECLARE_PER_CPU(int, dec_ticks);
+
+static int decrementer_read_proc(char *page, char **start, off_t off,
+				 int count, int *eof, void *data)
+{
+	int len, cpu;
+	char *cp = page;
+
+	for_each_cpu(cpu)
+		cp += sprintf (cp, "%d ", per_cpu(dec_ticks, cpu));
+
+	len = cp - page;
+
+	return proc_calc_metrics(page, start, off, count, eof, len);
+}
+
 extern struct seq_operations cpuinfo_op;
 static int cpuinfo_open(struct inode *inode, struct file *file)
 {
@@ -740,6 +756,7 @@ void __init proc_misc_init(void)
 		{"uptime",	uptime_read_proc},
 		{"meminfo",	meminfo_read_proc},
 		{"version",	version_read_proc},
+		{"decrementer",	decrementer_read_proc},
 #ifdef CONFIG_PROC_HARDWARE
 		{"hardware",	hardware_read_proc},
 #endif

_

-- 
Regards,
vatsa

^ permalink raw reply

* RE: Porting new MPC5200 based Board to linux kernel
From: Amir Bukhari @ 2006-04-07  7:00 UTC (permalink / raw)
  To: wd; +Cc: Linuxppc-embedded
In-Reply-To: <20060406225040.E5E4F352671@atlas.denx.de>

> In message <20060406205251.7511E67B16@ozlabs.org> you wrote:
> >  
> > Is that config file what I need to get linux running, didn't I need 
> > any board special code. Like tqm5xxx.c etc. which located on 
> > arch\ppc\platforms
> 
> What has the TQM code (fot TQ boards) to do with MEN boards? 
> You must be missing something.
> 
I mentioned it as an example, not to use it. I mean the board I use (Em01a)
is not directly supported by the kernel. Someone here (Hans) can give me his

Config file. But I as if I should write a platform code or not?

Sorry if you get confused, I am new to this jungle :-)

-Amir

^ permalink raw reply

* Re: MPC5200 + LocalPlus Bus + memcpy
From: Sascha Hauer @ 2006-04-07  7:37 UTC (permalink / raw)
  To: Andrey Volkov; +Cc: Sylvain Munaut, Paul Mackerras, Linuxppc-embedded
In-Reply-To: <583603349.20060406182144@varma-el.com>

Hello,

On Thu, Apr 06, 2006 at 06:21:44PM +0400, Andrey Volkov wrote:
> Hello, Sascha.
> 
> On Wednesday, April 5, 2006, Sascha Hauer wrote:
> 
> > Hi all,
> 
> > I try to use jffs2 on a flash device connected to the mpc5200
> > LocalPlus Bus. This bus does not allow misaligned accesses.
> > The jffs2 code uses memcpy to copy from a word aligned address to an
> > odd address. The ppc memcpy implementation first copies three bytes to get
> > the target address word aligned, but then the source address is on an
> > odd address. The following word accesses on this unaligned address fail
> > badly.
> Invalid crc on 'name' field ;)?

Yes, exactly ;)

> 
> > I have fixed my problem by modifying the physmap mtd driver, but some
> > day someone wants to connect SRAM to the LocalPlus Bus and I guess he
> > will expect memcpy to work.
> Heh, I'll have same problem. Patch (dirty hack)
> attached (vs head of vanilla 2.6. tree)
> 
> > (BTW the arm implementation of memcpy seems to work around this problem)
> Wrong, memcpy to/from SDRAM _may_ be unaligned, only
> memcpy_fromio/memcpy_toio _must_ be aligned to even addresses.

Hm, then a proper fix would be:
- implement an optimized version of memcpy_fromio/memcpy_toio, this
  could be a version of memcpy which only alignes on the io side
- use memcpy_fromio/memcpy_toio in jffs2 code

Do I see this right?

Is SRAM considered io? I know (Arm-)Boards which do not have SDRAM, they
run completely from SRAM.

> 
> P.S.
> Paul, Sylvain, any suggestions to fix it?
> AFAIK, memcpy_to/from_io must be it string.s, isn't it?
> 
> P.P.S Sacha if you start to write mscan driver, then please wait a
> week, I planned to send my work to can-socket at next Friday.

No I haven't started yet, and I will happily wait another week ;)

Sascha

^ permalink raw reply

* [PATCH 2/4] tickless idle cpu: Skip ticks when CPU is idle
From: Srivatsa Vaddagiri @ 2006-04-07  6:31 UTC (permalink / raw)
  To: anton, benh, paulus; +Cc: linuxppc-dev, sri_vatsa_v

This is the core patch which skips ticks when a CPU is idle.
Should work on pSeries, pmac and maple machines.

The patch is against 2.6.17-rc1-mm1 and has been tested on a 16-way (with SMT) 
Power5 box (p570).

Signed-off-by: Srivatsa Vaddagiri <vatsa@in.ibm.com>

---

 linux-2.6.17-rc1-root/arch/powerpc/Kconfig                   |    6 
 linux-2.6.17-rc1-root/arch/powerpc/kernel/idle_power4.S      |    3 
 linux-2.6.17-rc1-root/arch/powerpc/kernel/irq.c              |    3 
 linux-2.6.17-rc1-root/arch/powerpc/kernel/time.c             |  150 ++++++++---
 linux-2.6.17-rc1-root/arch/powerpc/kernel/traps.c            |    1 
 linux-2.6.17-rc1-root/arch/powerpc/platforms/pseries/setup.c |    6 
 linux-2.6.17-rc1-root/include/asm-powerpc/time.h             |    8 
 7 files changed, 147 insertions(+), 30 deletions(-)

diff -puN arch/powerpc/kernel/time.c~no_idle_hz arch/powerpc/kernel/time.c
--- linux-2.6.17-rc1/arch/powerpc/kernel/time.c~no_idle_hz	2006-04-07 04:14:39.000000000 +0530
+++ linux-2.6.17-rc1-root/arch/powerpc/kernel/time.c	2006-04-07 11:29:13.000000000 +0530
@@ -633,40 +633,12 @@ static void iSeries_tb_recal(void)
 }
 #endif
 
-/*
- * For iSeries shared processors, we have to let the hypervisor
- * set the hardware decrementer.  We set a virtual decrementer
- * in the lppaca and call the hypervisor if the virtual
- * decrementer is less than the current value in the hardware
- * decrementer. (almost always the new decrementer value will
- * be greater than the current hardware decementer so the hypervisor
- * call will not be needed)
- */
-
-/*
- * timer_interrupt - gets called when the decrementer overflows,
- * with interrupts disabled.
- */
-void timer_interrupt(struct pt_regs * regs)
+static void account_ticks(struct pt_regs *regs)
 {
 	int next_dec;
 	int cpu = smp_processor_id();
 	unsigned long ticks;
 
-#ifdef CONFIG_PPC32
-	if (atomic_read(&ppc_n_lost_interrupts) != 0)
-		do_IRQ(regs);
-#endif
-
-	irq_enter();
-
-	profile_tick(CPU_PROFILING, regs);
-	calculate_steal_time();
-
-#ifdef CONFIG_PPC_ISERIES
-	get_lppaca()->int_dword.fields.decr_int = 0;
-#endif
-
 	while ((ticks = tb_ticks_since(per_cpu(last_jiffy, cpu)))
 	       >= tb_ticks_per_jiffy) {
 		/* Update last_jiffy */
@@ -701,6 +673,123 @@ void timer_interrupt(struct pt_regs * re
 	
 	next_dec = tb_ticks_per_jiffy - ticks;
 	set_dec(next_dec);
+}
+
+#ifdef CONFIG_NO_IDLE_HZ
+
+/* Returns 1 if this CPU was set in the mask */
+static inline int clear_hzless_mask(void)
+{
+	unsigned long cpu = smp_processor_id();
+	int rc = 0;
+
+	if (unlikely(cpu_isset(cpu, nohz_cpu_mask))) {
+		cpu_clear(cpu, nohz_cpu_mask);
+		rc = 1;
+	}
+
+	return rc;
+}
+
+#define MAX_DEC_COUNT	UINT_MAX	/* Decrementer is 32-bit */
+static int min_skip = 2;		/* Minimum number of ticks to skip */
+static int max_skip;			/* Maximum number of ticks to skip */
+
+
+int sysctl_hz_timer = 1;
+
+/* Defer timer interrupt for as long as possible. This is accomplished by
+ * programming the decrementer to a suitable value such that it raises the
+ * exception after desired interval. This features allows CPUs to
+ * be used more efficiently in virtualized environments.
+ *
+ * Called with interrupts disabled on an idle CPU. Caller has to ensure that
+ * idle loop is not exited w/o start_hz_timer being called via an interrupt
+ * to restore timer interrupt frequency.
+ */
+
+void stop_hz_timer(void)
+{
+	unsigned long cpu = smp_processor_id(), seq, delta;
+	int next_dec;
+
+	if (sysctl_hz_timer != 0)
+		return;
+
+	cpu_set(cpu, nohz_cpu_mask);
+	mb();
+	if (rcu_pending(cpu) || local_softirq_pending()) {
+		cpu_clear(cpu, nohz_cpu_mask);
+		return;
+	}
+
+	do {
+		seq = read_seqbegin(&xtime_lock);
+
+		delta = next_timer_interrupt() - jiffies;
+
+		if (delta < min_skip) {
+			cpu_clear(cpu, nohz_cpu_mask);
+			return;
+		}
+
+		if (delta > max_skip)
+			delta = max_skip;
+
+		next_dec = tb_last_stamp + delta * tb_ticks_per_jiffy;
+
+	} while (read_seqretry(&xtime_lock, seq));
+
+	next_dec -= get_tb();
+	set_dec(next_dec);
+
+	return;
+}
+
+/* Take into account skipped ticks and restore the HZ timer frequency */
+void start_hz_timer(struct pt_regs *regs)
+{
+	if (clear_hzless_mask())
+		account_ticks(regs);
+}
+
+#else
+static inline int clear_hzless_mask(void) { return 0;}
+#endif
+
+/*
+ * For iSeries shared processors, we have to let the hypervisor
+ * set the hardware decrementer.  We set a virtual decrementer
+ * in the lppaca and call the hypervisor if the virtual
+ * decrementer is less than the current value in the hardware
+ * decrementer. (almost always the new decrementer value will
+ * be greater than the current hardware decementer so the hypervisor
+ * call will not be needed)
+ */
+
+/*
+ * timer_interrupt - gets called when the decrementer overflows,
+ * with interrupts disabled.
+ */
+void timer_interrupt(struct pt_regs * regs)
+{
+#ifdef CONFIG_PPC32
+	if (atomic_read(&ppc_n_lost_interrupts) != 0)
+		do_IRQ(regs);
+#endif
+
+	irq_enter();
+
+	clear_hzless_mask();
+
+	profile_tick(CPU_PROFILING, regs);
+	calculate_steal_time();
+
+#ifdef CONFIG_PPC_ISERIES
+	get_lppaca()->int_dword.fields.decr_int = 0;
+#endif
+
+	account_ticks(regs);
 
 #ifdef CONFIG_PPC_ISERIES
 	if (hvlpevent_is_pending())
@@ -955,6 +1044,9 @@ void __init time_init(void)
 	tb_ticks_per_usec = ppc_tb_freq / 1000000;
 	tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000);
 	calc_cputime_factors();
+#ifdef CONFIG_NO_IDLE_HZ
+	max_skip = __USE_RTC() ? HZ : MAX_DEC_COUNT / tb_ticks_per_jiffy;
+#endif
 
 	/*
 	 * Calculate the length of each tick in ns.  It will not be
diff -puN arch/powerpc/kernel/irq.c~no_idle_hz arch/powerpc/kernel/irq.c
--- linux-2.6.17-rc1/arch/powerpc/kernel/irq.c~no_idle_hz	2006-04-07 04:14:39.000000000 +0530
+++ linux-2.6.17-rc1-root/arch/powerpc/kernel/irq.c	2006-04-07 04:14:57.000000000 +0530
@@ -60,6 +60,7 @@
 #ifdef CONFIG_PPC_ISERIES
 #include <asm/paca.h>
 #endif
+#include <asm/time.h>
 
 int __irq_offset_value;
 #ifdef CONFIG_PPC32
@@ -189,6 +190,8 @@ void do_IRQ(struct pt_regs *regs)
 
         irq_enter();
 
+	start_hz_timer(regs);
+
 #ifdef CONFIG_DEBUG_STACKOVERFLOW
 	/* Debugging check for stack overflow: is there less than 2KB free? */
 	{
diff -puN include/asm-powerpc/time.h~no_idle_hz include/asm-powerpc/time.h
--- linux-2.6.17-rc1/include/asm-powerpc/time.h~no_idle_hz	2006-04-07 04:14:39.000000000 +0530
+++ linux-2.6.17-rc1-root/include/asm-powerpc/time.h	2006-04-07 04:14:58.000000000 +0530
@@ -198,6 +198,14 @@ static inline unsigned long tb_ticks_sin
 	return get_tbl() - tstamp;
 }
 
+#ifdef CONFIG_NO_IDLE_HZ
+extern void stop_hz_timer(void);
+extern void start_hz_timer(struct pt_regs *);
+#else
+static inline void stop_hz_timer(void) { }
+static inline void start_hz_timer(struct pt_regs *regs) { }
+#endif
+
 #define mulhwu(x,y) \
 ({unsigned z; asm ("mulhwu %0,%1,%2" : "=r" (z) : "r" (x), "r" (y)); z;})
 
diff -puN arch/powerpc/Kconfig~no_idle_hz arch/powerpc/Kconfig
--- linux-2.6.17-rc1/arch/powerpc/Kconfig~no_idle_hz	2006-04-07 04:14:39.000000000 +0530
+++ linux-2.6.17-rc1-root/arch/powerpc/Kconfig	2006-04-07 04:14:58.000000000 +0530
@@ -593,6 +593,12 @@ config HOTPLUG_CPU
 
 	  Say N if you are unsure.
 
+config NO_IDLE_HZ
+	depends on EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC || PPC_MAPLE)
+	bool "Switch off timer ticks on idle CPUs"
+	help
+	  Switches the HZ timer interrupts off when a CPU is idle.
+
 config KEXEC
 	bool "kexec system call (EXPERIMENTAL)"
 	depends on PPC_MULTIPLATFORM && EXPERIMENTAL
diff -puN arch/powerpc/kernel/traps.c~no_idle_hz arch/powerpc/kernel/traps.c
--- linux-2.6.17-rc1/arch/powerpc/kernel/traps.c~no_idle_hz	2006-04-07 04:14:39.000000000 +0530
+++ linux-2.6.17-rc1-root/arch/powerpc/kernel/traps.c	2006-04-07 04:14:58.000000000 +0530
@@ -875,6 +875,7 @@ void altivec_unavailable_exception(struc
 
 void performance_monitor_exception(struct pt_regs *regs)
 {
+	start_hz_timer(regs);
 	perf_irq(regs);
 }
 
diff -puN arch/powerpc/platforms/pseries/setup.c~no_idle_hz arch/powerpc/platforms/pseries/setup.c
--- linux-2.6.17-rc1/arch/powerpc/platforms/pseries/setup.c~no_idle_hz	2006-04-07 04:14:39.000000000 +0530
+++ linux-2.6.17-rc1-root/arch/powerpc/platforms/pseries/setup.c	2006-04-07 04:15:50.000000000 +0530
@@ -463,8 +463,10 @@ static void pseries_dedicated_idle_sleep
 	 * very low priority.  The cede enables interrupts, which
 	 * doesn't matter here.
 	 */
-	if (!lppaca[cpu ^ 1].idle || poll_pending() == H_PENDING)
+	if (!lppaca[cpu ^ 1].idle || poll_pending() == H_PENDING) {
+		stop_hz_timer();
 		cede_processor();
+	}
 
 out:
 	HMT_medium();
@@ -479,6 +481,8 @@ static void pseries_shared_idle_sleep(vo
 	 */
 	get_lppaca()->idle = 1;
 
+	stop_hz_timer();
+
 	/*
 	 * Yield the processor to the hypervisor.  We return if
 	 * an external interrupt occurs (which are driven prior
diff -puN arch/powerpc/kernel/idle_power4.S~no_idle_hz arch/powerpc/kernel/idle_power4.S
--- linux-2.6.17-rc1/arch/powerpc/kernel/idle_power4.S~no_idle_hz	2006-04-07 04:14:39.000000000 +0530
+++ linux-2.6.17-rc1-root/arch/powerpc/kernel/idle_power4.S	2006-04-07 04:14:58.000000000 +0530
@@ -30,6 +30,9 @@ END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
 	cmpwi	0,r4,0
 	beqlr
 
+	mflr	r4
+	bl	.stop_hz_timer
+	mtlr	r4
 	/* Go to NAP now */
 BEGIN_FTR_SECTION
 	DSSALL

_


-- 
Regards,
vatsa

^ permalink raw reply

* [RFC][PATCH] first pass at iSeries io rewrite
From: Stephen Rothwell @ 2006-04-07  7:57 UTC (permalink / raw)
  To: paulus; +Cc: ppc-dev

We would like to reduce the special casing of things for legacy iSeries
generally.  This patch starts the work on iSeries i/o.  This changes the
i/o so that iSeries will take a fault if any i/o is attempted and the
appripriate instructions are emulated.  To make this easier, some of the
i/o primitives have been modified to use a simple set of load/store
instructions with the target or source fixed to r0.

This also (strangely) shrinks a normal pSeries built kernel text by about
130 bytes (but adds 256 bytes to its data).

Before this change, typical outw() took about 1650 - 2740 cycles and
afterward about 2190 - 9020 cycles.  The variablilty is interesting and is
probably not only due to these changes.

This does not yet handle memset_io, memcopy_fromio and memcpy_toio.

Some possibilities:
	try to shorten the fault path
	doing a fixup on the fist trap

Suggestions? Comments?

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

---

 arch/powerpc/mm/fault.c                  |    8 ++
 arch/powerpc/platforms/iseries/pci.c     |  139 +++++++++++++++++++-----------
 include/asm-powerpc/io.h                 |   81 +++++------------
 include/asm-powerpc/iseries/iseries_io.h |   19 ----
 include/asm-powerpc/ppc-pci.h            |   11 ++
 5 files changed, 128 insertions(+), 130 deletions(-)

51ff17bea4b0434067e0d3b2fa58493227619baa
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index fdbba42..c0b1986 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -39,6 +39,8 @@
 #include <asm/tlbflush.h>
 #include <asm/kdebug.h>
 #include <asm/siginfo.h>
+#include <asm/firmware.h>
+#include <asm/ppc-pci.h>
 
 /*
  * Check whether the instruction at regs->nip is a store using
@@ -152,8 +154,12 @@ int __kprobes do_page_fault(struct pt_re
 	}
 
 	/* On a kernel SLB miss we can only check for a valid exception entry */
-	if (!user_mode(regs) && (address >= TASK_SIZE))
+	if (!user_mode(regs) && (address >= TASK_SIZE)) {
+		if (firmware_has_feature(FW_FEATURE_ISERIES) &&
+				iseries_handle_io_fault(regs, address))
+			return 0;
 		return SIGSEGV;
+	}
 
 #if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
   	if (error_code & DSISR_DABRMATCH) {
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c
index a19833b..3631995 100644
--- a/arch/powerpc/platforms/iseries/pci.c
+++ b/arch/powerpc/platforms/iseries/pci.c
@@ -26,6 +26,7 @@
 #include <linux/module.h>
 #include <linux/ide.h>
 #include <linux/pci.h>
+#include <linux/ptrace.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -37,6 +38,7 @@
 
 #include <asm/iseries/hv_call_xm.h>
 #include <asm/iseries/mf.h>
+#include <asm/iseries/iseries_io.h>
 
 #include <asm/ppc-pci.h>
 
@@ -465,46 +467,6 @@ static int scan_bridge_slot(HvBusNumber 
 }
 
 /*
- * I/0 Memory copy MUST use mmio commands on iSeries
- * To do; For performance, include the hv call directly
- */
-void iSeries_memset_io(volatile void __iomem *dest, char c, size_t Count)
-{
-	u8 ByteValue = c;
-	long NumberOfBytes = Count;
-
-	while (NumberOfBytes > 0) {
-		iSeries_Write_Byte(ByteValue, dest++);
-		-- NumberOfBytes;
-	}
-}
-EXPORT_SYMBOL(iSeries_memset_io);
-
-void iSeries_memcpy_toio(volatile void __iomem *dest, void *source, size_t count)
-{
-	char *src = source;
-	long NumberOfBytes = count;
-
-	while (NumberOfBytes > 0) {
-		iSeries_Write_Byte(*src++, dest++);
-		-- NumberOfBytes;
-	}
-}
-EXPORT_SYMBOL(iSeries_memcpy_toio);
-
-void iSeries_memcpy_fromio(void *dest, const volatile void __iomem *src, size_t count)
-{
-	char *dst = dest;
-	long NumberOfBytes = count;
-
-	while (NumberOfBytes > 0) {
-		*dst++ = iSeries_Read_Byte(src++);
-		-- NumberOfBytes;
-	}
-}
-EXPORT_SYMBOL(iSeries_memcpy_fromio);
-
-/*
  * Look down the chain to find the matching Device Device
  */
 static struct device_node *find_Device_Node(int bus, int devfn)
@@ -685,7 +647,7 @@ static inline struct device_node *xlate_
  * iSeries_Read_Word = Read Word  (16 bit)
  * iSeries_Read_Long = Read Long  (32 bit)
  */
-u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress)
+static u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress)
 {
 	u64 BarOffset;
 	u64 dsa;
@@ -713,9 +675,8 @@ u8 iSeries_Read_Byte(const volatile void
 
 	return (u8)ret.value;
 }
-EXPORT_SYMBOL(iSeries_Read_Byte);
 
-u16 iSeries_Read_Word(const volatile void __iomem *IoAddress)
+static u16 iSeries_Read_Word(const volatile void __iomem *IoAddress)
 {
 	u64 BarOffset;
 	u64 dsa;
@@ -744,9 +705,8 @@ u16 iSeries_Read_Word(const volatile voi
 
 	return swab16((u16)ret.value);
 }
-EXPORT_SYMBOL(iSeries_Read_Word);
 
-u32 iSeries_Read_Long(const volatile void __iomem *IoAddress)
+static u32 iSeries_Read_Long(const volatile void __iomem *IoAddress)
 {
 	u64 BarOffset;
 	u64 dsa;
@@ -775,7 +735,6 @@ u32 iSeries_Read_Long(const volatile voi
 
 	return swab32((u32)ret.value);
 }
-EXPORT_SYMBOL(iSeries_Read_Long);
 
 /*
  * Write MM I/O Instructions for the iSeries
@@ -784,7 +743,7 @@ EXPORT_SYMBOL(iSeries_Read_Long);
  * iSeries_Write_Word = Write Word(16 bit)
  * iSeries_Write_Long = Write Long(32 bit)
  */
-void iSeries_Write_Byte(u8 data, volatile void __iomem *IoAddress)
+static void iSeries_Write_Byte(u8 data, volatile void __iomem *IoAddress)
 {
 	u64 BarOffset;
 	u64 dsa;
@@ -810,9 +769,8 @@ void iSeries_Write_Byte(u8 data, volatil
 		rc = HvCall4(HvCallPciBarStore8, dsa, BarOffset, data, 0);
 	} while (CheckReturnCode("WWB", DevNode, &retry, rc) != 0);
 }
-EXPORT_SYMBOL(iSeries_Write_Byte);
 
-void iSeries_Write_Word(u16 data, volatile void __iomem *IoAddress)
+static void iSeries_Write_Word(u16 data, volatile void __iomem *IoAddress)
 {
 	u64 BarOffset;
 	u64 dsa;
@@ -838,9 +796,8 @@ void iSeries_Write_Word(u16 data, volati
 		rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, swab16(data), 0);
 	} while (CheckReturnCode("WWW", DevNode, &retry, rc) != 0);
 }
-EXPORT_SYMBOL(iSeries_Write_Word);
 
-void iSeries_Write_Long(u32 data, volatile void __iomem *IoAddress)
+static void iSeries_Write_Long(u32 data, volatile void __iomem *IoAddress)
 {
 	u64 BarOffset;
 	u64 dsa;
@@ -866,4 +823,82 @@ void iSeries_Write_Long(u32 data, volati
 		rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, swab32(data), 0);
 	} while (CheckReturnCode("WWL", DevNode, &retry, rc) != 0);
 }
-EXPORT_SYMBOL(iSeries_Write_Long);
+
+/*
+ * I/0 Memory copy MUST use mmio commands on iSeries
+ * To do; For performance, include the hv call directly
+ */
+void iSeries_memset_io(volatile void __iomem *dest, char c, size_t Count)
+{
+	u8 ByteValue = c;
+	long NumberOfBytes = Count;
+
+	while (NumberOfBytes > 0) {
+		iSeries_Write_Byte(ByteValue, dest++);
+		-- NumberOfBytes;
+	}
+}
+EXPORT_SYMBOL(iSeries_memset_io);
+
+void iSeries_memcpy_toio(volatile void __iomem *dest, void *source, size_t count)
+{
+	char *src = source;
+	long NumberOfBytes = count;
+
+	while (NumberOfBytes > 0) {
+		iSeries_Write_Byte(*src++, dest++);
+		-- NumberOfBytes;
+	}
+}
+EXPORT_SYMBOL(iSeries_memcpy_toio);
+
+void iSeries_memcpy_fromio(void *dest, const volatile void __iomem *src, size_t count)
+{
+	char *dst = dest;
+	long NumberOfBytes = count;
+
+	while (NumberOfBytes > 0) {
+		*dst++ = iSeries_Read_Byte(src++);
+		-- NumberOfBytes;
+	}
+}
+EXPORT_SYMBOL(iSeries_memcpy_fromio);
+
+int iseries_handle_io_fault(struct pt_regs *regs, unsigned long address)
+{
+	u32 instr;
+
+	/* is the address in out i/o range? */
+	if ((address < BASE_IO_MEMORY) || (address >= max_io_memory))
+		return 0;
+	/* we are only called for kernel mode faults */
+	instr = *(u32 *)regs->nip;
+	/* Is the major opcode 31 and target/source r0? */
+	if ((instr & 0xffe00000) != 0x7C000000)
+		return 0;
+
+	switch ((instr >> 1) & 0x3ff) {
+	case 87:
+		regs->gpr[0] = iSeries_Read_Byte((void __iomem *)address);
+		break;
+	case 215:
+		iSeries_Write_Byte(regs->gpr[0], (void __iomem *)address);
+		break;
+	case 790:
+		regs->gpr[0] = iSeries_Read_Word((void __iomem *)address);
+		break;
+	case 918:
+		iSeries_Write_Word(regs->gpr[0], (void __iomem *)address);
+		break;
+	case 534:
+		regs->gpr[0] = iSeries_Read_Long((void __iomem *)address);
+		break;
+	case 662:
+		iSeries_Write_Long(regs->gpr[0], (void __iomem *)address);
+		break;
+	default:
+		return 0;
+	}
+	regs->nip += 4;
+	return 1;
+}
diff --git a/include/asm-powerpc/io.h b/include/asm-powerpc/io.h
index 68efbea..0725c11 100644
--- a/include/asm-powerpc/io.h
+++ b/include/asm-powerpc/io.h
@@ -16,9 +16,6 @@
 #include <linux/compiler.h>
 #include <asm/page.h>
 #include <asm/byteorder.h>
-#ifdef CONFIG_PPC_ISERIES 
-#include <asm/iseries/iseries_io.h>
-#endif  
 #include <asm/synch.h>
 #include <asm/delay.h>
 
@@ -44,41 +41,6 @@ extern unsigned long io_page_mask;
 #define _IO_IS_VALID(port) ((port) >= MAX_ISA_PORT || (1 << (port>>PAGE_SHIFT)) \
 			    & io_page_mask)
 
-#ifdef CONFIG_PPC_ISERIES
-/* __raw_* accessors aren't supported on iSeries */
-#define __raw_readb(addr)	{ BUG(); 0; }
-#define __raw_readw(addr)       { BUG(); 0; }
-#define __raw_readl(addr)       { BUG(); 0; }
-#define __raw_readq(addr)       { BUG(); 0; }
-#define __raw_writeb(v, addr)   { BUG(); 0; }
-#define __raw_writew(v, addr)   { BUG(); 0; }
-#define __raw_writel(v, addr)   { BUG(); 0; }
-#define __raw_writeq(v, addr)   { BUG(); 0; }
-#define readb(addr)		iSeries_Read_Byte(addr)
-#define readw(addr)		iSeries_Read_Word(addr)
-#define readl(addr)		iSeries_Read_Long(addr)
-#define writeb(data, addr)	iSeries_Write_Byte((data),(addr))
-#define writew(data, addr)	iSeries_Write_Word((data),(addr))
-#define writel(data, addr)	iSeries_Write_Long((data),(addr))
-#define memset_io(a,b,c)	iSeries_memset_io((a),(b),(c))
-#define memcpy_fromio(a,b,c)	iSeries_memcpy_fromio((a), (b), (c))
-#define memcpy_toio(a,b,c)	iSeries_memcpy_toio((a), (b), (c))
-
-#define inb(addr)		readb(((void __iomem *)(long)(addr)))
-#define inw(addr)		readw(((void __iomem *)(long)(addr)))
-#define inl(addr)		readl(((void __iomem *)(long)(addr)))
-#define outb(data,addr)		writeb(data,((void __iomem *)(long)(addr)))
-#define outw(data,addr)		writew(data,((void __iomem *)(long)(addr)))
-#define outl(data,addr)		writel(data,((void __iomem *)(long)(addr)))
-/*
- * The *_ns versions below don't do byte-swapping.
- * Neither do the standard versions now, these are just here
- * for older code.
- */
-#define insw_ns(port, buf, ns)	_insw_ns((u16 __iomem *)((port)+pci_io_base), (buf), (ns))
-#define insl_ns(port, buf, nl)	_insl_ns((u32 __iomem *)((port)+pci_io_base), (buf), (nl))
-#else
-
 static inline unsigned char __raw_readb(const volatile void __iomem *addr)
 {
 	return *(volatile unsigned char __force *)addr;
@@ -144,8 +106,6 @@ static inline void __raw_writeq(unsigned
 #define outsw(port, buf, ns)  _outsw_ns((u16 __iomem *)((port)+pci_io_base), (buf), (ns))
 #define outsl(port, buf, nl)  _outsl_ns((u32 __iomem *)((port)+pci_io_base), (buf), (nl))
 
-#endif
-
 #define readb_relaxed(addr) readb(addr)
 #define readw_relaxed(addr) readw(addr)
 #define readl_relaxed(addr) readl(addr)
@@ -273,25 +233,30 @@ static inline void iosync(void)
  * These routines do not perform EEH-related I/O address translation,
  * and should not be used directly by device drivers.  Use inb/readb
  * instead.
+ *
+ * For some of these, we force the target/source register to be
+ * r0 to ease decoding on iSeries.
  */
 static inline int in_8(const volatile unsigned char __iomem *addr)
 {
-	int ret;
+	register unsigned int ret __asm__("r0");
 
-	__asm__ __volatile__("lbz%U1%X1 %0,%1; twi 0,%0,0; isync"
-			     : "=r" (ret) : "m" (*addr));
+	__asm__ __volatile__("lbzx %0,0,%1; twi 0,%0,0; isync"
+			     : "=r" (ret) : "r" (addr));
 	return ret;
 }
 
-static inline void out_8(volatile unsigned char __iomem *addr, int val)
+static inline void out_8(volatile unsigned char __iomem *addr, int ival)
 {
-	__asm__ __volatile__("stb%U0%X0 %1,%0; sync"
-			     : "=m" (*addr) : "r" (val));
+	register unsigned int val __asm__("r0") = ival;
+
+	__asm__ __volatile__("stbx %0,0,%1; sync"
+			     : : "r" (val), "r" (addr));
 }
 
 static inline int in_le16(const volatile unsigned short __iomem *addr)
 {
-	int ret;
+	register unsigned int ret __asm__("r0");
 
 	__asm__ __volatile__("lhbrx %0,0,%1; twi 0,%0,0; isync"
 			     : "=r" (ret) : "r" (addr), "m" (*addr));
@@ -307,10 +272,12 @@ static inline int in_be16(const volatile
 	return ret;
 }
 
-static inline void out_le16(volatile unsigned short __iomem *addr, int val)
+static inline void out_le16(volatile unsigned short __iomem *addr, int ival)
 {
-	__asm__ __volatile__("sthbrx %1,0,%2; sync"
-			     : "=m" (*addr) : "r" (val), "r" (addr));
+	register unsigned int val __asm__("r0") = ival;
+
+	__asm__ __volatile__("sthbrx %0,0,%1; sync"
+			     : : "r" (val), "r" (addr));
 }
 
 static inline void out_be16(volatile unsigned short __iomem *addr, int val)
@@ -321,7 +288,7 @@ static inline void out_be16(volatile uns
 
 static inline unsigned in_le32(const volatile unsigned __iomem *addr)
 {
-	unsigned ret;
+	register unsigned int ret __asm__("r0");
 
 	__asm__ __volatile__("lwbrx %0,0,%1; twi 0,%0,0; isync"
 			     : "=r" (ret) : "r" (addr), "m" (*addr));
@@ -337,10 +304,12 @@ static inline unsigned in_be32(const vol
 	return ret;
 }
 
-static inline void out_le32(volatile unsigned __iomem *addr, int val)
+static inline void out_le32(volatile unsigned __iomem *addr, int ival)
 {
-	__asm__ __volatile__("stwbrx %1,0,%2; sync" : "=m" (*addr)
-			     : "r" (val), "r" (addr));
+	register unsigned int val __asm__("r0") = ival;
+
+	__asm__ __volatile__("stwbrx %1,0,%2; sync"
+			     : "=m" (*addr) : "r" (val), "r" (addr));
 }
 
 static inline void out_be32(volatile unsigned __iomem *addr, int val)
@@ -399,9 +368,7 @@ static inline void out_be64(volatile uns
 	__asm__ __volatile__("std%U0%X0 %1,%0; sync" : "=m" (*addr) : "r" (val));
 }
 
-#ifndef CONFIG_PPC_ISERIES 
 #include <asm/eeh.h>
-#endif
 
 /**
  *	check_signature		-	find BIOS signatures
@@ -417,7 +384,6 @@ static inline int check_signature(const 
 	const unsigned char *signature, int length)
 {
 	int retval = 0;
-#ifndef CONFIG_PPC_ISERIES 
 	do {
 		if (readb(io_addr) != *signature)
 			goto out;
@@ -427,7 +393,6 @@ static inline int check_signature(const 
 	} while (length);
 	retval = 1;
 out:
-#endif
 	return retval;
 }
 
diff --git a/include/asm-powerpc/iseries/iseries_io.h b/include/asm-powerpc/iseries/iseries_io.h
index 496aa85..5be0a73 100644
--- a/include/asm-powerpc/iseries/iseries_io.h
+++ b/include/asm-powerpc/iseries/iseries_io.h
@@ -1,8 +1,6 @@
 #ifndef _ASM_POWERPC_ISERIES_ISERIES_IO_H
 #define _ASM_POWERPC_ISERIES_ISERIES_IO_H
 
-#include <linux/config.h>
-
 #ifdef CONFIG_PPC_ISERIES
 #include <linux/types.h>
 /*
@@ -33,28 +31,11 @@
  */
 
 #ifdef CONFIG_PCI
-extern u8   iSeries_Read_Byte(const volatile void __iomem * IoAddress);
-extern u16  iSeries_Read_Word(const volatile void __iomem * IoAddress);
-extern u32  iSeries_Read_Long(const volatile void __iomem * IoAddress);
-extern void iSeries_Write_Byte(u8  IoData, volatile void __iomem * IoAddress);
-extern void iSeries_Write_Word(u16 IoData, volatile void __iomem * IoAddress);
-extern void iSeries_Write_Long(u32 IoData, volatile void __iomem * IoAddress);
-
 extern void iSeries_memset_io(volatile void __iomem *dest, char x, size_t n);
 extern void iSeries_memcpy_toio(volatile void __iomem *dest, void *source,
 		size_t n);
 extern void iSeries_memcpy_fromio(void *dest,
 		const volatile void __iomem *source, size_t n);
-#else
-static inline u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress)
-{
-	return 0xff;
-}
-
-static inline void iSeries_Write_Byte(u8 IoData,
-		volatile void __iomem *IoAddress)
-{
-}
 #endif	/* CONFIG_PCI */
 
 #endif /* CONFIG_PPC_ISERIES */
diff --git a/include/asm-powerpc/ppc-pci.h b/include/asm-powerpc/ppc-pci.h
index cf79bc7..db153ab 100644
--- a/include/asm-powerpc/ppc-pci.h
+++ b/include/asm-powerpc/ppc-pci.h
@@ -51,6 +51,17 @@ extern void pSeries_irq_bus_setup(struct
 
 extern unsigned long pci_probe_only;
 
+/* From platforms/iseries/pci.c */
+#if defined(CONFIG_PPC_ISERIES) && defined(CONFIG_PCI)
+extern int iseries_handle_io_fault(struct pt_regs *regs, unsigned long address);
+#else
+static inline int iseries_handle_io_fault(struct pt_regs *regs,
+		unsigned long address)
+{
+	return 0;
+}
+#endif
+
 /* ---- EEH internal-use-only related routines ---- */
 #ifdef CONFIG_EEH
 
-- 
1.2.4

^ permalink raw reply related

* RTC/I2C on 82xx with Linux 2.6.x
From: Laurent Lagrange @ 2006-04-07  8:16 UTC (permalink / raw)
  To: linuxppc-embedded
In-Reply-To: <000001c642bd$1dc28fa0$5201a8c0@GEG2400>

Hello,

I use a Linux 2.6.x on a custom 8270 board with a RTC on the I2C bus
(rtc8564).
I want to use it as the system date :
	- Is it possible ?
	- Do I need to initialize the "ppc_md" structure in the "platform_init"
function with my own RTC functions ?
	- In that case, can I use the kernel I2C layer ?

Thanks all
Laurent

^ permalink raw reply

* [PATCH 1/4] tickless idle cpu - Allow any CPU to update jiffies
From: Srivatsa Vaddagiri @ 2006-04-07  6:30 UTC (permalink / raw)
  To: anton, benh, paulus; +Cc: linuxppc-dev, sri_vatsa_v

Currently, only boot CPU calls do_timer to update jiffies. This prevents
idle boot CPU from skipping ticks. Patch below, against 2.6.17-rc1-mm1,
allows jiffies to be updated from any CPU.

Signed-off-by: Srivatsa Vaddagiri <vatsa@in.ibm.com>

---

 linux-2.6.17-rc1-root/arch/powerpc/kernel/time.c |   22 ++++++++++------------
 1 file changed, 10 insertions(+), 12 deletions(-)

diff -puN arch/powerpc/kernel/time.c~boot_cpu_fix arch/powerpc/kernel/time.c
--- linux-2.6.17-rc1/arch/powerpc/kernel/time.c~boot_cpu_fix	2006-04-07 04:13:53.000000000 +0530
+++ linux-2.6.17-rc1-root/arch/powerpc/kernel/time.c	2006-04-07 04:14:03.000000000 +0530
@@ -685,19 +685,17 @@ void timer_interrupt(struct pt_regs * re
 		if (!cpu_is_offline(cpu))
 			account_process_time(regs);
 
-		/*
-		 * No need to check whether cpu is offline here; boot_cpuid
-		 * should have been fixed up by now.
-		 */
-		if (cpu != boot_cpuid)
-			continue;
-
 		write_seqlock(&xtime_lock);
-		tb_last_jiffy += tb_ticks_per_jiffy;
-		tb_last_stamp = per_cpu(last_jiffy, cpu);
-		do_timer(regs);
-		timer_recalc_offset(tb_last_jiffy);
-		timer_check_rtc();
+		if (tb_ticks_since(tb_last_stamp) >= tb_ticks_per_jiffy) {
+			tb_last_jiffy += tb_ticks_per_jiffy;
+			tb_last_stamp += tb_ticks_per_jiffy;
+			/* Handle RTCL overflow on 601 */
+			if (__USE_RTC() && tb_last_stamp >= 1000000000)
+				tb_last_stamp -= 1000000000;
+			do_timer(regs);
+			timer_recalc_offset(tb_last_jiffy);
+			timer_check_rtc();
+		}
 		write_sequnlock(&xtime_lock);
 	}
 	

_
-- 
Regards,
vatsa

^ permalink raw reply

* Re[2]: MPC5200 + LocalPlus Bus + memcpy
From: Andrey Volkov @ 2006-04-07  8:57 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: Sylvain Munaut, Paul Mackerras, Linuxppc-embedded
In-Reply-To: <20060407073701.GC10831@localhost.localdomain>

Hello, Sascha.

On Friday, April 7, 2006, Sascha Hauer wrote:

> Hello,

> On Thu, Apr 06, 2006 at 06:21:44PM +0400, Andrey Volkov wrote:
>> Hello, Sascha.
>> 
>> On Wednesday, April 5, 2006, Sascha Hauer wrote:
>> 
>> > Hi all,
>> 
>> > I try to use jffs2 on a flash device connected to the mpc5200
>> > LocalPlus Bus. This bus does not allow misaligned accesses.
>> > The jffs2 code uses memcpy to copy from a word aligned address to an
>> > odd address. The ppc memcpy implementation first copies three bytes to get
>> > the target address word aligned, but then the source address is on an
>> > odd address. The following word accesses on this unaligned address fail
>> > badly.
>> Invalid crc on 'name' field ;)?

> Yes, exactly ;)
:)
>> 
>> > I have fixed my problem by modifying the physmap mtd driver, but some
>> > day someone wants to connect SRAM to the LocalPlus Bus and I guess he
>> > will expect memcpy to work.
>> Heh, I'll have same problem. Patch (dirty hack)
>> attached (vs head of vanilla 2.6. tree)
>> 
>> > (BTW the arm implementation of memcpy seems to work around this problem)
>> Wrong, memcpy to/from SDRAM _may_ be unaligned, only
>> memcpy_fromio/memcpy_toio _must_ be aligned to even addresses.

> Hm, then a proper fix would be:
> - implement an optimized version of memcpy_fromio/memcpy_toio, this
>   could be a version of memcpy which only alignes on the io side
Yes.

> - use memcpy_fromio/memcpy_toio in jffs2 code
They already use it (from jffs2_read/write), only scan.c doesn't
calling this fns.

> Do I see this right?
Yes.

> Is SRAM considered io? I know (Arm-)Boards which do not have SDRAM, they
> run completely from SRAM.
Only LBP demand alignment, SDRAM/DDR and internal SRAM didn't.



-- 
Regards,
Andrey Volkov

^ permalink raw reply

* Re: RTC/I2C on 82xx with Linux 2.6.x
From: Claus Gindhart @ 2006-04-07  8:57 UTC (permalink / raw)
  To: linuxppc-embedded
In-Reply-To: <003401c65a1b$915dac90$5201a8c0@GEG2400>

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

Laurent,

attached you find a rtc-driver for 2.6.13.
I ported it from 2.4 myself, because i didnt find any 2.6-port out in the 
world.
the ppc_md-structure entries are initialized within the driver itself. This is 
propably not 100% consistent with the coding conventions, but it works fro 
me.
This i2c-layer can still be used with this driver; i have a LM75 and an EEPROM 
on the same bus, which i operate via LM-Sensors and the i2c-dev driver.

-- 
Mit freundlichen Gruessen / Best regards

Claus Gindhart
SW R&D 
Kontron Modular Computers
phone :++49 (0)8341-803-374
mailto:claus.gindhart@kontron-modular.com 
http://www.kontron.com

-----BEGIN GEEK CODE BLOCK-----
  Version: 3.1
  GU d- s++:>++:+ a+ C++$ !U !P L++>$ E-- W+(-) N- o? 
  K? w !O !M V !PS PE- Y+ PGP+ t 5? X R* tv- b+ DI+++ 
  D-- G e++> h--- !r x+++
------END GEEK CODE BLOCK------



Am Friday 07 April 2006 10:16 schrieb Laurent Lagrange:
Hello,

I use a Linux 2.6.x on a custom 8270 board with a RTC on the I2C bus
(rtc8564).
I want to use it as the system date :
	- Is it possible ?
	- Do I need to initialize the "ppc_md" structure in the "platform_init"
function with my own RTC functions ?
	- In that case, can I use the kernel I2C layer ?

Thanks all
Laurent


_______________________________________________
Linuxppc-embedded mailing list
Linuxppc-embedded@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-embedded


[-- Attachment #2: rtc8564.c --]
[-- Type: text/x-csrc, Size: 11730 bytes --]

/*
 *  linux/drivers/i2c/chips/rtc8564.c
 *
 *  Copyright (C) 2002-2004 Stefan Eletzhofer
 *
 *	based on linux/drivers/acron/char/pcf8583.c
 *  Copyright (C) 2000 Russell King
 *
 * 2006.03.14 Claus Gindhart <claus.gindhart@kontron-modular.com>
 * Added missing support for PowerPC and fix up for RTC update 
 * in interrupt mode (11 minute mode support)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 asr
 * published by the Free Software Foundation.
 *
 * Driver for system3's EPSON RTC 8564 chip
 */
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/rtc.h>		/* get the user-level API */
#include <linux/init.h>
#ifdef CONFIG_PPC
	#include <asm/machdep.h>
#endif

#include "rtc8564.h"

/* prints out the time to be set, if activated */
#undef EXT_DEBUG


#ifdef DEBUG
# define _DBG(x, fmt, args...) do{ if (debug>=x) printk("%s: " fmt "\n", __FUNCTION__, ##args); } while(0);
#else
# define _DBG(x, fmt, args...) do { } while(0);
#endif

#define _DBGRTCTM(x, rtctm) if (debug>=x) printk(KERN_DEBUG"%s: secs=%d, mins=%d, hours=%d, mday=%d, " \
			"mon=%d, year=%d, wday=%d VL=%d\n", __FUNCTION__, \
			(rtctm).secs, (rtctm).mins, (rtctm).hours, (rtctm).mday, \
			(rtctm).mon, (rtctm).year, (rtctm).wday, (rtctm).vl);

struct rtc8564_data {
	struct i2c_client client;
	u16 ctrl;
};

static inline u8 _rtc8564_ctrl1(struct i2c_client *client)
{
	struct rtc8564_data *data = i2c_get_clientdata(client);
	return data->ctrl & 0xff;
}
static inline u8 _rtc8564_ctrl2(struct i2c_client *client)
{
	struct rtc8564_data *data = i2c_get_clientdata(client);
	return (data->ctrl & 0xff00) >> 8;
}

#define CTRL1(c) _rtc8564_ctrl1(c)
#define CTRL2(c) _rtc8564_ctrl2(c)

#define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)
#define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10)

static int debug;
module_param(debug, int, S_IRUGO | S_IWUSR);

DECLARE_MUTEX(rtc8564_sem);

static struct i2c_driver rtc8564_driver;
struct i2c_client *this_client;

static unsigned short ignore[] = { I2C_CLIENT_END };
static unsigned short normal_addr[] = { 0x51, I2C_CLIENT_END };

static struct i2c_client_address_data addr_data = {
	.normal_i2c		= normal_addr,
	.probe			= ignore,
	.ignore			= ignore,
	.force			= ignore,
};

static int rtc8564_read_mem(struct i2c_client *client, struct mem *mem);
static int rtc8564_write_mem(struct i2c_client *client, struct mem *mem);

static int rtc8564_recv(struct i2c_client *client, 
			unsigned char *buf, unsigned char addrs, unsigned char count)
{
	int ret = -EIO;

	unsigned char addr[1] = { addrs };
	struct i2c_msg msgs[2] = {
		{client->addr, 0, 1, addr},
		{client->addr, I2C_M_RD, count, buf}
	};

	_DBG(1, "client=%p, addrs=%d, buf=%p, count=%d", client, addrs, buf, count);

	if (!buf) {
		ret = -EINVAL;
		goto done;
	}

	ret = i2c_transfer(client->adapter, msgs, 2);
	if (ret == 2) {
		ret = 0;
	}

done:
	return ret;
}

static int rtc8564_write(struct i2c_client *client, unsigned char adr,
			 unsigned char *data, unsigned char len)
{
	int ret = 0;
	unsigned char _data[16];
	struct i2c_msg wr;
	int i;

	if (!data || len > 15) {
		ret = -EINVAL;
		goto done;
	}

	_DBG(1, "client=%p, adr=%d, buf=%p, len=%d", client, adr, data, len);

	_data[0] = adr;
	for (i = 0; i < len; i++) {
		_data[i + 1] = data[i];
		_DBG(5, "data[%d] = 0x%02x (%d)", i, data[i], data[i]);
	}

	wr.addr = client->addr;
	wr.flags = 0;
	wr.len = len + 1;
	wr.buf = _data;

	ret = i2c_transfer(client->adapter, &wr, 1);
	if (ret == 1) {
		ret = 0;
	}

done:
	return ret;
}


static int rtc8564_get_datetime(struct i2c_client *client, struct rtc_tm *dt)
{
	int ret = -EIO;
	unsigned char buf[15];

	_DBG(1, "client=%p, dt=%p", client, dt);

	if (!dt)
		return -EINVAL;

	memset(buf, 0, sizeof(buf));

	ret = rtc8564_recv(client, buf, 0, 15);
	if (ret)
		return ret;

	/* century stored in minute alarm reg */
	dt->year = BCD_TO_BIN(buf[RTC8564_REG_YEAR]);
	dt->year += 100 * BCD_TO_BIN(buf[RTC8564_REG_AL_MIN] & 0x3f);
	dt->mday = BCD_TO_BIN(buf[RTC8564_REG_DAY] & 0x3f);
	dt->wday = BCD_TO_BIN(buf[RTC8564_REG_WDAY] & 7);
	dt->mon = BCD_TO_BIN(buf[RTC8564_REG_MON_CENT] & 0x1f);

	dt->secs = BCD_TO_BIN(buf[RTC8564_REG_SEC] & 0x7f);
	dt->vl = (buf[RTC8564_REG_SEC] & 0x80) == 0x80;
	dt->mins = BCD_TO_BIN(buf[RTC8564_REG_MIN] & 0x7f);
	dt->hours = BCD_TO_BIN(buf[RTC8564_REG_HR] & 0x3f);

	_DBGRTCTM(2, *dt);

	return 0;
}

unsigned long ppc_rtc8564_get_time( void )
{
	struct rtc_tm time;
	int rc;

	/* The only way to tell the user that rtc time is not reliable (?) */
	if(!this_client)
		return -1 /*RTC_24H | RTC_BATT_BAD */;


	down(&rtc8564_sem);
	rc = rtc8564_get_datetime(this_client,&time);
	up(&rtc8564_sem);
	if (rc)
	{
		return -1 /* RTC_24H | RTC_BATT_BAD */;
	}

	return mktime(time.year, time.mon, time.mday, 
				time.hours, time.mins, time.secs);
}



static int
rtc8564_set_datetime(struct i2c_client *client, struct rtc_tm *dt, int datetoo)
{
	int ret, len = 5;
	unsigned char buf[15];

	_DBG(1, "client=%p, dt=%p", client, dt);
#ifdef EXT_DEBUG
	printk("rtc8564_set_datetime %d\\%d\\%d %d:%d:%d, wday=%d\n",
		dt->year,dt->mon,dt->mday,
		dt->hours,dt->mins,dt->secs,dt->wday);
#endif

	if (!dt)
		return -EINVAL;

	_DBGRTCTM(2, *dt);

	buf[RTC8564_REG_CTRL1] = CTRL1(client) | RTC8564_CTRL1_STOP;
	buf[RTC8564_REG_CTRL2] = CTRL2(client);
	buf[RTC8564_REG_SEC] = BIN_TO_BCD(dt->secs);
	buf[RTC8564_REG_MIN] = BIN_TO_BCD(dt->mins);
	buf[RTC8564_REG_HR] = BIN_TO_BCD(dt->hours);

	if (datetoo) {
		len += 5;
		buf[RTC8564_REG_DAY] = BIN_TO_BCD(dt->mday);
		buf[RTC8564_REG_WDAY] = BIN_TO_BCD(dt->wday);
		buf[RTC8564_REG_MON_CENT] = BIN_TO_BCD(dt->mon) & 0x1f;
		/* century stored in minute alarm reg */
		buf[RTC8564_REG_YEAR] = BIN_TO_BCD(dt->year % 100);
		buf[RTC8564_REG_AL_MIN] = BIN_TO_BCD(dt->year / 100);
	}

	ret = rtc8564_write(client, 0, buf, len);
	if (ret) {
		_DBG(1, "error writing data! %d", ret);
	}

	buf[RTC8564_REG_CTRL1] = CTRL1(client);
	ret = rtc8564_write(client, 0, buf, 1);
	if (ret) {
		_DBG(1, "error writing data! %d", ret);
	}

	return ret;
}


int rtc8564_set_time(struct rtc_time *time)
{
	int rc;
	struct rtc_tm dt;

#ifdef EXT_DEBUG
	printk("rtc8564_set_time to %d\\%d\\%d %d:%d:%d\n",
		time->tm_year,time->tm_mon,time->tm_mday,
		time->tm_hour,time->tm_min,time->tm_sec);
#endif

	down(&rtc8564_sem);

	dt.secs = time->tm_sec;
	dt.mins = time->tm_min;
	dt.hours = time->tm_hour;
	dt.wday = time->tm_wday;
	dt.mday = time->tm_mday;
	dt.mon = time->tm_mon;
	dt.year = time->tm_year;

	rc = rtc8564_set_datetime(this_client,&dt,1);

	up(&rtc8564_sem);

	return rc;
}

static void deferred_set_rtc(void *thistime)
{
	struct rtc_time wtime;
	unsigned long nowtime = (unsigned long) thistime;
	to_tm(nowtime, &wtime);
	rtc8564_set_time(&wtime);
	return;
}


int ppc_rtc8564_set_time(unsigned long nowtime)
{
	struct rtc_time wtime;
	static DECLARE_WORK(set_rtc_work, deferred_set_rtc, NULL);

	if (unlikely(in_interrupt())) {
		/* because RTC works on interrupts (I2C access) 
		 * we can't set time while we are during interrupt
		 * processing, so set must be done later.
		 */
		/* if previous setting is not done - cancel it 
		 */
		cancel_delayed_work(&set_rtc_work);
		set_rtc_work.data = (void *)nowtime;
		schedule_work(&set_rtc_work);
		/* unfortunatelly, we can't wait till work_queue
		 * will be executed - lets assume it will return 0
		 */
		return 0;
	}
	to_tm(nowtime, &wtime);
	/* wtime probably needs some fiddling here (year -= 1900 etc.) */
	/* Be aware that adjtime uses /dev/port for rtc access: x86 only! */
	return rtc8564_set_time(&wtime);
}

static int rtc_8564_probe(struct i2c_adapter *adap, int addr, int kind)
{
	int ret;
	struct i2c_client *new_client;
	struct rtc8564_data *d;
	unsigned char data[10];
	unsigned char ad[1] = { 0 };
	struct i2c_msg ctrl_wr[1] = {
		{addr, 0, 2, data}
	};
	struct i2c_msg ctrl_rd[2] = {
		{addr, 0, 1, ad},
		{addr, I2C_M_RD, 2, data}
	};

	d = kmalloc(sizeof(struct rtc8564_data), GFP_KERNEL);
	if (!d) {
		ret = -ENOMEM;
		goto done;
	}
	memset(d, 0, sizeof(struct rtc8564_data));
	new_client = &d->client;

	strlcpy(new_client->name, "RTC8564", I2C_NAME_SIZE);
	i2c_set_clientdata(new_client, d);
	new_client->flags = I2C_CLIENT_ALLOW_USE | I2C_DF_NOTIFY;
	new_client->addr = addr;
	new_client->adapter = adap;
	new_client->driver = &rtc8564_driver;

	_DBG(1, "client=%p", new_client);

	/* init ctrl1 reg */
	data[0] = 0;
	data[1] = 0;
	ret = i2c_transfer(new_client->adapter, ctrl_wr, 1);
	if (ret != 1) {
		printk(KERN_ERR "rtc8564: cant init ctrl1\n");
		ret = -ENODEV;
		goto done;
	}

	/* read back ctrl1 and ctrl2 */
	ret = i2c_transfer(new_client->adapter, ctrl_rd, 2);
	if (ret != 2) {
		printk(KERN_ERR "rtc8564: cant read ctrl\n");
		ret = -ENODEV;
		goto done;
	}

	d->ctrl = data[0] | (data[1] << 8);

	_DBG(1, "RTC8564_REG_CTRL1=%02x, RTC8564_REG_CTRL2=%02x",
	     data[0], data[1]);

	ret = i2c_attach_client(new_client);
done:
	if (ret) {
		kfree(d);
	}

	this_client = new_client;

#ifdef CONFIG_PPC
        /* Hook up the wrapper to machdep for 11-minute mode support */
        ppc_md.set_rtc_time = ppc_rtc8564_set_time;
        ppc_md.get_rtc_time = ppc_rtc8564_get_time;
#endif


	return ret;
}

static int rtc_8564_attach(struct i2c_adapter *adap)
{
	return i2c_probe(adap, &addr_data, rtc_8564_probe);
}

static int rtc8564_detach(struct i2c_client *client)
{
	i2c_detach_client(client);
	kfree(i2c_get_clientdata(client));
	return 0;
}


static int rtc8564_get_ctrl(struct i2c_client *client, unsigned int *ctrl)
{
	struct rtc8564_data *data = i2c_get_clientdata(client);

	if (!ctrl)
		return -1;

	*ctrl = data->ctrl;
	return 0;
}

static int rtc8564_set_ctrl(struct i2c_client *client, unsigned int *ctrl)
{
	struct rtc8564_data *data = i2c_get_clientdata(client);
	unsigned char buf[2];

	if (!ctrl)
		return -1;

	buf[0] = *ctrl & 0xff;
	buf[1] = (*ctrl & 0xff00) >> 8;
	data->ctrl = *ctrl;

	return rtc8564_write(client, 0, buf, 2);
}

static int rtc8564_read_mem(struct i2c_client *client, struct mem *mem)
{

	if (!mem)
		return -EINVAL;

	return rtc8564_recv(client, mem->data, mem->loc, mem->nr);
}

static int rtc8564_write_mem(struct i2c_client *client, struct mem *mem)
{

	if (!mem)
		return -EINVAL;

	return rtc8564_write(client, mem->loc, mem->data, mem->nr);
}

static int
rtc8564_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
	int rc;
	_DBG(1, "cmd=%d", cmd);

	down(&rtc8564_sem);
	switch (cmd) {
	case RTC_GETDATETIME:
		rc = rtc8564_get_datetime(client, arg);
		break;

	case RTC_SETTIME:
		rc = rtc8564_set_datetime(client, arg, 0);
		break;

	case RTC_SETDATETIME:
		rc = rtc8564_set_datetime(client, arg, 1);
		break;

	case RTC_GETCTRL:
		rc = rtc8564_get_ctrl(client, arg);
		break;

	case RTC_SETCTRL:
		rc = rtc8564_set_ctrl(client, arg);
		break;

	case MEM_READ:
		rc = rtc8564_read_mem(client, arg);
		break;

	case MEM_WRITE:
		rc = rtc8564_write_mem(client, arg);
		break;

	default:
		rc = -EINVAL;
		break;
	}

	up(&rtc8564_sem);
	return rc;
}

static struct i2c_driver rtc8564_driver = {
	.owner		= THIS_MODULE,
	.name		= "RTC8564",
	.id		= I2C_DRIVERID_RTC8564,
	.flags		= I2C_DF_NOTIFY,
	.attach_adapter = rtc_8564_attach,
	.detach_client	= rtc8564_detach,
	.command	= rtc8564_command
};

static __init int rtc8564_init(void)
{
	return i2c_add_driver(&rtc8564_driver);
}

static __exit void rtc8564_exit(void)
{
	i2c_del_driver(&rtc8564_driver);
}

MODULE_AUTHOR("Stefan Eletzhofer <Stefan.Eletzhofer@eletztrick.de>");
MODULE_DESCRIPTION("EPSON RTC8564 Driver");
MODULE_LICENSE("GPL");

module_init(rtc8564_init);
module_exit(rtc8564_exit);

[-- Attachment #3: rtc8564.h --]
[-- Type: text/x-chdr, Size: 2356 bytes --]

/*
 *  linux/drivers/i2c/chips/rtc8564.h
 *
 *  Copyright (C) 2002-2004 Stefan Eletzhofer
 *
 *	based on linux/drivers/acron/char/pcf8583.h
 *  Copyright (C) 2000 Russell King
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
struct rtc_tm {
	unsigned char	secs;
	unsigned char	mins;
	unsigned char	hours;
	unsigned char	mday;
	unsigned char	mon;
	unsigned short	year; /* xxxx 4 digits :) */
	unsigned char	wday;
	unsigned char	vl;
};

struct mem {
	unsigned int	loc;
	unsigned int	nr;
	unsigned char	*data;
};

#define RTC_GETDATETIME	0
#define RTC_SETTIME	1
#define RTC_SETDATETIME	2
#define RTC_GETCTRL	3
#define RTC_SETCTRL	4
#define MEM_READ	5
#define MEM_WRITE	6

#define RTC8564_REG_CTRL1		0x0 /* T  0 S 0 | T 0 0 0 */
#define RTC8564_REG_CTRL2		0x1 /* 0  0 0 TI/TP | AF TF AIE TIE */
#define RTC8564_REG_SEC			0x2 /* VL 4 2 1 | 8 4 2 1 */
#define RTC8564_REG_MIN			0x3 /* x  4 2 1 | 8 4 2 1 */
#define RTC8564_REG_HR			0x4 /* x  x 2 1 | 8 4 2 1 */
#define RTC8564_REG_DAY			0x5 /* x  x 2 1 | 8 4 2 1 */
#define RTC8564_REG_WDAY		0x6 /* x  x x x | x 4 2 1 */
#define RTC8564_REG_MON_CENT	0x7 /* C  x x 1 | 8 4 2 1 */
#define RTC8564_REG_YEAR		0x8 /* 8  4 2 1 | 8 4 2 1 */
#define RTC8564_REG_AL_MIN		0x9 /* AE 4 2 1 | 8 4 2 1 */
#define RTC8564_REG_AL_HR		0xa /* AE 4 2 1 | 8 4 2 1 */
#define RTC8564_REG_AL_DAY		0xb /* AE x 2 1 | 8 4 2 1 */
#define RTC8564_REG_AL_WDAY		0xc /* AE x x x | x 4 2 1 */
#define RTC8564_REG_CLKOUT		0xd /* FE x x x | x x FD1 FD0 */
#define RTC8564_REG_TCTL		0xe /* TE x x x | x x FD1 FD0 */
#define RTC8564_REG_TIMER		0xf /* 8 bit binary */

/* Control reg */
#define RTC8564_CTRL1_TEST1		(1<<3)
#define RTC8564_CTRL1_STOP		(1<<5)
#define RTC8564_CTRL1_TEST2		(1<<7)

#define RTC8564_CTRL2_TIE		(1<<0)
#define RTC8564_CTRL2_AIE		(1<<1)
#define RTC8564_CTRL2_TF		(1<<2)
#define RTC8564_CTRL2_AF		(1<<3)
#define RTC8564_CTRL2_TI_TP		(1<<4)

/* CLKOUT frequencies */
#define RTC8564_FD_32768HZ		(0x0)
#define RTC8564_FD_1024HZ		(0x1)
#define RTC8564_FD_32			(0x2)
#define RTC8564_FD_1HZ			(0x3)

/* Timer CTRL */
#define RTC8564_TD_4096HZ		(0x0)
#define RTC8564_TD_64HZ			(0x1)
#define RTC8564_TD_1HZ			(0x2)
#define RTC8564_TD_1_60HZ		(0x3)

#define I2C_DRIVERID_RTC8564 0xf000

^ permalink raw reply

* Re: [PATCH] spufs: fix compile
From: Christoph Hellwig @ 2006-04-07 11:54 UTC (permalink / raw)
  To: arndb; +Cc: linuxppc-dev
In-Reply-To: <20060406134810.GB8552@lst.de>

On Thu, Apr 06, 2006 at 03:48:10PM +0200, Christoph Hellwig wrote:
> The current tree isn't exctly sure about the arguments to
> alloc_spu_context, let it agree on the no-arguments version.

Please ignore all these patches, I had a messed up tree.

^ permalink raw reply

* Re: [PATCH 2/4] tickless idle cpu: Skip ticks when CPU is idle
From: Kumar Gala @ 2006-04-07 14:16 UTC (permalink / raw)
  To: vatsa; +Cc: sri_vatsa_v, paulus, linuxppc-dev
In-Reply-To: <20060407063131.GB22416@in.ibm.com>


On Apr 7, 2006, at 1:31 AM, Srivatsa Vaddagiri wrote:

> This is the core patch which skips ticks when a CPU is idle.
> Should work on pSeries, pmac and maple machines.
>
> The patch is against 2.6.17-rc1-mm1 and has been tested on a 16-way  
> (with SMT)
> Power5 box (p570).
>
> Signed-off-by: Srivatsa Vaddagiri <vatsa@in.ibm.com>
>
> ---
>
>  linux-2.6.17-rc1-root/arch/powerpc/Kconfig                   |    6
>  linux-2.6.17-rc1-root/arch/powerpc/kernel/idle_power4.S      |    3
>  linux-2.6.17-rc1-root/arch/powerpc/kernel/irq.c              |    3
>  linux-2.6.17-rc1-root/arch/powerpc/kernel/time.c             |   
> 150 ++++++++---
>  linux-2.6.17-rc1-root/arch/powerpc/kernel/traps.c            |    1
>  linux-2.6.17-rc1-root/arch/powerpc/platforms/pseries/setup.c |    6
>  linux-2.6.17-rc1-root/include/asm-powerpc/time.h             |    8
>  7 files changed, 147 insertions(+), 30 deletions(-)
>

[snip]

> diff -puN arch/powerpc/Kconfig~no_idle_hz arch/powerpc/Kconfig
> --- linux-2.6.17-rc1/arch/powerpc/Kconfig~no_idle_hz	2006-04-07  
> 04:14:39.000000000 +0530
> +++ linux-2.6.17-rc1-root/arch/powerpc/Kconfig	2006-04-07  
> 04:14:58.000000000 +0530
> @@ -593,6 +593,12 @@ config HOTPLUG_CPU
>
>  	  Say N if you are unsure.
>
> +config NO_IDLE_HZ
> +	depends on EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC || PPC_MAPLE)
> +	bool "Switch off timer ticks on idle CPUs"
> +	help
> +	  Switches the HZ timer interrupts off when a CPU is idle.
> +

any reason not to provide this for all 6xx class processors?

>  config KEXEC
>  	bool "kexec system call (EXPERIMENTAL)"
>  	depends on PPC_MULTIPLATFORM && EXPERIMENTAL

^ permalink raw reply

* [PATCH 0/5] cell: recent bug fixes
From: arnd @ 2006-04-07 15:01 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev, cbe-oss-dev

This set of patches is mostly about making it possible to use
64k pages on the Cell platform, which did not work because
of a number of bugs.

Paulus, please apply to your bugfix tree.

	Arnd <><

^ permalink raw reply

* Re: RTC/I2C on 82xx with Linux 2.6.x
From: Mark A. Greer @ 2006-04-07 15:17 UTC (permalink / raw)
  To: Claus Gindhart; +Cc: linuxppc-embedded
In-Reply-To: <200604071057.26265.claus.gindhart@kontron-modular.com>

On Fri, Apr 07, 2006 at 10:57:25AM +0200, Claus Gindhart wrote:
> Laurent,
> 
> attached you find a rtc-driver for 2.6.13.
> I ported it from 2.4 myself, because i didnt find any 2.6-port out in the 
> world.
> the ppc_md-structure entries are initialized within the driver itself. This is 
> propably not 100% consistent with the coding conventions, but it works fro 
> me.
> This i2c-layer can still be used with this driver; i have a LM75 and an EEPROM 
> on the same bus, which i operate via LM-Sensors and the i2c-dev driver.

Note that there is a drivers/rtc directory that new (and old) rtc drivers
should be ported to.

Mark

^ permalink raw reply

* Re: [PATCH 4/5] powerpc: export symbols for page size selection
From: Christoph Hellwig @ 2006-04-07 15:28 UTC (permalink / raw)
  To: arnd; +Cc: linuxppc-dev, Paul Mackerras, cbe-oss-dev, Arnd Bergmann
In-Reply-To: <20060407150743.688538000@dyn-9-152-242-103.boeblingen.de.ibm.com>

On Fri, Apr 07, 2006 at 12:00:04AM +0200, arnd@arndb.de wrote:
> We need access to some symbols in powerpc memory management
> from spufs in order to create proper SLB entries.

One more reason to disallow modular spufs..

^ permalink raw reply

* Re: [PATCH 4/5] powerpc: export symbols for page size selection
From: Olof Johansson @ 2006-04-07 15:42 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: linuxppc-dev, Paul Mackerras, cbe-oss-dev, Arnd Bergmann
In-Reply-To: <20060407152813.GA382@lst.de>

On Fri, Apr 07, 2006 at 05:28:13PM +0200, Christoph Hellwig wrote:
> On Fri, Apr 07, 2006 at 12:00:04AM +0200, arnd@arndb.de wrote:
> > We need access to some symbols in powerpc memory management
> > from spufs in order to create proper SLB entries.
> 
> One more reason to disallow modular spufs..

Yeah, what's the need for that, really? It needs to know so much of
kernel internals that it's getting silly to allow it to be a module.


-Olof

^ 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