diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-28 09:24:14 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-28 09:24:14 -0700 |
commit | e430426654c6a99fb1977bae71d4844e876c4a52 (patch) | |
tree | 65a22a59321b6bed5579c2e58371eeb373e1db61 /arch/parisc/kernel | |
parent | e732ff707743e5ceba6ae2bfc7e799a0bac30ffa (diff) | |
parent | 650a35f868f809aade56ef960d8a465f57ac74e2 (diff) |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/kyle/parisc-2.6
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/kyle/parisc-2.6:
parisc: add tty driver to PDC console
drivers/parisc/iosapic.c: Remove unnecessary kzalloc cast
parisc: remove homegrown L1_CACHE_ALIGN macro
arch/parisc: Removing undead ifdef CONFIG_PA20
parisc: unwind - optimise linked-list searches for modules
parisc: change to new flag variable
drivers/char/agp/parisc-agp.c: eliminate memory leak
parisc: kill __do_IRQ
parisc: convert eisa interrupts to flow handlers
parisc: convert gsc and dino pci interrupts to flow handlers
parisc: convert suckyio interrupts to flow handlers
parisc: convert iosapic interrupts to proper flow handlers
parisc: convert cpu interrupts to proper flow handlers
parisc: lay groundwork for killing __do_IRQ
parisc: add prlimit64 syscall
parisc: squelch warning when using dev_get_stats
Diffstat (limited to 'arch/parisc/kernel')
-rw-r--r-- | arch/parisc/kernel/irq.c | 41 | ||||
-rw-r--r-- | arch/parisc/kernel/pdc_cons.c | 141 | ||||
-rw-r--r-- | arch/parisc/kernel/syscall_table.S | 1 | ||||
-rw-r--r-- | arch/parisc/kernel/unaligned.c | 3 | ||||
-rw-r--r-- | arch/parisc/kernel/unwind.c | 5 |
5 files changed, 157 insertions, 34 deletions
diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c index efbcee5d222..5024f643b3b 100644 --- a/arch/parisc/kernel/irq.c +++ b/arch/parisc/kernel/irq.c @@ -52,7 +52,7 @@ static volatile unsigned long cpu_eiem = 0; */ static DEFINE_PER_CPU(unsigned long, local_ack_eiem) = ~0UL; -static void cpu_disable_irq(unsigned int irq) +static void cpu_mask_irq(unsigned int irq) { unsigned long eirr_bit = EIEM_MASK(irq); @@ -63,7 +63,7 @@ static void cpu_disable_irq(unsigned int irq) * then gets disabled */ } -static void cpu_enable_irq(unsigned int irq) +static void cpu_unmask_irq(unsigned int irq) { unsigned long eirr_bit = EIEM_MASK(irq); @@ -75,12 +75,6 @@ static void cpu_enable_irq(unsigned int irq) smp_send_all_nop(); } -static unsigned int cpu_startup_irq(unsigned int irq) -{ - cpu_enable_irq(irq); - return 0; -} - void no_ack_irq(unsigned int irq) { } void no_end_irq(unsigned int irq) { } @@ -99,7 +93,7 @@ void cpu_ack_irq(unsigned int irq) mtctl(mask, 23); } -void cpu_end_irq(unsigned int irq) +void cpu_eoi_irq(unsigned int irq) { unsigned long mask = EIEM_MASK(irq); int cpu = smp_processor_id(); @@ -146,12 +140,10 @@ static int cpu_set_affinity_irq(unsigned int irq, const struct cpumask *dest) static struct irq_chip cpu_interrupt_type = { .name = "CPU", - .startup = cpu_startup_irq, - .shutdown = cpu_disable_irq, - .enable = cpu_enable_irq, - .disable = cpu_disable_irq, + .mask = cpu_mask_irq, + .unmask = cpu_unmask_irq, .ack = cpu_ack_irq, - .end = cpu_end_irq, + .eoi = cpu_eoi_irq, #ifdef CONFIG_SMP .set_affinity = cpu_set_affinity_irq, #endif @@ -247,10 +239,11 @@ int cpu_claim_irq(unsigned int irq, struct irq_chip *type, void *data) if (irq_desc[irq].chip != &cpu_interrupt_type) return -EBUSY; + /* for iosapic interrupts */ if (type) { - irq_desc[irq].chip = type; - irq_desc[irq].chip_data = data; - cpu_interrupt_type.enable(irq); + set_irq_chip_and_handler(irq, type, handle_level_irq); + set_irq_chip_data(irq, data); + cpu_unmask_irq(irq); } return 0; } @@ -368,7 +361,7 @@ void do_cpu_irq_mask(struct pt_regs *regs) goto set_out; } #endif - __do_IRQ(irq); + generic_handle_irq(irq); out: irq_exit(); @@ -398,14 +391,15 @@ static void claim_cpu_irqs(void) { int i; for (i = CPU_IRQ_BASE; i <= CPU_IRQ_MAX; i++) { - irq_desc[i].chip = &cpu_interrupt_type; + set_irq_chip_and_handler(i, &cpu_interrupt_type, + handle_level_irq); } - irq_desc[TIMER_IRQ].action = &timer_action; - irq_desc[TIMER_IRQ].status = IRQ_PER_CPU; + set_irq_handler(TIMER_IRQ, handle_percpu_irq); + setup_irq(TIMER_IRQ, &timer_action); #ifdef CONFIG_SMP - irq_desc[IPI_IRQ].action = &ipi_action; - irq_desc[IPI_IRQ].status = IRQ_PER_CPU; + set_irq_handler(IPI_IRQ, handle_percpu_irq); + setup_irq(IPI_IRQ, &ipi_action); #endif } @@ -423,3 +417,4 @@ void __init init_IRQ(void) set_eiem(cpu_eiem); /* EIEM : enable all external intr */ } + diff --git a/arch/parisc/kernel/pdc_cons.c b/arch/parisc/kernel/pdc_cons.c index 1ff366cb968..66d1f17fdb9 100644 --- a/arch/parisc/kernel/pdc_cons.c +++ b/arch/parisc/kernel/pdc_cons.c @@ -12,6 +12,7 @@ * Copyright (C) 2001 Helge Deller <deller at parisc-linux.org> * Copyright (C) 2001 Thomas Bogendoerfer <tsbogend at parisc-linux.org> * Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org> + * Copyright (C) 2010 Guy Martin <gmsoft at tuxicoman.be> * * * This program is free software; you can redistribute it and/or modify @@ -31,12 +32,11 @@ /* * The PDC console is a simple console, which can be used for debugging - * boot related problems on HP PA-RISC machines. + * boot related problems on HP PA-RISC machines. It is also useful when no + * other console works. * * This code uses the ROM (=PDC) based functions to read and write characters * from and to PDC's boot path. - * Since all character read from that path must be polled, this code never - * can or will be a fully functional linux console. */ /* Define EARLY_BOOTUP_DEBUG to debug kernel related boot problems. @@ -53,6 +53,7 @@ #include <asm/pdc.h> /* for iodc_call() proto and friends */ static DEFINE_SPINLOCK(pdc_console_lock); +static struct console pdc_cons; static void pdc_console_write(struct console *co, const char *s, unsigned count) { @@ -85,12 +86,138 @@ static int pdc_console_setup(struct console *co, char *options) #if defined(CONFIG_PDC_CONSOLE) #include <linux/vt_kern.h> +#include <linux/tty_flip.h> + +#define PDC_CONS_POLL_DELAY (30 * HZ / 1000) + +static struct timer_list pdc_console_timer; + +extern struct console * console_drivers; + +static int pdc_console_tty_open(struct tty_struct *tty, struct file *filp) +{ + + mod_timer(&pdc_console_timer, jiffies + PDC_CONS_POLL_DELAY); + + return 0; +} + +static void pdc_console_tty_close(struct tty_struct *tty, struct file *filp) +{ + if (!tty->count) + del_timer(&pdc_console_timer); +} + +static int pdc_console_tty_write(struct tty_struct *tty, const unsigned char *buf, int count) +{ + pdc_console_write(NULL, buf, count); + return count; +} + +static int pdc_console_tty_write_room(struct tty_struct *tty) +{ + return 32768; /* no limit, no buffer used */ +} + +static int pdc_console_tty_chars_in_buffer(struct tty_struct *tty) +{ + return 0; /* no buffer */ +} + +static struct tty_driver *pdc_console_tty_driver; + +static const struct tty_operations pdc_console_tty_ops = { + .open = pdc_console_tty_open, + .close = pdc_console_tty_close, + .write = pdc_console_tty_write, + .write_room = pdc_console_tty_write_room, + .chars_in_buffer = pdc_console_tty_chars_in_buffer, +}; + +static void pdc_console_poll(unsigned long unused) +{ + + int data, count = 0; + + struct tty_struct *tty = pdc_console_tty_driver->ttys[0]; + + if (!tty) + return; + + while (1) { + data = pdc_console_poll_key(NULL); + if (data == -1) + break; + tty_insert_flip_char(tty, data & 0xFF, TTY_NORMAL); + count ++; + } + + if (count) + tty_flip_buffer_push(tty); + + if (tty->count && (pdc_cons.flags & CON_ENABLED)) + mod_timer(&pdc_console_timer, jiffies + PDC_CONS_POLL_DELAY); +} + +static int __init pdc_console_tty_driver_init(void) +{ + + int err; + struct tty_driver *drv; + + /* Check if the console driver is still registered. + * It is unregistered if the pdc console was not selected as the + * primary console. */ + + struct console *tmp = console_drivers; + + for (tmp = console_drivers; tmp; tmp = tmp->next) + if (tmp == &pdc_cons) + break; + + if (!tmp) { + printk(KERN_INFO "PDC console driver not registered anymore, not creating %s\n", pdc_cons.name); + return -ENODEV; + } + + printk(KERN_INFO "The PDC console driver is still registered, removing CON_BOOT flag\n"); + pdc_cons.flags &= ~CON_BOOT; + + drv = alloc_tty_driver(1); + + if (!drv) + return -ENOMEM; + + drv->driver_name = "pdc_cons"; + drv->name = "ttyB"; + drv->major = MUX_MAJOR; + drv->minor_start = 0; + drv->type = TTY_DRIVER_TYPE_SYSTEM; + drv->init_termios = tty_std_termios; + drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS; + tty_set_operations(drv, &pdc_console_tty_ops); + + err = tty_register_driver(drv); + if (err) { + printk(KERN_ERR "Unable to register the PDC console TTY driver\n"); + return err; + } + + pdc_console_tty_driver = drv; + + /* No need to initialize the pdc_console_timer if tty isn't allocated */ + init_timer(&pdc_console_timer); + pdc_console_timer.function = pdc_console_poll; + + return 0; +} + +module_init(pdc_console_tty_driver_init); static struct tty_driver * pdc_console_device (struct console *c, int *index) { - extern struct tty_driver console_driver; - *index = c->index ? c->index-1 : fg_console; - return &console_driver; + *index = c->index; + return pdc_console_tty_driver; } #else #define pdc_console_device NULL @@ -101,7 +228,7 @@ static struct console pdc_cons = { .write = pdc_console_write, .device = pdc_console_device, .setup = pdc_console_setup, - .flags = CON_BOOT | CON_PRINTBUFFER | CON_ENABLED, + .flags = CON_BOOT | CON_PRINTBUFFER, .index = -1, }; diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S index 3d52c978738..74867dfdabe 100644 --- a/arch/parisc/kernel/syscall_table.S +++ b/arch/parisc/kernel/syscall_table.S @@ -419,6 +419,7 @@ ENTRY_SAME(perf_event_open) ENTRY_COMP(recvmmsg) ENTRY_SAME(accept4) /* 320 */ + ENTRY_SAME(prlimit64) /* Nothing yet */ diff --git a/arch/parisc/kernel/unaligned.c b/arch/parisc/kernel/unaligned.c index 92d977bb5ea..234e3682cf0 100644 --- a/arch/parisc/kernel/unaligned.c +++ b/arch/parisc/kernel/unaligned.c @@ -619,15 +619,12 @@ void handle_unaligned(struct pt_regs *regs) flop=1; ret = emulate_std(regs, R2(regs->iir),1); break; - -#ifdef CONFIG_PA20 case OPCODE_LDD_L: ret = emulate_ldd(regs, R2(regs->iir),0); break; case OPCODE_STD_L: ret = emulate_std(regs, R2(regs->iir),0); break; -#endif } #endif switch (regs->iir & OPCODE3_MASK) diff --git a/arch/parisc/kernel/unwind.c b/arch/parisc/kernel/unwind.c index d58eac1a828..76ed62ed785 100644 --- a/arch/parisc/kernel/unwind.c +++ b/arch/parisc/kernel/unwind.c @@ -80,8 +80,11 @@ find_unwind_entry(unsigned long addr) if (addr >= table->start && addr <= table->end) e = find_unwind_entry_in_table(table, addr); - if (e) + if (e) { + /* Move-to-front to exploit common traces */ + list_move(&table->list, &unwind_tables); break; + } } return e; |