* [PATCH] Do ioremap and allocation for sleep on 3400 once at boot
From: Paul Mackerras @ 2007-12-13 5:15 UTC (permalink / raw)
To: linuxppc-dev
Currently the sleep code on the old powerbook 3400 does an ioremap and
a kmalloc on each sleep/wakeup cycle. This moves the ioremap and
kmalloc to boot-time code (via_pmu_start) so that they only need to be
done once. This will be more convenient when we change to using the
generic suspend code, since it will avoid the need to do the
ioremap/kmalloc after devices have been suspended.
Signed-off-by: Paul Mackerras <paulus@samba.org>
---
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 35e1f22..0e84cb8 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -203,6 +203,12 @@ static int proc_read_options(char *page, char **start, off_t off,
static int proc_write_options(struct file *file, const char __user *buffer,
unsigned long count, void *data);
+#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32)
+static void powerbook_sleep_init_3400(void);
+#else
+#define powerbook_sleep_init_3400() do { } while (0)
+#endif
+
#ifdef CONFIG_ADB
struct adb_driver via_pmu_driver = {
"PMU",
@@ -450,6 +456,10 @@ static int __init via_pmu_start(void)
pmu_poll();
} while (pmu_state != idle);
+ /* Do allocations and ioremaps that will be needed for sleep */
+ if (pmu_kind == PMU_OHARE_BASED)
+ powerbook_sleep_init_3400();
+
return 0;
}
@@ -2271,26 +2281,30 @@ powerbook_sleep_Core99(void)
#define PB3400_MEM_CTRL 0xf8000000
#define PB3400_MEM_CTRL_SLEEP 0x70
-static int
-powerbook_sleep_3400(void)
+static void __iomem *pb3400_mem_ctrl;
+
+static void powerbook_sleep_init_3400(void)
+{
+ /* map in the memory controller registers */
+ pb3400_mem_ctrl = ioremap(PB3400_MEM_CTRL, 0x100);
+ if (pb3400_mem_ctrl == NULL)
+ printk(KERN_WARNING "ioremap failed: sleep won't be possible");
+
+ /* Allocate room for PCI save */
+ pbook_alloc_pci_save();
+}
+
+static int powerbook_sleep_3400(void)
{
int ret, i, x;
unsigned int hid0;
unsigned long p;
struct adb_request sleep_req;
- void __iomem *mem_ctrl;
unsigned int __iomem *mem_ctrl_sleep;
- /* first map in the memory controller registers */
- mem_ctrl = ioremap(PB3400_MEM_CTRL, 0x100);
- if (mem_ctrl == NULL) {
- printk("powerbook_sleep_3400: ioremap failed\n");
+ if (pb3400_mem_ctrl == NULL)
return -ENOMEM;
- }
- mem_ctrl_sleep = mem_ctrl + PB3400_MEM_CTRL_SLEEP;
-
- /* Allocate room for PCI save */
- pbook_alloc_pci_save();
+ mem_ctrl_sleep = pb3400_mem_ctrl + PB3400_MEM_CTRL_SLEEP;
ret = pmac_suspend_devices();
if (ret) {
@@ -2343,8 +2357,6 @@ powerbook_sleep_3400(void)
mb();
pmac_wakeup_devices();
- pbook_free_pci_save();
- iounmap(mem_ctrl);
return 0;
}
^ permalink raw reply related
* Re: [PATCH 2/2] kdump shutdown hook support
From: Olof Johansson @ 2007-12-13 5:13 UTC (permalink / raw)
To: Michael Neuling; +Cc: linuxppc-dev, RAISCH, Paul Mackerras, THEMANN
In-Reply-To: <20071213051224.GA22378@lixom.net>
On Wed, Dec 12, 2007 at 11:12:24PM -0600, Olof Johansson wrote:
> Hi,
> > + __delay(SETJMP_MACHINE_CHECK_DELAY);
>
> Where is this defined?
Oops, nevermind. In 1/2, of course. :-)
-Olof
^ permalink raw reply
* Re: [PATCH 2/2] kdump shutdown hook support
From: Olof Johansson @ 2007-12-13 5:12 UTC (permalink / raw)
To: Michael Neuling; +Cc: linuxppc-dev, RAISCH, Paul Mackerras, THEMANN
In-Reply-To: <20071213031618.DBD207038C@localhost.localdomain>
Hi,
On Thu, Dec 13, 2007 at 02:16:18PM +1100, Michael Neuling wrote:
> Index: clone3/arch/powerpc/kernel/crash.c
> ===================================================================
> --- clone3.orig/arch/powerpc/kernel/crash.c
> +++ clone3/arch/powerpc/kernel/crash.c
> @@ -32,6 +32,8 @@
> #include <asm/lmb.h>
> #include <asm/firmware.h>
> #include <asm/smp.h>
> +#include <asm/system.h>
> +#include <asm/setjmp.h>
>
> #ifdef DEBUG
> #include <asm/udbg.h>
> @@ -45,6 +47,11 @@ int crashing_cpu = -1;
> static cpumask_t cpus_in_crash = CPU_MASK_NONE;
> cpumask_t cpus_in_sr = CPU_MASK_NONE;
>
> +#define CRASH_HANDLER_MAX 1
> +/* NULL terminated list of shutdown handles */
> +static crash_shutdown_t crash_shutdown_handles[CRASH_HANDLER_MAX+1];
> +static DEFINE_SPINLOCK(crash_handers_lock);
How about just using 'handlers' instead of 'handers' and 'handles'? :)
> static atomic_t enter_on_soft_reset = ATOMIC_INIT(0);
>
> @@ -285,9 +292,72 @@ static inline void crash_kexec_stop_spus
> }
> #endif /* CONFIG_SPU_BASE */
>
> +/*
> + * Register a function to be called on shutdown. Only use this if you
> + * can't reset your device in the second kernel.
> + */
> +int crash_shutdown_register(crash_shutdown_t handler)
> +{
> + unsigned int i, rc;
> +
> + spin_lock(&crash_handers_lock);
> + for (i = 0 ; i < CRASH_HANDLER_MAX; i++)
> + if (!crash_shutdown_handles[i]) {
> + /* Insert handle at first empty entry */
> + crash_shutdown_handles[i] = handler;
> + rc = 0;
> + break;
> + }
> +
> + if (i == CRASH_HANDLER_MAX) {
> + printk(KERN_ERR "Crash shutdown handles full, "
> + "not registered.\n");
> + rc = 1;
> + }
> +
> + spin_unlock(&crash_handers_lock);
> + return rc;
> +}
> +EXPORT_SYMBOL(crash_shutdown_register);
> +
> +int crash_shutdown_unregister(crash_shutdown_t handler)
> +{
> + unsigned int i, rc;
> +
> + spin_lock(&crash_handers_lock);
> + for (i = 0 ; i < CRASH_HANDLER_MAX; i++)
> + if (crash_shutdown_handles[i] == handler)
> + break;
> +
> + if (i == CRASH_HANDLER_MAX) {
> + printk(KERN_ERR "Crash shutdown handle not found\n");
> + rc = 1;
> + } else {
> + /* Shift handles down */
> + for (; crash_shutdown_handles[i]; i++)
> + crash_shutdown_handles[i] =
> + crash_shutdown_handles[i+1];
> + rc = 0;
> + }
> +
> + spin_unlock(&crash_handers_lock);
> + return rc;
> +}
> +EXPORT_SYMBOL(crash_shutdown_unregister);
> +
> +static unsigned long crash_shutdown_buf[SETJMP_BUF_LEN];
> +
> +static int handle_fault(struct pt_regs *regs)
> +{
> + longjmp(crash_shutdown_buf, 1);
> + return 0;
> +}
> +
> void default_machine_crash_shutdown(struct pt_regs *regs)
> {
> - unsigned int irq;
> + unsigned int i;
> + int (*old_handler)(struct pt_regs *regs);
> +
>
> /*
> * This function is only called after the system
> @@ -301,15 +371,37 @@ void default_machine_crash_shutdown(stru
> */
> hard_irq_disable();
>
> - for_each_irq(irq) {
> - struct irq_desc *desc = irq_desc + irq;
> + for_each_irq(i) {
> + struct irq_desc *desc = irq_desc + i;
>
> if (desc->status & IRQ_INPROGRESS)
> - desc->chip->eoi(irq);
> + desc->chip->eoi(i);
>
> if (!(desc->status & IRQ_DISABLED))
> - desc->chip->disable(irq);
> + desc->chip->disable(i);
> + }
> +
> + /*
> + * Call registered shutdown routines savely. Swap out
> + * __debugger_fault_handler, and replace on exit.
> + */
> + old_handler = __debugger_fault_handler;
> + __debugger_fault_handler = handle_fault;
> + for (i = 0; crash_shutdown_handles[i]; i++) {
> + if (setjmp(crash_shutdown_buf) == 0) {
> + /*
> + * Insert syncs and delay to ensure
> + * instructions in the dangerous region don't
> + * leak away from this protected region.
> + */
> + asm volatile("sync; isync");
> + /* dangerous region */
> + crash_shutdown_handles[i]();
> + asm volatile("sync; isync");
> + __delay(SETJMP_MACHINE_CHECK_DELAY);
Where is this defined?
> + }
> }
> + __debugger_fault_handler = old_handler;
>
> /*
> * Make a note of crashing cpu. Will be used in machine_kexec
> Index: clone3/include/asm-powerpc/kexec.h
> ===================================================================
> --- clone3.orig/include/asm-powerpc/kexec.h
> +++ clone3/include/asm-powerpc/kexec.h
> @@ -123,6 +123,9 @@ struct pt_regs;
> extern void default_machine_kexec(struct kimage *image);
> extern int default_machine_kexec_prepare(struct kimage *image);
> extern void default_machine_crash_shutdown(struct pt_regs *regs);
> +typedef void (*crash_shutdown_t)(void);
> +extern int crash_shutdown_register(crash_shutdown_t handler);
> +extern int crash_shutdown_unregister(crash_shutdown_t handler);
>
> extern void machine_kexec_simple(struct kimage *image);
> extern void crash_kexec_secondary(struct pt_regs *regs);
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
^ permalink raw reply
* [PATCH] Convert therm_windtunnel.c to use the kthread API
From: Paul Mackerras @ 2007-12-13 4:57 UTC (permalink / raw)
To: linuxppc-dev
This is fairly straightforward, and lets us get rid of x.completion
as well.
Signed-off-by: Paul Mackerras <paulus@samba.org>
---
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c
index 5452da1..3722402 100644
--- a/drivers/macintosh/therm_windtunnel.c
+++ b/drivers/macintosh/therm_windtunnel.c
@@ -36,6 +36,7 @@
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/init.h>
+#include <linux/kthread.h>
#include <asm/prom.h>
#include <asm/machdep.h>
@@ -61,8 +62,7 @@ I2C_CLIENT_INSMOD;
static struct {
volatile int running;
- struct completion completion;
- pid_t poll_task;
+ struct task_struct *poll_task;
struct semaphore lock;
struct of_device *of_dev;
@@ -282,27 +282,27 @@ restore_regs( void )
write_reg( x.fan, 0x00, x.r0, 1 );
}
-static int
-control_loop( void *dummy )
+static int control_loop(void *dummy)
{
- daemonize("g4fand");
-
- down( &x.lock );
+ down(&x.lock);
setup_hardware();
+ up(&x.lock);
- while( x.running ) {
- up( &x.lock );
-
+ for (;;) {
msleep_interruptible(8000);
-
- down( &x.lock );
+ if (kthread_should_stop())
+ break;
+
+ down(&x.lock);
poll_temp();
+ up(&x.lock);
}
+ down(&x.lock);
restore_regs();
- up( &x.lock );
+ up(&x.lock);
- complete_and_exit( &x.completion, 0 );
+ return 0;
}
@@ -322,8 +322,7 @@ do_attach( struct i2c_adapter *adapter )
ret = i2c_probe( adapter, &addr_data, &do_probe );
if( x.thermostat && x.fan ) {
x.running = 1;
- init_completion( &x.completion );
- x.poll_task = kernel_thread( control_loop, NULL, SIGCHLD | CLONE_KERNEL );
+ x.poll_task = kthread_run(control_loop, NULL, "g4fand");
}
}
return ret;
@@ -339,7 +338,8 @@ do_detach( struct i2c_client *client )
else {
if( x.running ) {
x.running = 0;
- wait_for_completion( &x.completion );
+ kthread_stop(x.poll_task);
+ x.poll_task = NULL;
}
if( client == x.thermostat )
x.thermostat = NULL;
^ permalink raw reply related
* [PATCH] Convert therm_pm72.c to use the kthread API
From: Paul Mackerras @ 2007-12-13 4:54 UTC (permalink / raw)
To: linuxppc-dev
This converts the therm_pm72.c driver to use the kthread API. I
thought about making it use kthread_stop() instead of the `state'
variable and the `ctrl_complete' completion, but that isn't simple and
will require changing the way that `state' is used.
Signed-off-by: Paul Mackerras <paulus@samba.org>
---
diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c
index e43554e..6fadc9a 100644
--- a/drivers/macintosh/therm_pm72.c
+++ b/drivers/macintosh/therm_pm72.c
@@ -121,6 +121,7 @@
#include <linux/reboot.h>
#include <linux/kmod.h>
#include <linux/i2c.h>
+#include <linux/kthread.h>
#include <asm/prom.h>
#include <asm/machdep.h>
#include <asm/io.h>
@@ -161,7 +162,7 @@ static struct slots_pid_state slots_state;
static int state;
static int cpu_count;
static int cpu_pid_type;
-static pid_t ctrl_task;
+static struct task_struct *ctrl_task;
static struct completion ctrl_complete;
static int critical_state;
static int rackmac;
@@ -1779,8 +1780,6 @@ static int call_critical_overtemp(void)
*/
static int main_control_loop(void *x)
{
- daemonize("kfand");
-
DBG("main_control_loop started\n");
down(&driver_lock);
@@ -1956,7 +1955,7 @@ static void start_control_loops(void)
{
init_completion(&ctrl_complete);
- ctrl_task = kernel_thread(main_control_loop, NULL, SIGCHLD | CLONE_KERNEL);
+ ctrl_task = kthread_run(main_control_loop, NULL, "kfand");
}
/*
@@ -1964,7 +1963,7 @@ static void start_control_loops(void)
*/
static void stop_control_loops(void)
{
- if (ctrl_task != 0)
+ if (ctrl_task)
wait_for_completion(&ctrl_complete);
}
^ permalink raw reply related
* RE: Xilinx devicetrees
From: Stephen Neuendorffer @ 2007-12-13 4:52 UTC (permalink / raw)
To: Koss, Mike (Mission Systems), David H. Lynch Jr., Grant Likely,
linuxppc-embedded
In-Reply-To: <EDAE140DF1B2FC42B5867C22CA0B333F0A58E4@XMBIL132.northgrum.com>
[-- Attachment #1: Type: text/plain, Size: 3699 bytes --]
-----Original Message-----
From: Koss, Mike (Mission Systems) [mailto:mike.koss@ngc.com]
Sent: Mon 11/26/2007 7:31 AM
To: Stephen Neuendorffer; David H. Lynch Jr.; Grant Likely; linuxppc-embedded
Subject: RE: Xilinx devicetrees
Time for my $.02, since I am heavily weighting my future designs on the
use of the device trees. :) (and b/c I don't check my work e-mail from
home ;P)
________________________________
SN> As Grant says, the dynamic detection doesn't have to be done in the
boot loader, it could be done in the platform code. You can largely
ignore
SN> the device trees, or always boot with a core device tree and figure
it all out later (perhaps using version registers). I anticipate that
SN> the 'standard flow' will have standard platform code for any board
that uses a complete device tree. If you have the need to do something
SN> extraordinary, then you should feel free to hack away... However,
It doesn't seem to me to be really necessary in your case, assuming that
SN> the device tree is packaged (somehow, TBD) along with the bitstream.
> I don't know if packaging the device tree with the bitstream is the best
> way to go. It's possible that it could lead to headaches for certain
> systems that have security restrictions. The same could be said for
> using it w/ the SystemACE to load it into RAM after the image. (which is
> what I'm currently doing for my 2 linux images in lieu of a true on-chip
> bootloader). I am already taking the security concerns into account for
> future revisions of the hardware wrt to using a SystemACE, and am
> planning on moving the device trees into NV storage like FLASH.
'with' not 'in'. either using SystemAce, or a flash image.
> One solution I've been thinking through (in lieu of direct support from
> EDK) is to use a tcl script with xps to traverse the hardware tree and
> generate the device tree. It seems like it should be relatively trivial
> to obtain the information. It's just going to be a pain to write all the
> handlers for each different linux driver: temac, interrupt controller,
> DMA controller, etc.
> In reality the best way to handle this would be to have EDK generate the
> device tree as part of the library/bsp build process.
We have a python script to do this. The main problem with just looking at the mhs file is that you lose all the defaults for each IP. Hence, we've also written a BSP generator to do this. both are at git://git.xilinx.com/gen-mhs-devtree.py
Once I can verify that they work in the mainline tree, I'll be sending out the patches that make this all work.
> Now, what I'd like
> to see with regards to this is the ability to change the handler for the
> generating a specific device information. An example could be the temac.
> If at some point in the future the temac needs new/more information to
> support its configuration/run-time then having to get a patch from
> Xilinx for a EDK is way too slow. The developers should be giving the
> opportunity to inject a new handler into the various parts of the device
> tree generation. That way when the kernel patch is submitted, an EDK
> device generator patch will be submitted at the same time to keep
> everything in sync.
Interesting idea.. I've been trying to figure out how to architect this better, but it requires some information passing within EDK that isnot today supported. I don't see at all how to synchronize this with patches to the kernel, tho. My approach is to describe the hardware as completely and faithfully as we can (given the information in EDK), and let the drivers do whatever with it that they want to.
Steve
[-- Attachment #2: Type: text/html, Size: 4504 bytes --]
^ permalink raw reply
* [PATCH] Convert adb.c to use kthread API and not spin on ADB requests
From: Paul Mackerras @ 2007-12-13 4:11 UTC (permalink / raw)
To: linuxppc-dev
This converts adb.c to use the kthread API.
It also changes adb_request so that if the ADBREQ_SYNC flag is
specified, we now sleep waiting for the request to finish using an
on-stack completion rather than spinning. To implement this, we now
require that if the ADBREQ_SYNC flag is set, the `done' parameter must
be NULL. All of the existing callers of adb_request that pass
ADBREQ_SYNC appear to be in process context and have done == NULL.
Doing this allows us to get rid of an awful hack in adb_request()
where we used to test whether the request was coming from the adb
probe task and use a completion if it was, and otherwise spin.
This also gets rid of a static request block that was used if the req
parameter to adb_request was NULL. None of the callers do that any
more, so the static request block is no longer necessary.
Signed-off-by: Paul Mackerras <paulus@samba.org>
---
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
index 7b892f4..5ae28f0 100644
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -35,6 +35,7 @@
#include <linux/spinlock.h>
#include <linux/completion.h>
#include <linux/device.h>
+#include <linux/kthread.h>
#include <asm/uaccess.h>
#include <asm/semaphore.h>
@@ -82,9 +83,7 @@ struct adb_driver *adb_controller;
BLOCKING_NOTIFIER_HEAD(adb_client_list);
static int adb_got_sleep;
static int adb_inited;
-static pid_t adb_probe_task_pid;
static DECLARE_MUTEX(adb_probe_mutex);
-static struct completion adb_probe_task_comp;
static int sleepy_trackpad;
static int autopoll_devs;
int __adb_probe_sync;
@@ -126,16 +125,6 @@ static void printADBreply(struct adb_request *req)
}
#endif
-
-static __inline__ void adb_wait_ms(unsigned int ms)
-{
- if (current->pid && adb_probe_task_pid &&
- adb_probe_task_pid == current->pid)
- msleep(ms);
- else
- mdelay(ms);
-}
-
static int adb_scan_bus(void)
{
int i, highFree=0, noMovement;
@@ -240,13 +229,10 @@ static int adb_scan_bus(void)
static int
adb_probe_task(void *x)
{
- strcpy(current->comm, "kadbprobe");
-
printk(KERN_INFO "adb: starting probe task...\n");
do_adb_reset_bus();
printk(KERN_INFO "adb: finished probe task...\n");
- adb_probe_task_pid = 0;
up(&adb_probe_mutex);
return 0;
@@ -255,7 +241,7 @@ adb_probe_task(void *x)
static void
__adb_probe_task(struct work_struct *bullshit)
{
- adb_probe_task_pid = kernel_thread(adb_probe_task, NULL, SIGCHLD | CLONE_KERNEL);
+ kthread_run(adb_probe_task, NULL, "kadbprobe");
}
static DECLARE_WORK(adb_reset_work, __adb_probe_task);
@@ -341,7 +327,6 @@ int __init adb_init(void)
sleepy_trackpad = 1;
#endif /* CONFIG_PPC */
- init_completion(&adb_probe_task_comp);
adbdev_init();
adb_reset_bus();
}
@@ -366,7 +351,7 @@ do_adb_reset_bus(void)
if (sleepy_trackpad) {
/* Let the trackpad settle down */
- adb_wait_ms(500);
+ msleep(500);
}
down(&adb_handler_sem);
@@ -382,7 +367,7 @@ do_adb_reset_bus(void)
if (sleepy_trackpad) {
/* Let the trackpad settle down */
- adb_wait_ms(1500);
+ msleep(1500);
}
if (!ret) {
@@ -406,41 +391,27 @@ adb_poll(void)
adb_controller->poll();
}
-static void
-adb_probe_wakeup(struct adb_request *req)
+static void adb_sync_req_done(struct adb_request *req)
{
- complete(&adb_probe_task_comp);
-}
+ struct completion *comp = req->arg;
-/* Static request used during probe */
-static struct adb_request adb_sreq;
-static unsigned long adb_sreq_lock; // Use semaphore ! */
+ complete(comp);
+}
int
adb_request(struct adb_request *req, void (*done)(struct adb_request *),
int flags, int nbytes, ...)
{
va_list list;
- int i, use_sreq;
+ int i;
int rc;
+ struct completion comp;
if ((adb_controller == NULL) || (adb_controller->send_request == NULL))
return -ENXIO;
if (nbytes < 1)
return -EINVAL;
- if (req == NULL && (flags & ADBREQ_NOSEND))
- return -EINVAL;
-
- if (req == NULL) {
- if (test_and_set_bit(0,&adb_sreq_lock)) {
- printk("adb.c: Warning: contention on static request !\n");
- return -EPERM;
- }
- req = &adb_sreq;
- flags |= ADBREQ_SYNC;
- use_sreq = 1;
- } else
- use_sreq = 0;
+
req->nbytes = nbytes+1;
req->done = done;
req->reply_expected = flags & ADBREQ_REPLY;
@@ -453,25 +424,18 @@ adb_request(struct adb_request *req, void (*done)(struct adb_request *),
if (flags & ADBREQ_NOSEND)
return 0;
- /* Synchronous requests send from the probe thread cause it to
- * block. Beware that the "done" callback will be overriden !
- */
- if ((flags & ADBREQ_SYNC) &&
- (current->pid && adb_probe_task_pid &&
- adb_probe_task_pid == current->pid)) {
- req->done = adb_probe_wakeup;
- rc = adb_controller->send_request(req, 0);
- if (rc || req->complete)
- goto bail;
- wait_for_completion(&adb_probe_task_comp);
- rc = 0;
- goto bail;
+ /* Synchronous requests block using an on-stack completion */
+ if (flags & ADBREQ_SYNC) {
+ WARN_ON(done);
+ req->done = adb_sync_req_done;
+ req->arg = ∁
+ init_completion(&comp);
}
- rc = adb_controller->send_request(req, flags & ADBREQ_SYNC);
-bail:
- if (use_sreq)
- clear_bit(0, &adb_sreq_lock);
+ rc = adb_controller->send_request(req, 0);
+
+ if ((flags & ADBREQ_SYNC) && !rc && !req->complete)
+ wait_for_completion(&comp);
return rc;
}
^ permalink raw reply related
* printf - How does it work?
From: Siva Prasad @ 2007-12-13 3:23 UTC (permalink / raw)
To: linuxppc-dev
[-- Attachment #1: Type: text/plain, Size: 385 bytes --]
Hi,
Can some one point me to an URL or some thing that explains how exactly
the characters from printf in user program gets printed on to the
console. Some thing like "it goes to /dev/console, and kernel reads from
....." would be great, so that I can trace it out.
Is there any way, we can get access to those prints from the kernel?
Thanks
Siva
[-- Attachment #2: Type: text/html, Size: 2490 bytes --]
^ permalink raw reply
* [PATCH 2/2] kdump shutdown hook support
From: Michael Neuling @ 2007-12-13 3:16 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, Michael Neuling, RAISCH, THEMANN
In-Reply-To: <1197515777.834799.307108384755.qpush@coopers>
This adds hooks into the default_machine_crash_shutdown so drivers can
register a function to be run in the first kernel before we hand off
to the second kernel. This should only be used in exceptional
circumstances, like where the device can't be reset in the second
kernel alone (as is the case with eHEA). To emphasize this, the
number of handles allowed to be registered is currently #def to 1.
This uses the setjmp/longjmp code to call out to the registered hooks,
so any bogus exceptions we encounter will hopefully be recoverable.
Tested with bogus data and instruction exceptions.
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
arch/powerpc/kernel/crash.c | 102 +++++++++++++++++++++++++++++++++++++++++---
include/asm-powerpc/kexec.h | 3 +
2 files changed, 100 insertions(+), 5 deletions(-)
Index: clone3/arch/powerpc/kernel/crash.c
===================================================================
--- clone3.orig/arch/powerpc/kernel/crash.c
+++ clone3/arch/powerpc/kernel/crash.c
@@ -32,6 +32,8 @@
#include <asm/lmb.h>
#include <asm/firmware.h>
#include <asm/smp.h>
+#include <asm/system.h>
+#include <asm/setjmp.h>
#ifdef DEBUG
#include <asm/udbg.h>
@@ -45,6 +47,11 @@ int crashing_cpu = -1;
static cpumask_t cpus_in_crash = CPU_MASK_NONE;
cpumask_t cpus_in_sr = CPU_MASK_NONE;
+#define CRASH_HANDLER_MAX 1
+/* NULL terminated list of shutdown handles */
+static crash_shutdown_t crash_shutdown_handles[CRASH_HANDLER_MAX+1];
+static DEFINE_SPINLOCK(crash_handers_lock);
+
#ifdef CONFIG_SMP
static atomic_t enter_on_soft_reset = ATOMIC_INIT(0);
@@ -285,9 +292,72 @@ static inline void crash_kexec_stop_spus
}
#endif /* CONFIG_SPU_BASE */
+/*
+ * Register a function to be called on shutdown. Only use this if you
+ * can't reset your device in the second kernel.
+ */
+int crash_shutdown_register(crash_shutdown_t handler)
+{
+ unsigned int i, rc;
+
+ spin_lock(&crash_handers_lock);
+ for (i = 0 ; i < CRASH_HANDLER_MAX; i++)
+ if (!crash_shutdown_handles[i]) {
+ /* Insert handle at first empty entry */
+ crash_shutdown_handles[i] = handler;
+ rc = 0;
+ break;
+ }
+
+ if (i == CRASH_HANDLER_MAX) {
+ printk(KERN_ERR "Crash shutdown handles full, "
+ "not registered.\n");
+ rc = 1;
+ }
+
+ spin_unlock(&crash_handers_lock);
+ return rc;
+}
+EXPORT_SYMBOL(crash_shutdown_register);
+
+int crash_shutdown_unregister(crash_shutdown_t handler)
+{
+ unsigned int i, rc;
+
+ spin_lock(&crash_handers_lock);
+ for (i = 0 ; i < CRASH_HANDLER_MAX; i++)
+ if (crash_shutdown_handles[i] == handler)
+ break;
+
+ if (i == CRASH_HANDLER_MAX) {
+ printk(KERN_ERR "Crash shutdown handle not found\n");
+ rc = 1;
+ } else {
+ /* Shift handles down */
+ for (; crash_shutdown_handles[i]; i++)
+ crash_shutdown_handles[i] =
+ crash_shutdown_handles[i+1];
+ rc = 0;
+ }
+
+ spin_unlock(&crash_handers_lock);
+ return rc;
+}
+EXPORT_SYMBOL(crash_shutdown_unregister);
+
+static unsigned long crash_shutdown_buf[SETJMP_BUF_LEN];
+
+static int handle_fault(struct pt_regs *regs)
+{
+ longjmp(crash_shutdown_buf, 1);
+ return 0;
+}
+
void default_machine_crash_shutdown(struct pt_regs *regs)
{
- unsigned int irq;
+ unsigned int i;
+ int (*old_handler)(struct pt_regs *regs);
+
/*
* This function is only called after the system
@@ -301,15 +371,37 @@ void default_machine_crash_shutdown(stru
*/
hard_irq_disable();
- for_each_irq(irq) {
- struct irq_desc *desc = irq_desc + irq;
+ for_each_irq(i) {
+ struct irq_desc *desc = irq_desc + i;
if (desc->status & IRQ_INPROGRESS)
- desc->chip->eoi(irq);
+ desc->chip->eoi(i);
if (!(desc->status & IRQ_DISABLED))
- desc->chip->disable(irq);
+ desc->chip->disable(i);
+ }
+
+ /*
+ * Call registered shutdown routines savely. Swap out
+ * __debugger_fault_handler, and replace on exit.
+ */
+ old_handler = __debugger_fault_handler;
+ __debugger_fault_handler = handle_fault;
+ for (i = 0; crash_shutdown_handles[i]; i++) {
+ if (setjmp(crash_shutdown_buf) == 0) {
+ /*
+ * Insert syncs and delay to ensure
+ * instructions in the dangerous region don't
+ * leak away from this protected region.
+ */
+ asm volatile("sync; isync");
+ /* dangerous region */
+ crash_shutdown_handles[i]();
+ asm volatile("sync; isync");
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
+ }
}
+ __debugger_fault_handler = old_handler;
/*
* Make a note of crashing cpu. Will be used in machine_kexec
Index: clone3/include/asm-powerpc/kexec.h
===================================================================
--- clone3.orig/include/asm-powerpc/kexec.h
+++ clone3/include/asm-powerpc/kexec.h
@@ -123,6 +123,9 @@ struct pt_regs;
extern void default_machine_kexec(struct kimage *image);
extern int default_machine_kexec_prepare(struct kimage *image);
extern void default_machine_crash_shutdown(struct pt_regs *regs);
+typedef void (*crash_shutdown_t)(void);
+extern int crash_shutdown_register(crash_shutdown_t handler);
+extern int crash_shutdown_unregister(crash_shutdown_t handler);
extern void machine_kexec_simple(struct kimage *image);
extern void crash_kexec_secondary(struct pt_regs *regs);
^ permalink raw reply
* [PATCH 1/2] Make setjmp/longjmp code generic
From: Michael Neuling @ 2007-12-13 3:16 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, Michael Neuling, RAISCH, THEMANN
In-Reply-To: <1197515777.834799.307108384755.qpush@coopers>
This makes the setjmp/longjmp code used by xmon, generically available
to other code. It also removes the requirement for debugger hooks to
be only called on 0x300 (data storage) exception and adds some
documentation.
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
arch/powerpc/kernel/misc.S | 128 ++++++++++++++++++++++++++++++++++++++++
arch/powerpc/mm/fault.c | 6 -
arch/powerpc/xmon/Makefile | 2
arch/powerpc/xmon/setjmp.S | 135 -------------------------------------------
arch/powerpc/xmon/xmon.c | 38 ++++--------
include/asm-powerpc/setjmp.h | 19 ++++++
6 files changed, 164 insertions(+), 164 deletions(-)
Index: clone3/arch/powerpc/kernel/misc.S
===================================================================
--- clone3.orig/arch/powerpc/kernel/misc.S
+++ clone3/arch/powerpc/kernel/misc.S
@@ -8,6 +8,8 @@
* Adapted for iSeries by Mike Corrigan (mikejc@us.ibm.com)
* PPC64 updates by Dave Engebretsen (engebret@us.ibm.com)
*
+ * setjmp/longjmp and xmon_save_regs code by Paul Mackerras.
+ *
* 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
@@ -15,6 +17,8 @@
*/
#include <asm/ppc_asm.h>
#include <asm/unistd.h>
+#include <asm/asm-compat.h>
+#include <asm/asm-offsets.h>
.text
@@ -51,3 +55,127 @@ _GLOBAL(kernel_execve)
bnslr
neg r3,r3
blr
+
+_GLOBAL(setjmp)
+ mflr r0
+ PPC_STL r0,0(r3)
+ PPC_STL r1,SZL(r3)
+ PPC_STL r2,2*SZL(r3)
+ mfcr r0
+ PPC_STL r0,3*SZL(r3)
+ PPC_STL r13,4*SZL(r3)
+ PPC_STL r14,5*SZL(r3)
+ PPC_STL r15,6*SZL(r3)
+ PPC_STL r16,7*SZL(r3)
+ PPC_STL r17,8*SZL(r3)
+ PPC_STL r18,9*SZL(r3)
+ PPC_STL r19,10*SZL(r3)
+ PPC_STL r20,11*SZL(r3)
+ PPC_STL r21,12*SZL(r3)
+ PPC_STL r22,13*SZL(r3)
+ PPC_STL r23,14*SZL(r3)
+ PPC_STL r24,15*SZL(r3)
+ PPC_STL r25,16*SZL(r3)
+ PPC_STL r26,17*SZL(r3)
+ PPC_STL r27,18*SZL(r3)
+ PPC_STL r28,19*SZL(r3)
+ PPC_STL r29,20*SZL(r3)
+ PPC_STL r30,21*SZL(r3)
+ PPC_STL r31,22*SZL(r3)
+ li r3,0
+ blr
+
+_GLOBAL(longjmp)
+ PPC_LCMPI r4,0
+ bne 1f
+ li r4,1
+1: PPC_LL r13,4*SZL(r3)
+ PPC_LL r14,5*SZL(r3)
+ PPC_LL r15,6*SZL(r3)
+ PPC_LL r16,7*SZL(r3)
+ PPC_LL r17,8*SZL(r3)
+ PPC_LL r18,9*SZL(r3)
+ PPC_LL r19,10*SZL(r3)
+ PPC_LL r20,11*SZL(r3)
+ PPC_LL r21,12*SZL(r3)
+ PPC_LL r22,13*SZL(r3)
+ PPC_LL r23,14*SZL(r3)
+ PPC_LL r24,15*SZL(r3)
+ PPC_LL r25,16*SZL(r3)
+ PPC_LL r26,17*SZL(r3)
+ PPC_LL r27,18*SZL(r3)
+ PPC_LL r28,19*SZL(r3)
+ PPC_LL r29,20*SZL(r3)
+ PPC_LL r30,21*SZL(r3)
+ PPC_LL r31,22*SZL(r3)
+ PPC_LL r0,3*SZL(r3)
+ mtcrf 0x38,r0
+ PPC_LL r0,0(r3)
+ PPC_LL r1,SZL(r3)
+ PPC_LL r2,2*SZL(r3)
+ mtlr r0
+ mr r3,r4
+ blr
+
+#ifdef CONFIG_XMON
+/*
+ * Grab the register values as they are now.
+ * This won't do a particularily good job because we really
+ * want our caller's caller's registers, and our caller has
+ * already executed its prologue.
+ * ToDo: We could reach back into the caller's save area to do
+ * a better job of representing the caller's state (note that
+ * that will be different for 32-bit and 64-bit, because of the
+ * different ABIs, though).
+ */
+_GLOBAL(xmon_save_regs)
+ PPC_STL r0,0*SZL(r3)
+ PPC_STL r2,2*SZL(r3)
+ PPC_STL r3,3*SZL(r3)
+ PPC_STL r4,4*SZL(r3)
+ PPC_STL r5,5*SZL(r3)
+ PPC_STL r6,6*SZL(r3)
+ PPC_STL r7,7*SZL(r3)
+ PPC_STL r8,8*SZL(r3)
+ PPC_STL r9,9*SZL(r3)
+ PPC_STL r10,10*SZL(r3)
+ PPC_STL r11,11*SZL(r3)
+ PPC_STL r12,12*SZL(r3)
+ PPC_STL r13,13*SZL(r3)
+ PPC_STL r14,14*SZL(r3)
+ PPC_STL r15,15*SZL(r3)
+ PPC_STL r16,16*SZL(r3)
+ PPC_STL r17,17*SZL(r3)
+ PPC_STL r18,18*SZL(r3)
+ PPC_STL r19,19*SZL(r3)
+ PPC_STL r20,20*SZL(r3)
+ PPC_STL r21,21*SZL(r3)
+ PPC_STL r22,22*SZL(r3)
+ PPC_STL r23,23*SZL(r3)
+ PPC_STL r24,24*SZL(r3)
+ PPC_STL r25,25*SZL(r3)
+ PPC_STL r26,26*SZL(r3)
+ PPC_STL r27,27*SZL(r3)
+ PPC_STL r28,28*SZL(r3)
+ PPC_STL r29,29*SZL(r3)
+ PPC_STL r30,30*SZL(r3)
+ PPC_STL r31,31*SZL(r3)
+ /* go up one stack frame for SP */
+ PPC_LL r4,0(r1)
+ PPC_STL r4,1*SZL(r3)
+ /* get caller's LR */
+ PPC_LL r0,LRSAVE(r4)
+ PPC_STL r0,_NIP-STACK_FRAME_OVERHEAD(r3)
+ PPC_STL r0,_LINK-STACK_FRAME_OVERHEAD(r3)
+ mfmsr r0
+ PPC_STL r0,_MSR-STACK_FRAME_OVERHEAD(r3)
+ mfctr r0
+ PPC_STL r0,_CTR-STACK_FRAME_OVERHEAD(r3)
+ mfxer r0
+ PPC_STL r0,_XER-STACK_FRAME_OVERHEAD(r3)
+ mfcr r0
+ PPC_STL r0,_CCR-STACK_FRAME_OVERHEAD(r3)
+ li r0,0
+ PPC_STL r0,_TRAP-STACK_FRAME_OVERHEAD(r3)
+ blr
+#endif
Index: clone3/arch/powerpc/mm/fault.c
===================================================================
--- clone3.orig/arch/powerpc/mm/fault.c
+++ clone3/arch/powerpc/mm/fault.c
@@ -167,10 +167,8 @@ int __kprobes do_page_fault(struct pt_re
if (notify_page_fault(regs))
return 0;
- if (trap == 0x300) {
- if (debugger_fault_handler(regs))
- return 0;
- }
+ if (unlikely(debugger_fault_handler(regs)))
+ return 0;
/* On a kernel SLB miss we can only check for a valid exception entry */
if (!user_mode(regs) && (address >= TASK_SIZE))
Index: clone3/arch/powerpc/xmon/Makefile
===================================================================
--- clone3.orig/arch/powerpc/xmon/Makefile
+++ clone3/arch/powerpc/xmon/Makefile
@@ -4,7 +4,7 @@ ifdef CONFIG_PPC64
EXTRA_CFLAGS += -mno-minimal-toc
endif
-obj-y += xmon.o setjmp.o start.o nonstdio.o
+obj-y += xmon.o start.o nonstdio.o
ifdef CONFIG_XMON_DISASSEMBLY
obj-y += ppc-dis.o ppc-opc.o
Index: clone3/arch/powerpc/xmon/setjmp.S
===================================================================
--- clone3.orig/arch/powerpc/xmon/setjmp.S
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 1996 Paul Mackerras.
- *
- * 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.
- *
- * NOTE: assert(sizeof(buf) > 23 * sizeof(long))
- */
-#include <asm/processor.h>
-#include <asm/ppc_asm.h>
-#include <asm/asm-offsets.h>
-
-_GLOBAL(xmon_setjmp)
- mflr r0
- PPC_STL r0,0(r3)
- PPC_STL r1,SZL(r3)
- PPC_STL r2,2*SZL(r3)
- mfcr r0
- PPC_STL r0,3*SZL(r3)
- PPC_STL r13,4*SZL(r3)
- PPC_STL r14,5*SZL(r3)
- PPC_STL r15,6*SZL(r3)
- PPC_STL r16,7*SZL(r3)
- PPC_STL r17,8*SZL(r3)
- PPC_STL r18,9*SZL(r3)
- PPC_STL r19,10*SZL(r3)
- PPC_STL r20,11*SZL(r3)
- PPC_STL r21,12*SZL(r3)
- PPC_STL r22,13*SZL(r3)
- PPC_STL r23,14*SZL(r3)
- PPC_STL r24,15*SZL(r3)
- PPC_STL r25,16*SZL(r3)
- PPC_STL r26,17*SZL(r3)
- PPC_STL r27,18*SZL(r3)
- PPC_STL r28,19*SZL(r3)
- PPC_STL r29,20*SZL(r3)
- PPC_STL r30,21*SZL(r3)
- PPC_STL r31,22*SZL(r3)
- li r3,0
- blr
-
-_GLOBAL(xmon_longjmp)
- PPC_LCMPI r4,0
- bne 1f
- li r4,1
-1: PPC_LL r13,4*SZL(r3)
- PPC_LL r14,5*SZL(r3)
- PPC_LL r15,6*SZL(r3)
- PPC_LL r16,7*SZL(r3)
- PPC_LL r17,8*SZL(r3)
- PPC_LL r18,9*SZL(r3)
- PPC_LL r19,10*SZL(r3)
- PPC_LL r20,11*SZL(r3)
- PPC_LL r21,12*SZL(r3)
- PPC_LL r22,13*SZL(r3)
- PPC_LL r23,14*SZL(r3)
- PPC_LL r24,15*SZL(r3)
- PPC_LL r25,16*SZL(r3)
- PPC_LL r26,17*SZL(r3)
- PPC_LL r27,18*SZL(r3)
- PPC_LL r28,19*SZL(r3)
- PPC_LL r29,20*SZL(r3)
- PPC_LL r30,21*SZL(r3)
- PPC_LL r31,22*SZL(r3)
- PPC_LL r0,3*SZL(r3)
- mtcrf 0x38,r0
- PPC_LL r0,0(r3)
- PPC_LL r1,SZL(r3)
- PPC_LL r2,2*SZL(r3)
- mtlr r0
- mr r3,r4
- blr
-
-/*
- * Grab the register values as they are now.
- * This won't do a particularily good job because we really
- * want our caller's caller's registers, and our caller has
- * already executed its prologue.
- * ToDo: We could reach back into the caller's save area to do
- * a better job of representing the caller's state (note that
- * that will be different for 32-bit and 64-bit, because of the
- * different ABIs, though).
- */
-_GLOBAL(xmon_save_regs)
- PPC_STL r0,0*SZL(r3)
- PPC_STL r2,2*SZL(r3)
- PPC_STL r3,3*SZL(r3)
- PPC_STL r4,4*SZL(r3)
- PPC_STL r5,5*SZL(r3)
- PPC_STL r6,6*SZL(r3)
- PPC_STL r7,7*SZL(r3)
- PPC_STL r8,8*SZL(r3)
- PPC_STL r9,9*SZL(r3)
- PPC_STL r10,10*SZL(r3)
- PPC_STL r11,11*SZL(r3)
- PPC_STL r12,12*SZL(r3)
- PPC_STL r13,13*SZL(r3)
- PPC_STL r14,14*SZL(r3)
- PPC_STL r15,15*SZL(r3)
- PPC_STL r16,16*SZL(r3)
- PPC_STL r17,17*SZL(r3)
- PPC_STL r18,18*SZL(r3)
- PPC_STL r19,19*SZL(r3)
- PPC_STL r20,20*SZL(r3)
- PPC_STL r21,21*SZL(r3)
- PPC_STL r22,22*SZL(r3)
- PPC_STL r23,23*SZL(r3)
- PPC_STL r24,24*SZL(r3)
- PPC_STL r25,25*SZL(r3)
- PPC_STL r26,26*SZL(r3)
- PPC_STL r27,27*SZL(r3)
- PPC_STL r28,28*SZL(r3)
- PPC_STL r29,29*SZL(r3)
- PPC_STL r30,30*SZL(r3)
- PPC_STL r31,31*SZL(r3)
- /* go up one stack frame for SP */
- PPC_LL r4,0(r1)
- PPC_STL r4,1*SZL(r3)
- /* get caller's LR */
- PPC_LL r0,LRSAVE(r4)
- PPC_STL r0,_NIP-STACK_FRAME_OVERHEAD(r3)
- PPC_STL r0,_LINK-STACK_FRAME_OVERHEAD(r3)
- mfmsr r0
- PPC_STL r0,_MSR-STACK_FRAME_OVERHEAD(r3)
- mfctr r0
- PPC_STL r0,_CTR-STACK_FRAME_OVERHEAD(r3)
- mfxer r0
- PPC_STL r0,_XER-STACK_FRAME_OVERHEAD(r3)
- mfcr r0
- PPC_STL r0,_CCR-STACK_FRAME_OVERHEAD(r3)
- li r0,0
- PPC_STL r0,_TRAP-STACK_FRAME_OVERHEAD(r3)
- blr
Index: clone3/arch/powerpc/xmon/xmon.c
===================================================================
--- clone3.orig/arch/powerpc/xmon/xmon.c
+++ clone3/arch/powerpc/xmon/xmon.c
@@ -40,6 +40,7 @@
#include <asm/spu.h>
#include <asm/spu_priv1.h>
#include <asm/firmware.h>
+#include <asm/setjmp.h>
#ifdef CONFIG_PPC64
#include <asm/hvcall.h>
@@ -71,12 +72,9 @@ static unsigned long ncsum = 4096;
static int termch;
static char tmpstr[128];
-#define JMP_BUF_LEN 23
-static long bus_error_jmp[JMP_BUF_LEN];
+static long bus_error_jmp[SETJMP_BUF_LEN];
static int catch_memory_errors;
static long *xmon_fault_jmp[NR_CPUS];
-#define setjmp xmon_setjmp
-#define longjmp xmon_longjmp
/* Breakpoint stuff */
struct bpt {
@@ -162,8 +160,6 @@ int xmon_no_auto_backtrace;
extern void xmon_enter(void);
extern void xmon_leave(void);
-extern long setjmp(long *);
-extern void longjmp(long *, long);
extern void xmon_save_regs(struct pt_regs *);
#ifdef CONFIG_PPC64
@@ -338,7 +334,7 @@ static int xmon_core(struct pt_regs *reg
{
int cmd = 0;
struct bpt *bp;
- long recurse_jmp[JMP_BUF_LEN];
+ long recurse_jmp[SETJMP_BUF_LEN];
unsigned long offset;
unsigned long flags;
#ifdef CONFIG_SMP
@@ -1428,7 +1424,7 @@ void prregs(struct pt_regs *fp)
sync();
regs = *(struct pt_regs *)base;
sync();
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
} else {
catch_memory_errors = 0;
printf("*** Error reading registers from "REG"\n",
@@ -1497,8 +1493,7 @@ void cacheflush(void)
cinval((void *) adrs);
}
sync();
- /* wait a little while to see if we get a machine check */
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
}
catch_memory_errors = 0;
}
@@ -1533,8 +1528,7 @@ read_spr(int n)
ret = code();
sync();
- /* wait a little while to see if we get a machine check */
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
n = size;
}
@@ -1569,8 +1563,7 @@ write_spr(int n, unsigned long val)
code(val);
sync();
- /* wait a little while to see if we get a machine check */
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
n = size;
}
}
@@ -1676,8 +1669,7 @@ mread(unsigned long adrs, void *buf, int
}
}
sync();
- /* wait a little while to see if we get a machine check */
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
n = size;
}
catch_memory_errors = 0;
@@ -1713,8 +1705,7 @@ mwrite(unsigned long adrs, void *buf, in
}
}
sync();
- /* wait a little while to see if we get a machine check */
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
n = size;
} else {
printf("*** Error writing address %x\n", adrs + n);
@@ -2521,8 +2512,7 @@ static void xmon_print_symbol(unsigned l
name = kallsyms_lookup(address, &size, &offset, &modname,
tmpstr);
sync();
- /* wait a little while to see if we get a machine check */
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
}
catch_memory_errors = 0;
@@ -2777,7 +2767,7 @@ static void stop_spus(void)
spu_mfc_sr1_set(spu, tmp);
sync();
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
spu_info[i].stopped_ok = 1;
@@ -2817,7 +2807,7 @@ static void restart_spus(void)
spu_info[i].saved_spu_runcntl_RW);
sync();
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
printf("Restarted spu %.2d\n", i);
} else {
@@ -2837,7 +2827,7 @@ do { \
printf(" %-*s = "format"\n", DUMP_WIDTH, \
#field, value); \
sync(); \
- __delay(200); \
+ __delay(SETJMP_MACHINE_CHECK_DELAY); \
} else { \
catch_memory_errors = 0; \
printf(" %-*s = *** Error reading field.\n", \
@@ -2899,7 +2889,7 @@ static void dump_spu_ls(unsigned long nu
sync();
ls_addr = (unsigned long)spu_info[num].spu->local_store;
sync();
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
} else {
catch_memory_errors = 0;
printf("*** Error: accessing spu info for spu %d\n", num);
Index: clone3/include/asm-powerpc/setjmp.h
===================================================================
--- /dev/null
+++ clone3/include/asm-powerpc/setjmp.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2007 Michael Neuling
+ *
+ * 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.
+ *
+ */
+#ifndef _ASM_POWERPC_SETJMP_H
+#define _ASM_POWERPC_SETJMP_H
+
+#define SETJMP_BUF_LEN 23
+#define SETJMP_MACHINE_CHECK_DELAY 200
+
+extern long setjmp(long *);
+extern void longjmp(long *, long);
+
+#endif /* _ASM_POWERPC_SETJMP_H */
^ permalink raw reply
* [PATCH 0/2] Add crashdump shutdown hooks
From: Michael Neuling @ 2007-12-13 3:16 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, Michael Neuling, RAISCH, THEMANN
In-Reply-To: <20071212054512.A02B062C153@localhost.localdomain>
The following patches add crashdump shutdown hooks for POWERPC.
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
This is an updated series following comments from the first post.
Adds some documentation, better code flow, fixes 32 bit compiles and
other updates based on feedback
Again these are based on paulus' for 2.6.25 tree.
^ permalink raw reply
* [PATCH] Convert media-bay.c to use the kthread API
From: Paul Mackerras @ 2007-12-13 3:12 UTC (permalink / raw)
To: linuxppc-dev
We aren't supposed to use kernel_thread directly in drivers any more,
and in fact using kthread_run is a bit simpler.
Signed-off-by: Paul Mackerras <paulus@samba.org>
---
diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c
index 48d647a..080844b 100644
--- a/drivers/macintosh/mediabay.c
+++ b/drivers/macintosh/mediabay.c
@@ -20,6 +20,7 @@
#include <linux/stddef.h>
#include <linux/init.h>
#include <linux/ide.h>
+#include <linux/kthread.h>
#include <asm/prom.h>
#include <asm/pgtable.h>
#include <asm/io.h>
@@ -35,7 +36,6 @@
#define MB_DEBUG
-#define MB_IGNORE_SIGNALS
#ifdef MB_DEBUG
#define MBDBG(fmt, arg...) printk(KERN_INFO fmt , ## arg)
@@ -622,12 +622,7 @@ static int media_bay_task(void *x)
{
int i;
- strcpy(current->comm, "media-bay");
-#ifdef MB_IGNORE_SIGNALS
- sigfillset(¤t->blocked);
-#endif
-
- for (;;) {
+ while (!kthread_should_stop()) {
for (i = 0; i < media_bay_count; ++i) {
down(&media_bays[i].lock);
if (!media_bays[i].sleeping)
@@ -636,8 +631,6 @@ static int media_bay_task(void *x)
}
msleep_interruptible(MB_POLL_DELAY);
- if (signal_pending(current))
- return 0;
}
}
@@ -699,7 +692,7 @@ static int __devinit media_bay_attach(struct macio_dev *mdev, const struct of_de
/* Startup kernel thread */
if (i == 0)
- kernel_thread(media_bay_task, NULL, CLONE_KERNEL);
+ kthread_run(media_bay_task, NULL, "media-bay");
return 0;
^ permalink raw reply related
* Re: [PATCH RFC 0/7] "NAND on UPM" and related patches
From: Chris Fester @ 2007-12-13 3:01 UTC (permalink / raw)
To: avorontsov; +Cc: linuxppc-dev
In-Reply-To: <20071210204705.GA31263@localhost.localdomain>
On Mon, 2007-12-10 at 23:47 +0300, Anton Vorontsov wrote:
> Hi all,
>
> Here are patches to support NAND on UPM. That driver is generic for
> all processors with FSL UPMs. And because of that, few more patches are
> needed -- GPIO API and generic FSL UPM functions.
> I would appreciate any comments and suggestions, thanks!
Hi Anton,
Apologies for not getting back sooner to comment...
We've been using a home-brewed UPM driver for our NAND for a while now.
There's several issues we've hit that I figured I would share. The
issues involve deficiencies of both the UPM and the NAND part itself.
We modeled our driver loosely after the suggestions in this white paper:
http://www.freescale.com/files/32bit/doc/white_paper/NANDFLASHWP.pdf?fpsp=1&WT_TYPE=WhitePapers&WT_VENDOR=FREESCALE&WT_FILE_FORMAT=pdf&WT_ASSET=Documentation
We also connected the NAND according to the suggestions in the above
document.
Something that you should be made aware of right away about the UPM -
you do not have control of the logic lines all of the time. You only
can control them during a transaction (in our case, a byte transaction).
In other words, the time that is between reading/writing bytes, or
putting the address on the bus, or asserting commands you are not able
to hold the lines to a certain state. Most of the control lines coming
from the UPM default to a logic 1 when unused (I believe only one
defaults to a logic 0).
The first issue is timings between versions of processors. We've got
one board using an MPC8349 running a 1Gb ST micro part (NAND01G-B).
Another board is an MPC8347 using the same 1Gb ST micro part. After
much time analyzing logic analyzer captures we found that write pulses
with the 8349 had to be shifted to the left a half clock in order to
properly latch the data on the bus. This was unexpected given the two
boards are very similar and the processors are in the same family. I
suppose the fix was easy enough, we just had to make a new version of
the microcode. What's interesting is that Freescale said that there's
nothing different between the two processors' UPMs. Yet there is a
distinct difference between local bus behavior on the 2 cpus, our LA
captures prove it.
The second issue was with interrupts during reads. We noticed that some
of our boards experienced ECC errors while reading the NAND. Logic
analyzer captures and debugging revealed that when an interrupt happened
while the driver's read code was executing, the UPM went into an idle
state, and the chip select of the part went high. This may not be a
problem for other NAND parts, but for our ST Micro parts, the spec says
that if CS is held high for more than 100us, the part will exit page
read mode. The default state of the UPM pins are high, so when the UPM
is idle all the signals are at logic 1.
Anyways, when the interrupt had completed, or driver wasn't aware that
an interrupt had occurred, so it continued to do it's read loop. The ST
Micro part was now in an undefined state. The page read appeared to
continue just fine, but we almost always had one or more bits corrupted
for the very first resuming data byte.
The fix that we ultimately did was to move the chip select control from
the UPM to a GPIO from the processor. This forced the chip to never
"sleep" during an interrupt, because we could keep the chip select low
for the entire page read transaction. This brought up other minor
issues. You must make sure that your boot loader (U-Boot in our case)
sets the GPIO data BEFORE it sets the GPIO direction. Otherwise the
NAND will automatically enter a start up read condition that will drive
the local bus, causing anything else on the local bus (such as a NOR
flash) to be useless...
The latest version of the app note online (link above) does not mention
the problem you may experience with interrupts. I requested from our
Freescale support contact that Freescale document this fact and make it
available to others such that they won't bump into the same problems we
did!
The THIRD issue we had (actually, are having) is very related to our
second issue. Our customer now wants a 2Gb NAND on our board. We
swapped the chip out. We included one more address byte transaction
that is needed with the larger part in the driver. And it doesn't work.
The part is considered to be the "bigger brother" to the 1Gb part, but
apparently enough of it's state machine has changed that it doesn't
tolerate the AL and CL lines going high while chip select is low.
Incidentally, when debugging our second issue we were told by ST Micro
support that the only time AL and CL were sampled by the NAND was when
W# and R# were driven low. Had we known that the 2Gb part wouldn't have
worked, we would have done much more major reworking to the NAND
subsystem when we respun our board.
This mail isn't meant to be a rant. Everyone knows that this kind of
low-level hardware/software work is difficult. This mail is meant to
caution you against using the NAND with the UPM. Freescale may say that
it works, and present you a pretty looking white paper, but it's really
kludgy and you are pretty guaranteed to have problems. Please encourage
your board designers to hook the NAND to some sort of CPLD device rather
than the UPM. At least with a CPLD you have some real control over the
state of the control lines.
If you for whatever reason are stuck with the UPM...
1.) Get your hardware people to stick inverters on the AL and CL lines.
Adjust your UPM microcode accordingly.
2.) Put your CS under control of a GPIO pin.
3.) Buy a nice logic analyzer, because you're going to need it!!!
I hope this helps someone out there... I've been spending a lot of time
on-and-off on this. Every time we think we have it right one little
seemingly benign change throws the whole thing out the window...
Okie, happy coding,
Chris Fester
^ permalink raw reply
* RE: Xilinx devicetrees
From: Koss, Mike (Mission Systems) @ 2007-12-13 2:40 UTC (permalink / raw)
To: Stephen Neuendorffer, David H. Lynch Jr., Grant Likely,
linuxppc-embedded
In-Reply-To: <20071125235855.95B9999804D@mail138-cpk.bigfish.com>
[-- Attachment #1: Type: text/plain, Size: 7713 bytes --]
Time for my $.02, since I am heavily weighting my future designs on the
use of the device trees. :) (and b/c I don't check my work e-mail from
home ;P)
________________________________
From: Stephen Neuendorffer [mailto:stephen.neuendorffer@xilinx.com]
Sent: Sunday, November 25, 2007 6:59 PM
To: David H. Lynch Jr.; Grant Likely; linuxppc-embedded
Subject: RE: Xilinx devicetrees
DL> I am not expert on this, but at Pico we already store our boot
monitor in the .bit files in BRAM.
DL> But that is not free. It is one of the reasons we do not use
u-boot. Our boot monitor must fit into 16K of BRAM.
DL> Must be able to perform selftests on critical hardware, support
a flash file system, load bit files from flash to the FGA, load and
exectute elf files, allow a small set of user commands,
DL> and handle hosted vs. standalone operation.
DL> And aparently extract the devicetree from a bit file and pass it
to a linux kernel.
SN> Once you can load a bitstream from flash, loading the device tree
from flash
SN> should be practically free. In any event, why do you do this rather
than just run out of the flash (or a ram copy of the flash?)
This is the approach that I am currently taking with our future design.
In our system, we actually have 2 physical systems running Linux inside
the V4 (that's why there are 2 PowerPCs :) ). My current plan would be
to have the device trees stored in FLASH along w/ a single linux image.
Our bootloader on the board would then copy that information from FLASH
to RAM for both systems. This allows us to have two physically different
systems setup with different hardware, but have one linux image with two
different device trees. With a standard linux kernel weighing it at ~
3-5MB (including initramfs) that's a hefty savings in FLASH for us. Plus
it can considerably lower boot time instead of having to verify multiple
large images.
DL> In static or fairly static hardware, that's fine. Even in somewhat
dynamic hardware with large quantities of startup resources - like a PC.
DL> But in highly dynamic hardware with fairly limited resources it
starts to become an issue.
SN> As Grant says, the dynamic detection doesn't have to be done in the
boot loader, it could be done in the platform code. You can largely
ignore
SN> the device trees, or always boot with a core device tree and figure
it all out later (perhaps using version registers). I anticipate that
SN> the 'standard flow' will have standard platform code for any board
that uses a complete device tree. If you have the need to do something
SN> extraordinary, then you should feel free to hack away... However,
It doesn't seem to me to be really necessary in your case, assuming that
SN> the device tree is packaged (somehow, TBD) along with the bitstream.
I don't know if packaging the device tree with the bitstream is the best
way to go. It's possible that it could lead to headaches for certain
systems that have security restrictions. The same could be said for
using it w/ the SystemACE to load it into RAM after the image. (which is
what I'm currently doing for my 2 linux images in lieu of a true on-chip
bootloader). I am already taking the security concerns into account for
future revisions of the hardware wrt to using a SystemACE, and am
planning on moving the device trees into NV storage like FLASH.
GL> No, unfortunately they don't deal with the problem you're facing
GL> (which I'm facing also). But it will be solved if we figure out a
GL> sane way to bind the device tree up with the FPGA bitstream without
GL> consuming FPGA resources.
DL> Note to Xilinx:
DL> There MUST be some way of binding a device description to a
bit file.
DL> neither building it into the FPGA fabric nor appending it to the
end
DL> of the bit file are perfect solutions,
DL> The former is more powerfull and flexible but wastes precious
DL> resources. The later is more complex and puts more burdens on
DL> software developers, and may be completely unfeasible in some
DL> environments - not mine fortunately.
SN> I don't understand the 'burden on software developers'. The code to
do this will just be standard code. The worst that one can say is:
SN> 1) I need several KB additional non volatile storage. Given the
size of the FPGA bitstream, this can't be a huge constraint.
SN> 2) I can't use compile time optimization based on xparameters as
easily. Anyone want to implement the alternatives mechanism on ppc and
microblaze?
SN> 3) Some additional boot time. However, again, this seems marginal.
I do agree that using more FPGA resources is not a solution to the
problem. I'm already hitting 80% usage on a FX60 and trying to squeeze
more real estate for storage of the device tree seems silly. Especially
since that would require that every image have this extra hardware built
into it just to support booting a Linux kernel. Why should I have to
have different hardware to boot linux, versus non-kernel, xilkernel, or
other (GHS, LynxOS, etc..)?
DL> Regardless, something must be done. An odd collection of
devicetree
DL> files co-mingled with a collection of bit files, is little better
than
DL> xparameter files all over the place.
SN> Certainly.. But in a sense, these are all intermediate files on the
path to the image on the board. That
SN> (and how it is interpreted by the platform code) should be generated
in a consistent fashion by EDK.
SN> See my other email for some of the possibilities. Are there
specific reasons why you think those
SN> proposals are inadequate? Now is the time when we can take
criticism, with the goal towards making
SN> a good end solution.
One solution I've been thinking through (in lieu of direct support from
EDK) is to use a tcl script with xps to traverse the hardware tree and
generate the device tree. It seems like it should be relatively trivial
to obtain the information. It's just going to be a pain to write all the
handlers for each different linux driver: temac, interrupt controller,
DMA controller, etc.
In reality the best way to handle this would be to have EDK generate the
device tree as part of the library/bsp build process. Now, what I'd like
to see with regards to this is the ability to change the handler for the
generating a specific device information. An example could be the temac.
If at some point in the future the temac needs new/more information to
support its configuration/run-time then having to get a patch from
Xilinx for a EDK is way too slow. The developers should be giving the
opportunity to inject a new handler into the various parts of the device
tree generation. That way when the kernel patch is submitted, an EDK
device generator patch will be submitted at the same time to keep
everything in sync.
DL> And once again a plea to ALWAYS make version/capabilities
registers
DL> atleast an optional part of every design.
DL> Embeddeding a device tree into a design might be fairly
expensive. a
DL> pair of read only 32 bit registers is damn near free - basically the
DL> FPGA equivalent of atmost 64 diodes or resistors.
SN> Actually, device trees actually seem to be cheaper (in the whole
system sense) than such registers. Unless there is something I don't
understand?
The issue here is that the hardware changed and the driver doesn't
support it. I think this would be fixed by having information passed to
the driver in the platform_device struct to specify information, since
its not able to be discerned by the physical hardware information:
version registers, etc.
[-- Attachment #2: Type: text/html, Size: 11617 bytes --]
^ permalink raw reply
* RE: initrd - console
From: Siva Prasad @ 2007-12-13 2:06 UTC (permalink / raw)
To: michael; +Cc: linuxppc-dev, linuxppc-embedded
In-Reply-To: <1197336860.7378.29.camel@concordia>
Thanks for the response Michael.
Yes!... I do have /dev/console
I also have the following line in /etc/inittab (::respawn:/sbin/getty -L
ttyS0 115200 VT100)
Still it does not print any thing from the user land. All the kernel
printk's are working fine.
I tried to print the arguments and environment variables for getty and
echo /dev/console. Below is the info.
sys_execve - filename=3D/sbin/getty.
copy_strings: kaddr =3D /sbin/getty.
copy_strings: kaddr =3D USER=3Droot.
copy_strings: kaddr =3D SHELL=3D/bin/sh.
copy_strings: kaddr =3D PATH=3D/usr/bin:/bin:/usr/sbin:/sbin.
copy_strings: kaddr =3D TERM=3Dvt102.
copy_strings: kaddr =3D HOME=3D/.
copy_strings: kaddr =3D VT100.
copy_strings: kaddr =3D 115200.
copy_strings: kaddr =3D ttyS0.
copy_strings: kaddr =3D -L.
copy_strings: kaddr =3D /sbin/getty.
sys_execve - filename=3D/bin/echo.
copy_strings: kaddr =3D /bin/echo.
copy_strings: kaddr =3D GATEWAY0=3D172.27.255.254.
copy_strings: kaddr =3D NETMASK0=3D255.255.0.0.
copy_strings: kaddr =3D PWD=3D/.
copy_strings: kaddr =3D SMBD_ARGS=3D.
copy_strings: kaddr =3D NAMESERVER0=3D172.27.0.1.
copy_strings: kaddr =3D NTP_SERVER=3D.
copy_strings: kaddr =3D SHELL=3D/bin/sh.
copy_strings: kaddr =3D INETD_ARGS=3D.
copy_strings: kaddr =3D BOA_ARGS=3D.
copy_strings: kaddr =3D NMBD_ARGS=3D.
copy_strings: kaddr =3D TMPFS=3Dtmpfs.
copy_strings: kaddr =3D PATH=3D/usr/bin:/bin:/usr/sbin:/sbin.
copy_strings: kaddr =3D READONLY_FS=3D.
copy_strings: kaddr =3D TERM=3Dvt102.
copy_strings: kaddr =3D MODLIST=3D.
copy_strings: kaddr =3D SYSCFG_IFACE0=3Dy.
copy_strings: kaddr =3D IPADDR0=3D172.27.180.41.
copy_strings: kaddr =3D DEPLOYMENT_STYLE=3DRAMDISK.
copy_strings: kaddr =3D SYSCFG_DHCPC_CMD=3Dudhcpc -b -i .
copy_strings: kaddr =3D DHCP_ARG=3D.
copy_strings: kaddr =3D RAMDIRS=3D.
copy_strings: kaddr =3D BROADCAST0=3D172.27.255.255.
copy_strings: kaddr =3D HOME=3D/.
copy_strings: kaddr =3D HOSTNAME=3Dmpc8641hpcn.
copy_strings: kaddr =3D USER=3Droot.
copy_strings: kaddr =3D INTERFACE0=3Deth0.
copy_strings: kaddr =3D /dev/console.
copy_strings: kaddr =3D echo.
Thanks
Siva
-----Original Message-----
From: Michael Ellerman [mailto:michael@ellerman.id.au]=20
Sent: Monday, December 10, 2007 5:34 PM
To: Siva Prasad
Cc: linuxppc-dev@ozlabs.org; linuxppc-embedded@ozlabs.org
Subject: Re: initrd - console
On Mon, 2007-12-10 at 17:26 -0800, Siva Prasad wrote:
> Hi,
>=20
> I am trying to boot kernel with initrd. However, it hangs in
> run_init_process("/sbin/init"). I went into the system calls to see
what
> it is doing.=20
>=20
> As part of debugging, I ended up adding a printk statement in
> arch/powerpc/kernel/process.c:sys_execve() routine. Noticed that all
the
> calls are coming here, however nothing is printed on the screen. I
think
> initrd is executing fine (unless one of you says otherwise). See the
> capture below for boot log.
>=20
> Question 1: how come nothing is printed from ramdisk (userland
programs)
> to the serial console, while all the kernel printk's are working
> perfectly?
Do you have a /dev/console etc. in your initrd?
> Question 2: How important is to have interrupts working for just
> printing. I know that interrupts are must to enter input.
Depends on what your console is, but if it's something simple then you
should be able to write to it without taking interrupts.
cheers
--=20
Michael Ellerman
OzLabs, IBM Australia Development Lab
wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)
We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person
^ permalink raw reply
* Re: [PATCH 1/3] ps3: vuart: fix error path locking
From: Geoff Levand @ 2007-12-13 2:00 UTC (permalink / raw)
To: akpm
Cc: Daniel Walker, matthias.kaehlcke, linux-kernel, linux,
linuxppc-dev, mingo, kjwinchester
In-Reply-To: <20071213003028.676998182@mvista.com>
> This stray down would cause a permanent sleep which doesn't seem correct.
> The other uses of this semaphore appear fairly mutex like it's even initialized
> with init_MUTEX() .. So here a patch for removing this one down().
>
> Signed-off-by: Daniel Walker <dwalker@mvista.com>
>
> ---
> drivers/ps3/ps3-vuart.c | 1 -
> 1 file changed, 1 deletion(-)
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
Looks, good.
Andrew, Please apply.
-Geoff
^ permalink raw reply
* Re: [PATCH/RFC] CPM1: implement GPIO API
From: Anton Vorontsov @ 2007-12-13 0:53 UTC (permalink / raw)
To: Arnd Bergmann; +Cc: linuxppc-dev
In-Reply-To: <200712122316.34354.arnd@arndb.de>
On Wed, Dec 12, 2007 at 11:16:33PM +0100, Arnd Bergmann wrote:
> On Wednesday 12 December 2007, Jochen Friedrich wrote:
>
> > +static spinlock_t *cpm1_port_locks;
> > +static int cpm1_num_ports;
>
> Having an array of spinlocks is rather unusual and normally not necessary.
> Did you measure a significant performance impact by using a global lock
> for all ports?
> If not, I would recommend simplifying this.
I disagree. Why should we force bank A to stomp on bank B, if we can
prevent this in few lines of trivial code? It doesn't need any measuring
or simplifying IMO, what's so complexing in array of spinlocks guarding
array of banks?
But, you can repeat that you really want to get rid of this array --
and I'll silently remove it. Not because I gave up, but mostly because
with gpiolib we'll able to embed spinlock into per-bank gpio_chip
structure, thus eventually they will come back. :-))
> > +EXPORT_SYMBOL_GPL(gpio_request);
> > +EXPORT_SYMBOL_GPL(gpio_direction_input);
> > +EXPORT_SYMBOL_GPL(gpio_direction_output);
> > +EXPORT_SYMBOL_GPL(gpio_get_value);
> > +EXPORT_SYMBOL_GPL(gpio_set_value);
>
> All these function names are rather generic identifiers, but you export them
> from a platform specific file. I'd say they should either have a more specific
> name space (e.g. cpm1_gpio_request), or should be implemented in a more
> generic way.
No. This is how gpio api is working currently. With gpiolib[1], most of
these functions will be controller-specific. IIRC, gpiolib is still in
early development stage, so, for now, we have to limit us to one gpio
chip controller.
This works great for us: CPM, CPM2 and QE shouldn't appear on the single
crystal.
I'm not sure if gpiolib will hit 2.6.25, really. Maybe not. So I'd rather
stick with limited gpio api, and later convert it to gpiolib -- it will be
really trivial. Just rename functions and wrap them around gpio_chip
structure.
The bright side of smooth transition is that API itself isn't changing,
GPIO API/GPIOLIB API is fully interchangeable, their differences are
in implementation details.
[1] http://www.kernel.org/pub/linux/kernel/people/akpm/patches/2.6/2.6.24-rc4/2.6.24-rc4-mm1/broken-out/generic-gpio-gpio_chip-support.patch
Thanks,
--
Anton Vorontsov
email: cbou@mail.ru
backup email: ya-cbou@yandex.ru
irc://irc.freenode.net/bd2
^ permalink raw reply
* Re: [PATCH 2/3] mpc82xx: Embedded Planet EP8248E support
From: Stephen Rothwell @ 2007-12-13 0:55 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev
In-Reply-To: <47606538.2090605@freescale.com>
[-- Attachment #1: Type: text/plain, Size: 713 bytes --]
On Wed, 12 Dec 2007 16:48:24 -0600 Scott Wood <scottwood@freescale.com> wrote:
>
> Stephen Rothwell wrote:
> >> + ep8248e_bcsr = of_iomap(ep8248e_bcsr_node, 0);
> >
> > of_node_put(ep8248e_bcsr_node;
>
> No, because we hold on to the node for later use in ep8248e_mdio_probe().
Sorry, you are right, I didn't notice that it was global ...
> BTW, is there any actual node removal done that justifies dealing with
> refcounts everywhere?
In the hotplug code. So I guess it is not very relevant to you, but it
is a pain to retrofit this stuff if it does become important more widely.
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: [PATCH 2/2] kdump shutdown hook support
From: Michael Neuling @ 2007-12-13 0:53 UTC (permalink / raw)
To: Olof Johansson; +Cc: linuxppc-dev, RAISCH, Paul Mackerras, THEMANN
In-Reply-To: <20071212070150.GC786@lixom.net>
>
> > + if (setjmp(crash_shutdown_buf) == 0) {
> > + asm volatile("sync; isync");
> > + crash_shutdown_handles[i]();
> > + asm volatile("sync; isync");
> > + __delay(200);
>
> This looks a bit random. Why the handcoded barriers, and why the delay?
> I don't see a need for the barriers at all here?
I was following the bouncing ball here from the xmon code. We don't
want the hardware executing any of potentially dangerous hooks before
we've setup the setjmp save buffer. Similar, any code past the
dangerous hooks shouldn't be executed before we take a machine check.
It's definitely not a fast path so.... :-)
> At least comment why the delay is needed (and why just 200 is
> sufficient).
xmon.c says:
/* wait a little while to see if we get a machine check */
I'll update the "200" with a #define SETJMP_MACHINE_CHECK_DELAY and push
the same change into the xmon code. This delay in the machine check is
apparently required on 601 machines.
All you other comments I agree with.
Mikey
^ permalink raw reply
* [PATCH 1/3] ps3: vuart: fix error path locking
From: Daniel Walker @ 2007-12-12 8:00 UTC (permalink / raw)
To: akpm
Cc: matthias.kaehlcke, linux-kernel, linux, linuxppc-dev, mingo,
kjwinchester
This stray down would cause a permanent sleep which doesn't seem correct.
The other uses of this semaphore appear fairly mutex like it's even initialized
with init_MUTEX() .. So here a patch for removing this one down().
Signed-off-by: Daniel Walker <dwalker@mvista.com>
---
drivers/ps3/ps3-vuart.c | 1 -
1 file changed, 1 deletion(-)
Index: linux-2.6.23/drivers/ps3/ps3-vuart.c
===================================================================
--- linux-2.6.23.orig/drivers/ps3/ps3-vuart.c
+++ linux-2.6.23/drivers/ps3/ps3-vuart.c
@@ -1072,7 +1072,6 @@ static int ps3_vuart_probe(struct ps3_sy
if (result) {
dev_dbg(&dev->core, "%s:%d: drv->probe failed\n",
__func__, __LINE__);
- down(&vuart_bus_priv.probe_mutex);
goto fail_probe;
}
--
^ permalink raw reply
* Re: [PATCH 6/8] mpc83xx: timer driver for PM wakeup
From: Stephen Rothwell @ 2007-12-13 0:14 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev, paulus
In-Reply-To: <20071212173604.GE5596@loki.buserror.net>
[-- Attachment #1: Type: text/plain, Size: 487 bytes --]
Hi Scott,
On Wed, 12 Dec 2007 11:36:04 -0600 Scott Wood <scottwood@freescale.com> wrote:
>
> +static int __devinit gtm_probe(struct of_device *dev,
> + const struct of_device_id *match)
> +{
.
.
.
> +out:
Just for consistency, you probably want
dev_set_drvdata(&dev->dev, NULL);
here
> + kfree(priv);
> + return ret;
> +}
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: [PATCH 2/2] kdump shutdown hook support
From: Michael Neuling @ 2007-12-13 0:04 UTC (permalink / raw)
To: michael; +Cc: linuxppc-dev, RAISCH, Paul Mackerras, THEMANN
In-Reply-To: <1197500839.7695.19.camel@concordia>
In message <1197500839.7695.19.camel@concordia> you wrote:
>
> --=-Kza0KCx0MG8nsjfq7kOz
> Content-Type: text/plain
> Content-Transfer-Encoding: quoted-printable
>
> On Wed, 2007-12-12 at 16:45 +1100, Michael Neuling wrote:
> > This adds hooks into the default_machine_crash_shutdown so drivers can
> > register a function to be run in the first kernel before we hand off
> > to the second kernel. This should only be used in exceptional
> > circumstances, like where the device can't be reset in the second
> > kernel alone (as is the case with eHEA). To emphasize this, the
> > number of handles allowed to be registered is currently #def to 1.
> >=20
> > This uses the setjmp/longjmp code to call out to the registered hooks,
> > so any bogus exceptions we encounter will hopefully be recoverable. =20
> >=20
> > I've tested with bogus data and instruction exceptions.
> >=20
> > Signed-off-by: Michael Neuling <mikey@neuling.org>
> > ---
> >=20
> > arch/powerpc/kernel/crash.c | 90 +++++++++++++++++++++++++++++++++++++=
> ++++---
> > include/asm-powerpc/kexec.h | 3 +
> > 2 files changed, 88 insertions(+), 5 deletions(-)
> >=20
> > Index: linux-2.6-ozlabs/arch/powerpc/kernel/crash.c
> > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> > --- linux-2.6-ozlabs.orig/arch/powerpc/kernel/crash.c
> > +++ linux-2.6-ozlabs/arch/powerpc/kernel/crash.c
> > @@ -32,6 +32,8 @@
> > #include <asm/lmb.h>
> > #include <asm/firmware.h>
> > #include <asm/smp.h>
> > +#include <asm/system.h>
> > +#include <asm/setjmp.h>
> > =20
> > #ifdef DEBUG
> > #include <asm/udbg.h>
> > @@ -45,6 +47,11 @@ int crashing_cpu =3D -1;
> > static cpumask_t cpus_in_crash =3D CPU_MASK_NONE;
> > cpumask_t cpus_in_sr =3D CPU_MASK_NONE;
> > =20
> > +#define CRASH_SHUTDOWN_HANDLES_NUM 1
>
> CRASH_HANDLER_MAX ?
yep, MAX is probably a more representative name
>
> > +/* NULL terminated list of shutdown handles */
> > +static crash_shutdown_t crash_shutdown_handles[CRASH_SHUTDOWN_HANDLES_NU=
> M+1];
> > +static DEFINE_SPINLOCK(crash_handles_lock);
> > +
> > #ifdef CONFIG_SMP
> > static atomic_t enter_on_soft_reset =3D ATOMIC_INIT(0);
> > =20
> > @@ -285,9 +292,69 @@ static inline void crash_kexec_stop_spus
> > }
> > #endif /* CONFIG_SPU_BASE */
> > =20
> > +/*=20
> > + * Register a function to be called on shutdown. Only use this if you
> > + * can't reset your device in the second kernel.
> > + */
> > +int crash_shutdown_register(crash_shutdown_t handler)
> > +{
> > + unsigned int i, rc;
> > +
> > + spin_lock(&crash_handles_lock);
>
> > + for(i =3D 0 ; i <=3D CRASH_SHUTDOWN_HANDLES_NUM; i++) {
> > + if (!crash_shutdown_handles[i]) {
> > + /* Insert handle at end */
> > + crash_shutdown_handles[i] =3D handler;
> > + rc =3D 0;
> > + break;
> > + }
> > + }
> >=20
> > + if (i =3D=3D CRASH_SHUTDOWN_HANDLES_NUM){
> > + printk(KERN_ERR "Crash shutdown handles full, "
> > + "not registered.\n");
> > + rc =3D 1;
> > + }
> > +
> > + spin_unlock(&crash_handles_lock);
>
> Perhaps?
Yep, looks nicer. I'll fix the one below too.
>
> > + return rc;
> > +}
> > +EXPORT_SYMBOL(crash_shutdown_register);
> > +
> > +int crash_shutdown_unregister(crash_shutdown_t handler)
> > +{
> > + unsigned int i;
> > +
> > + spin_lock(&crash_handles_lock);
> > + for(i =3D 0 ; i <=3D CRASH_SHUTDOWN_HANDLES_NUM; i++)
> > + if (crash_shutdown_handles[i] =3D=3D handler)
> > + break;
> > +
> > + if (i =3D=3D CRASH_SHUTDOWN_HANDLES_NUM){
> > + printk(KERN_ERR "Crash shutdown handle not found\n");
> > + spin_unlock(&crash_handles_lock);
> > + return 1;
> > + }
> > +
> > + /* Shift handles down */
> > + while(crash_shutdown_handles[i]) {
> > + crash_shutdown_handles[i] =3D crash_shutdown_handles[i+1];
> > + i++;
> > + }
> > + spin_unlock(&crash_handles_lock);
> > + return 0;
> > +}
> > +EXPORT_SYMBOL(crash_shutdown_unregister);
> > +
> > +static long crash_shutdown_buf[SETJMP_BUF_LEN];
>
> unsigned long?
yep
>
> > +
> > +static int handle_fault(struct pt_regs *regs)
> > +{
> > + longjmp(crash_shutdown_buf, 1);
> > + return 0;
> > +}
> > +
> > void default_machine_crash_shutdown(struct pt_regs *regs)
> > {
> > - unsigned int irq;
> > + unsigned int i;
> > =20
> > /*
> > * This function is only called after the system
> > @@ -301,14 +368,27 @@ void default_machine_crash_shutdown(stru
> > */
> > hard_irq_disable();
> > =20
> > - for_each_irq(irq) {
> > - struct irq_desc *desc =3D irq_desc + irq;
> > + for_each_irq(i) {
> > + struct irq_desc *desc =3D irq_desc + i;
> > =20
> > if (desc->status & IRQ_INPROGRESS)
> > - desc->chip->eoi(irq);
> > + desc->chip->eoi(i);
> > =20
> > if (!(desc->status & IRQ_DISABLED))
> > - desc->chip->disable(irq);
> > + desc->chip->disable(i);
> > + }
> > +
> > + /* Call registered shutdown routines */
> > + __debugger_fault_handler =3D handle_fault;
> > + i =3D 0;
> > + while(crash_shutdown_handles[i]){
> > + if (setjmp(crash_shutdown_buf) =3D=3D 0) {
> > + asm volatile("sync; isync");
> > + crash_shutdown_handles[i]();
> > + asm volatile("sync; isync");
> > + __delay(200);
> > + }
> > + i++;
> > }
>
> You should probably reset __debugger_fault_handler, just to be safe.
Agreed.
Mikey
^ permalink raw reply
* Re: [PATCH 1/2] Make setjmp/longjmp code generic
From: Michael Neuling @ 2007-12-12 23:40 UTC (permalink / raw)
To: michael; +Cc: linuxppc-dev, RAISCH, Paul Mackerras, THEMANN
In-Reply-To: <1197500215.7695.11.camel@concordia>
> > arch/powerpc/xmon/setjmp.S | 135 ------------------------------------------
<snip>
> > +#ifdef CONFIG_XMON
> > +/*
> > + * Grab the register values as they are now.
> > + * This won't do a particularily good job because we really
> > + * want our caller's caller's registers, and our caller has
> > + * already executed its prologue.
> > + * ToDo: We could reach back into the caller's save area to do
> > + * a better job of representing the caller's state (note that
> > + * that will be different for 32-bit and 64-bit, because of the
> > + * different ABIs, though).
> > + */
> > +_GLOBAL(xmon_save_regs)
> > + PPC_STL r0,0*SZL(r3)
> > + PPC_STL r2,2*SZL(r3)
> > + PPC_STL r3,3*SZL(r3)
> > + PPC_STL r4,4*SZL(r3)
>
> Does xmon_save_regs belong here?
This was the only function left in xmon/setjmp.S. So rather than rename
the whole file to reflect it no longer has anything to do with setjmp, I
moved it out to misc.S
I'm not fussed what we end up doing.
Mikey
^ permalink raw reply
* Re: [PATCH v2] [POWERPC] pasemi: Implement MSI support
From: Michael Ellerman @ 2007-12-12 23:18 UTC (permalink / raw)
To: Olof Johansson; +Cc: linuxppc-dev
In-Reply-To: <1197499871.7695.9.camel@concordia>
[-- Attachment #1: Type: text/plain, Size: 526 bytes --]
On Thu, 2007-12-13 at 09:51 +1100, Michael Ellerman wrote:
> On Wed, 2007-12-12 at 01:23 -0600, Olof Johansson wrote:
>
> Patch looks good otherwise.
By which I mean:
Acked-by: Michael Ellerman <michael@ellerman.id.au>
This patch is double-plus-good!
cheers
--
Michael Ellerman
OzLabs, IBM Australia Development Lab
wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)
We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: [PATCH 2/2] kdump shutdown hook support
From: Michael Ellerman @ 2007-12-12 23:07 UTC (permalink / raw)
To: Michael Neuling; +Cc: linuxppc-dev, RAISCH, Paul Mackerras, THEMANN
In-Reply-To: <20071212054512.A02B062C153@localhost.localdomain>
[-- Attachment #1: Type: text/plain, Size: 4958 bytes --]
On Wed, 2007-12-12 at 16:45 +1100, Michael Neuling wrote:
> This adds hooks into the default_machine_crash_shutdown so drivers can
> register a function to be run in the first kernel before we hand off
> to the second kernel. This should only be used in exceptional
> circumstances, like where the device can't be reset in the second
> kernel alone (as is the case with eHEA). To emphasize this, the
> number of handles allowed to be registered is currently #def to 1.
>
> This uses the setjmp/longjmp code to call out to the registered hooks,
> so any bogus exceptions we encounter will hopefully be recoverable.
>
> I've tested with bogus data and instruction exceptions.
>
> Signed-off-by: Michael Neuling <mikey@neuling.org>
> ---
>
> arch/powerpc/kernel/crash.c | 90 +++++++++++++++++++++++++++++++++++++++++---
> include/asm-powerpc/kexec.h | 3 +
> 2 files changed, 88 insertions(+), 5 deletions(-)
>
> Index: linux-2.6-ozlabs/arch/powerpc/kernel/crash.c
> ===================================================================
> --- linux-2.6-ozlabs.orig/arch/powerpc/kernel/crash.c
> +++ linux-2.6-ozlabs/arch/powerpc/kernel/crash.c
> @@ -32,6 +32,8 @@
> #include <asm/lmb.h>
> #include <asm/firmware.h>
> #include <asm/smp.h>
> +#include <asm/system.h>
> +#include <asm/setjmp.h>
>
> #ifdef DEBUG
> #include <asm/udbg.h>
> @@ -45,6 +47,11 @@ int crashing_cpu = -1;
> static cpumask_t cpus_in_crash = CPU_MASK_NONE;
> cpumask_t cpus_in_sr = CPU_MASK_NONE;
>
> +#define CRASH_SHUTDOWN_HANDLES_NUM 1
CRASH_HANDLER_MAX ?
> +/* NULL terminated list of shutdown handles */
> +static crash_shutdown_t crash_shutdown_handles[CRASH_SHUTDOWN_HANDLES_NUM+1];
> +static DEFINE_SPINLOCK(crash_handles_lock);
> +
> #ifdef CONFIG_SMP
> static atomic_t enter_on_soft_reset = ATOMIC_INIT(0);
>
> @@ -285,9 +292,69 @@ static inline void crash_kexec_stop_spus
> }
> #endif /* CONFIG_SPU_BASE */
>
> +/*
> + * Register a function to be called on shutdown. Only use this if you
> + * can't reset your device in the second kernel.
> + */
> +int crash_shutdown_register(crash_shutdown_t handler)
> +{
> + unsigned int i, rc;
> +
> + spin_lock(&crash_handles_lock);
> + for(i = 0 ; i <= CRASH_SHUTDOWN_HANDLES_NUM; i++) {
> + if (!crash_shutdown_handles[i]) {
> + /* Insert handle at end */
> + crash_shutdown_handles[i] = handler;
> + rc = 0;
> + break;
> + }
> + }
>
> + if (i == CRASH_SHUTDOWN_HANDLES_NUM){
> + printk(KERN_ERR "Crash shutdown handles full, "
> + "not registered.\n");
> + rc = 1;
> + }
> +
> + spin_unlock(&crash_handles_lock);
Perhaps?
> + return rc;
> +}
> +EXPORT_SYMBOL(crash_shutdown_register);
> +
> +int crash_shutdown_unregister(crash_shutdown_t handler)
> +{
> + unsigned int i;
> +
> + spin_lock(&crash_handles_lock);
> + for(i = 0 ; i <= CRASH_SHUTDOWN_HANDLES_NUM; i++)
> + if (crash_shutdown_handles[i] == handler)
> + break;
> +
> + if (i == CRASH_SHUTDOWN_HANDLES_NUM){
> + printk(KERN_ERR "Crash shutdown handle not found\n");
> + spin_unlock(&crash_handles_lock);
> + return 1;
> + }
> +
> + /* Shift handles down */
> + while(crash_shutdown_handles[i]) {
> + crash_shutdown_handles[i] = crash_shutdown_handles[i+1];
> + i++;
> + }
> + spin_unlock(&crash_handles_lock);
> + return 0;
> +}
> +EXPORT_SYMBOL(crash_shutdown_unregister);
> +
> +static long crash_shutdown_buf[SETJMP_BUF_LEN];
unsigned long?
> +
> +static int handle_fault(struct pt_regs *regs)
> +{
> + longjmp(crash_shutdown_buf, 1);
> + return 0;
> +}
> +
> void default_machine_crash_shutdown(struct pt_regs *regs)
> {
> - unsigned int irq;
> + unsigned int i;
>
> /*
> * This function is only called after the system
> @@ -301,14 +368,27 @@ void default_machine_crash_shutdown(stru
> */
> hard_irq_disable();
>
> - for_each_irq(irq) {
> - struct irq_desc *desc = irq_desc + irq;
> + for_each_irq(i) {
> + struct irq_desc *desc = irq_desc + i;
>
> if (desc->status & IRQ_INPROGRESS)
> - desc->chip->eoi(irq);
> + desc->chip->eoi(i);
>
> if (!(desc->status & IRQ_DISABLED))
> - desc->chip->disable(irq);
> + desc->chip->disable(i);
> + }
> +
> + /* Call registered shutdown routines */
> + __debugger_fault_handler = handle_fault;
> + i = 0;
> + while(crash_shutdown_handles[i]){
> + if (setjmp(crash_shutdown_buf) == 0) {
> + asm volatile("sync; isync");
> + crash_shutdown_handles[i]();
> + asm volatile("sync; isync");
> + __delay(200);
> + }
> + i++;
> }
You should probably reset __debugger_fault_handler, just to be safe.
cheers
--
Michael Ellerman
OzLabs, IBM Australia Development Lab
wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)
We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox