Commit fc8ab213 authored by Anton Blanchard's avatar Anton Blanchard

Merge samba.org:/scratch/anton/export

into samba.org:/scratch/anton/linux-2.5_ppc64
parents 979bd8fe 4f6b41e5
...@@ -18,7 +18,7 @@ KERNELLOAD := 0xc000000000000000 ...@@ -18,7 +18,7 @@ KERNELLOAD := 0xc000000000000000
LDFLAGS := -m elf64ppc LDFLAGS := -m elf64ppc
LDFLAGS_vmlinux := -Bstatic -e $(KERNELLOAD) -Ttext $(KERNELLOAD) LDFLAGS_vmlinux := -Bstatic -e $(KERNELLOAD) -Ttext $(KERNELLOAD)
CFLAGS += -msoft-float -pipe -Wno-uninitialized -mminimal-toc \ CFLAGS += -msoft-float -pipe -Wno-uninitialized -mminimal-toc \
-mtraceback=full -mcpu=power4 -mcpu=power4
have_zero_bss := $(shell if $(CC) -fno-zero-initialized-in-bss -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi) have_zero_bss := $(shell if $(CC) -fno-zero-initialized-in-bss -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi)
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/random.h> #include <linux/random.h>
#include <linux/kallsyms.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/bitops.h> #include <asm/bitops.h>
...@@ -350,14 +351,11 @@ int show_interrupts(struct seq_file *p, void *v) ...@@ -350,14 +351,11 @@ int show_interrupts(struct seq_file *p, void *v)
return 0; return 0;
} }
extern char *ppc_find_proc_name(unsigned *p, char *buf, unsigned buflen); static inline int handle_irq_event(int irq, struct pt_regs *regs,
struct irqaction *action)
static inline void handle_irq_event(int irq, struct pt_regs *regs,
struct irqaction *action)
{ {
int status = 0; int status = 0;
int retval = 0; int retval = 0;
struct irqaction *first_action = action;
if (!(action->flags & SA_INTERRUPT)) if (!(action->flags & SA_INTERRUPT))
local_irq_enable(); local_irq_enable();
...@@ -370,30 +368,90 @@ static inline void handle_irq_event(int irq, struct pt_regs *regs, ...@@ -370,30 +368,90 @@ static inline void handle_irq_event(int irq, struct pt_regs *regs,
if (status & SA_SAMPLE_RANDOM) if (status & SA_SAMPLE_RANDOM)
add_interrupt_randomness(irq); add_interrupt_randomness(irq);
local_irq_disable(); local_irq_disable();
if (retval != 1) { return retval;
static int count = 100; }
char name_buf[256];
if (count) { static void __report_bad_irq(int irq, irq_desc_t *desc, irqreturn_t action_ret)
count--; {
if (retval) { struct irqaction *action;
printk("irq event %d: bogus retval mask %x\n",
irq, retval); if (action_ret != IRQ_HANDLED && action_ret != IRQ_NONE) {
} else { printk(KERN_ERR "irq event %d: bogus return value %x\n",
printk("irq %d: nobody cared!\n", irq); irq, action_ret);
} } else {
dump_stack(); printk(KERN_ERR "irq %d: nobody cared!\n", irq);
printk("handlers:\n"); }
action = first_action; dump_stack();
do { printk(KERN_ERR "handlers:\n");
printk("[<%p>]", action->handler); action = desc->action;
printk(" (%s)\n", do {
ppc_find_proc_name((unsigned *)action->handler, name_buf, 256)); printk(KERN_ERR "[<%p>]", action->handler);
action = action->next; print_symbol(" (%s)",
} while (action); (unsigned long)action->handler);
} printk("\n");
action = action->next;
} while (action);
}
static void report_bad_irq(int irq, irq_desc_t *desc, irqreturn_t action_ret)
{
static int count = 100;
if (count) {
count--;
__report_bad_irq(irq, desc, action_ret);
} }
} }
static int noirqdebug;
static int __init noirqdebug_setup(char *str)
{
noirqdebug = 1;
printk("IRQ lockup detection disabled\n");
return 1;
}
__setup("noirqdebug", noirqdebug_setup);
/*
* If 99,900 of the previous 100,000 interrupts have not been handled then
* assume that the IRQ is stuck in some manner. Drop a diagnostic and try to
* turn the IRQ off.
*
* (The other 100-of-100,000 interrupts may have been a correctly-functioning
* device sharing an IRQ with the failing one)
*
* Called under desc->lock
*/
static void note_interrupt(int irq, irq_desc_t *desc, irqreturn_t action_ret)
{
if (action_ret != IRQ_HANDLED) {
desc->irqs_unhandled++;
if (action_ret != IRQ_NONE)
report_bad_irq(irq, desc, action_ret);
}
desc->irq_count++;
if (desc->irq_count < 100000)
return;
desc->irq_count = 0;
if (desc->irqs_unhandled > 99900) {
/*
* The interrupt is stuck
*/
__report_bad_irq(irq, desc, action_ret);
/*
* Now kill the IRQ
*/
printk(KERN_EMERG "Disabling IRQ #%d\n", irq);
desc->status |= IRQ_DISABLED;
desc->handler->disable(irq);
}
desc->irqs_unhandled = 0;
}
/* /*
* Eventually, this should take an array of interrupts and an array size * Eventually, this should take an array of interrupts and an array size
* so it can dispatch multiple interrupts. * so it can dispatch multiple interrupts.
...@@ -462,10 +520,13 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq) ...@@ -462,10 +520,13 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq)
* SMP environment. * SMP environment.
*/ */
for (;;) { for (;;) {
irqreturn_t action_ret;
spin_unlock(&desc->lock); spin_unlock(&desc->lock);
handle_irq_event(irq, regs, action); action_ret = handle_irq_event(irq, regs, action);
spin_lock(&desc->lock); spin_lock(&desc->lock);
if (!noirqdebug)
note_interrupt(irq, desc, action_ret);
if (likely(!(desc->status & IRQ_PENDING))) if (likely(!(desc->status & IRQ_PENDING)))
break; break;
desc->status &= ~IRQ_PENDING; desc->status &= ~IRQ_PENDING;
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <linux/init_task.h> #include <linux/init_task.h>
#include <linux/prctl.h> #include <linux/prctl.h>
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/kallsyms.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -130,12 +131,9 @@ struct task_struct *__switch_to(struct task_struct *prev, ...@@ -130,12 +131,9 @@ struct task_struct *__switch_to(struct task_struct *prev,
return last; return last;
} }
char *ppc_find_proc_name(unsigned *p, char *buf, unsigned buflen);
void show_regs(struct pt_regs * regs) void show_regs(struct pt_regs * regs)
{ {
int i; int i;
char name_buf[256];
printk("NIP: %016lX XER: %016lX LR: %016lX\n", printk("NIP: %016lX XER: %016lX LR: %016lX\n",
regs->nip, regs->xer, regs->link); regs->nip, regs->xer, regs->link);
...@@ -170,8 +168,7 @@ void show_regs(struct pt_regs * regs) ...@@ -170,8 +168,7 @@ void show_regs(struct pt_regs * regs)
* above info out without failing * above info out without failing
*/ */
printk("NIP [%016lx] ", regs->nip); printk("NIP [%016lx] ", regs->nip);
printk("%s\n", ppc_find_proc_name((unsigned *)regs->nip, print_symbol("%s\n", regs->nip);
name_buf, 256));
show_stack(current, (unsigned long *)regs->gpr[1]); show_stack(current, (unsigned long *)regs->gpr[1]);
} }
...@@ -385,62 +382,6 @@ int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2, ...@@ -385,62 +382,6 @@ int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
return error; return error;
} }
char *ppc_find_proc_name(unsigned *p, char *buf, unsigned buflen)
{
unsigned long tb_flags;
unsigned short name_len;
unsigned long tb_start, code_start, code_ptr, code_offset;
unsigned int code_len;
unsigned long end;
strcpy(buf, "Unknown");
code_ptr = (unsigned long)p;
code_offset = 0;
/* handle functions in text and init sections */
if (((unsigned long)p >= (unsigned long)_stext) &&
((unsigned long)p < (unsigned long)_etext))
end = (unsigned long)_etext;
else if (((unsigned long)p >= (unsigned long)__init_begin) &&
((unsigned long)p < (unsigned long)__init_end))
end = (unsigned long)__init_end;
else
return buf;
while ((unsigned long)p < end) {
if (*p == 0) {
tb_start = (unsigned long)p;
++p; /* Point to traceback flags */
tb_flags = *((unsigned long *)p);
p += 2; /* Skip over traceback flags */
if (tb_flags & TB_NAME_PRESENT) {
if (tb_flags & TB_PARMINFO)
++p; /* skip over parminfo data */
if (tb_flags & TB_HAS_TBOFF) {
code_len = *p; /* get code length */
code_start = tb_start - code_len;
code_offset = code_ptr - code_start + 1;
if (code_offset > 0x100000)
break;
++p; /* skip over code size */
}
name_len = *((unsigned short *)p);
if (name_len > (buflen-20))
name_len = buflen-20;
memcpy(buf, ((char *)p)+2, name_len);
buf[name_len] = 0;
if (code_offset)
sprintf(buf+name_len, "+0x%lx",
code_offset-1);
}
break;
}
++p;
}
return buf;
}
/* /*
* These bracket the sleeping functions.. * These bracket the sleeping functions..
*/ */
...@@ -480,7 +421,6 @@ void show_stack(struct task_struct *p, unsigned long *_sp) ...@@ -480,7 +421,6 @@ void show_stack(struct task_struct *p, unsigned long *_sp)
unsigned long ip; unsigned long ip;
unsigned long stack_page = (unsigned long)p->thread_info; unsigned long stack_page = (unsigned long)p->thread_info;
int count = 0; int count = 0;
char name_buf[256];
unsigned long sp = (unsigned long)_sp; unsigned long sp = (unsigned long)_sp;
if (!p) if (!p)
...@@ -499,8 +439,7 @@ void show_stack(struct task_struct *p, unsigned long *_sp) ...@@ -499,8 +439,7 @@ void show_stack(struct task_struct *p, unsigned long *_sp)
if (__get_user(ip, (unsigned long *)(sp + 16))) if (__get_user(ip, (unsigned long *)(sp + 16)))
break; break;
printk("[%016lx] ", ip); printk("[%016lx] ", ip);
printk("%s\n", ppc_find_proc_name((unsigned *)ip, print_symbol("%s\n", ip);
name_buf, 256));
} while (count++ < 32); } while (count++ < 32);
} }
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment