Commit cf17c020 authored by Dave Jones's avatar Dave Jones

Merge tetrachloride.(none):/mnt/raid/src/kernel/2.5/bk-linus

into tetrachloride.(none):/mnt/raid/src/kernel/2.5/agpgart
parents 30ffac45 f55ae64b
/* /*
* Copyright (C) 1995-2001 Russell King * Copyright (C) 1995-2003 Russell King
* 2001-2002 Keith Owens * 2001-2002 Keith Owens
* *
* Generate definitions needed by assembly language modules. * Generate definitions needed by assembly language modules.
...@@ -24,12 +24,21 @@ ...@@ -24,12 +24,21 @@
#if defined(__APCS_26__) #if defined(__APCS_26__)
#error Sorry, your compiler targets APCS-26 but this kernel requires APCS-32 #error Sorry, your compiler targets APCS-26 but this kernel requires APCS-32
#endif #endif
#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 95) /*
#error Sorry, your compiler is known to miscompile kernels. Only use gcc 2.95.3 and later. * GCC 2.95.1, 2.95.2: ignores register clobber list in asm().
#endif * GCC 3.0, 3.1: general bad code generation.
#if __GNUC__ == 2 && __GNUC_MINOR__ == 95 * GCC 3.2.0: incorrect function argument offset calculation.
/* shame we can't detect the .1 or .2 releases */ * GCC 3.2.x: miscompiles NEW_AUX_ENT in fs/binfmt_elf.c
#warning GCC 2.95.2 and earlier miscompiles kernels. * (http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view&pr=8896)
*/
#if __GNUC__ < 2 || \
(__GNUC__ == 2 && __GNUC_MINOR__ < 95) || \
(__GNUC__ == 2 && __GNUC_MINOR__ == 95 && __GNUC_PATCHLEVEL__ != 0 && \
__GNUC_PATCHLEVEL__ < 3) || \
(__GNUC__ == 3 && __GNUC_MINOR__ < 2) || \
(__GNUC__ == 3 && __GNUC_MINOR__ == 2 && __GNUC_PATCHLEVEL__ < 1)
#error Your compiler is too buggy; it is known to miscompile kernels.
#error Known good compilers: 2.95.3, 2.95.4, 2.96, 3.2.2+PR8896
#endif #endif
/* Use marker if you need to separate the values later */ /* Use marker if you need to separate the values later */
...@@ -62,7 +71,6 @@ int main(void) ...@@ -62,7 +71,6 @@ int main(void)
DEFINE(LPTE_EXEC, L_PTE_EXEC); DEFINE(LPTE_EXEC, L_PTE_EXEC);
DEFINE(LPTE_DIRTY, L_PTE_DIRTY); DEFINE(LPTE_DIRTY, L_PTE_DIRTY);
BLANK(); BLANK();
BLANK();
DEFINE(PAGE_SZ, PAGE_SIZE); DEFINE(PAGE_SZ, PAGE_SIZE);
BLANK(); BLANK();
DEFINE(SYS_ERROR0, 0x9f0000); DEFINE(SYS_ERROR0, 0x9f0000);
......
/* /*
* linux/arch/arm/lib/calls.h * linux/arch/arm/kernel/calls.S
* *
* Copyright (C) 1995-1998 Russell King * Copyright (C) 1995-2003 Russell King
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
......
...@@ -621,7 +621,7 @@ ENTRY(anakin_active_irqs) ...@@ -621,7 +621,7 @@ ENTRY(anakin_active_irqs)
rsb \irqstat, \irqnr, #0 rsb \irqstat, \irqnr, #0
and \irqstat, \irqstat, \irqnr and \irqstat, \irqstat, \irqnr
clz \irqnr, \irqstat clz \irqnr, \irqstat
rsb \irqnr, \irqnr, #23 rsb \irqnr, \irqnr, #(31 - PXA_IRQ_SKIP)
1001: 1001:
.endm .endm
......
...@@ -58,6 +58,11 @@ void dummy_mask_unmask_irq(unsigned int irq) ...@@ -58,6 +58,11 @@ void dummy_mask_unmask_irq(unsigned int irq)
{ {
} }
irqreturn_t no_action(int irq, void *dev_id, struct pt_regs *regs)
{
return IRQ_NONE;
}
void do_bad_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) void do_bad_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
{ {
irq_err_count += 1; irq_err_count += 1;
...@@ -222,6 +227,7 @@ static void ...@@ -222,6 +227,7 @@ static void
__do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs) __do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs)
{ {
unsigned int status; unsigned int status;
int retval = 0;
spin_unlock(&irq_controller_lock); spin_unlock(&irq_controller_lock);
...@@ -231,7 +237,7 @@ __do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs) ...@@ -231,7 +237,7 @@ __do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs)
status = 0; status = 0;
do { do {
status |= action->flags; status |= action->flags;
action->handler(irq, action->dev_id, regs); retval |= action->handler(irq, action->dev_id, regs);
action = action->next; action = action->next;
} while (action); } while (action);
...@@ -239,6 +245,19 @@ __do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs) ...@@ -239,6 +245,19 @@ __do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs)
add_interrupt_randomness(irq); add_interrupt_randomness(irq);
spin_lock_irq(&irq_controller_lock); spin_lock_irq(&irq_controller_lock);
if (retval != 1) {
static int count = 100;
if (count) {
count--;
if (retval) {
printk("irq event %d: bogus retval mask %x\n",
irq, retval);
} else {
printk("irq %d: nobody cared\n", irq);
}
}
}
} }
/* /*
...@@ -606,7 +625,7 @@ int setup_irq(unsigned int irq, struct irqaction *new) ...@@ -606,7 +625,7 @@ int setup_irq(unsigned int irq, struct irqaction *new)
* SA_SAMPLE_RANDOM The interrupt can be used for entropy * SA_SAMPLE_RANDOM The interrupt can be used for entropy
* *
*/ */
int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *),
unsigned long irq_flags, const char * devname, void *dev_id) unsigned long irq_flags, const char * devname, void *dev_id)
{ {
unsigned long retval; unsigned long retval;
......
...@@ -16,10 +16,18 @@ ...@@ -16,10 +16,18 @@
#include <asm/leds.h> #include <asm/leds.h>
#include <asm/system.h> #include <asm/system.h>
/*
* Tell the linker that pm_do_suspend may not be present.
*/
extern int pm_do_suspend(void) __attribute__((weak));
int suspend(void) int suspend(void)
{ {
int ret; int ret;
if (!pm_do_suspend)
return -ENOSYS;
/* /*
* Suspend "legacy" devices. * Suspend "legacy" devices.
*/ */
...@@ -82,9 +90,26 @@ int suspend(void) ...@@ -82,9 +90,26 @@ int suspend(void)
} }
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
/*
* We really want this to die. It's a disgusting hack using unallocated
* sysctl numbers. We should be using a real interface.
*/
#include <linux/init.h> #include <linux/init.h>
#include <linux/sysctl.h> #include <linux/sysctl.h>
static int
pm_sysctl_proc_handler(ctl_table *ctl, int write, struct file *filp,
void *buffer, size_t *lenp)
{
int ret = -EIO;
printk("PM: task %s (pid %d) uses deprecated sysctl PM interface\n",
current->comm, current->pid);
if (write)
ret = suspend();
return ret;
}
/* /*
* This came from arch/arm/mach-sa1100/pm.c: * This came from arch/arm/mach-sa1100/pm.c:
* Copyright (c) 2001 Cliff Brake <cbrake@accelent.com> * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
...@@ -102,13 +127,23 @@ int suspend(void) ...@@ -102,13 +127,23 @@ int suspend(void)
static struct ctl_table pm_table[] = static struct ctl_table pm_table[] =
{ {
{ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, (proc_handler *)&suspend}, {
.ctl_name = ACPI_S1_SLP_TYP,
.procname = "suspend",
.mode = 0200,
.proc_handler = pm_sysctl_proc_handler,
},
{0} {0}
}; };
static struct ctl_table pm_dir_table[] = static struct ctl_table pm_dir_table[] =
{ {
{CTL_ACPI, "pm", NULL, 0, 0555, pm_table}, {
.ctl_name = CTL_ACPI,
.procname = "pm",
.mode = 0555,
.child = pm_table,
},
{0} {0}
}; };
......
...@@ -18,10 +18,12 @@ ...@@ -18,10 +18,12 @@
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/user.h> #include <linux/user.h>
#include <linux/security.h> #include <linux/security.h>
#include <linux/init.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/traps.h>
#include "ptrace.h" #include "ptrace.h"
...@@ -32,7 +34,7 @@ ...@@ -32,7 +34,7 @@
* in exit.c or in signal.c. * in exit.c or in signal.c.
*/ */
#if 1 #if 0
/* /*
* Breakpoint SWI instruction: SWI &9F0001 * Breakpoint SWI instruction: SWI &9F0001
*/ */
...@@ -479,25 +481,47 @@ void ptrace_break(struct task_struct *tsk, struct pt_regs *regs) ...@@ -479,25 +481,47 @@ void ptrace_break(struct task_struct *tsk, struct pt_regs *regs)
{ {
siginfo_t info; siginfo_t info;
/*
* The PC is always left pointing at the next instruction. Fix this.
*/
regs->ARM_pc -= 4;
if (tsk->thread.debug.nsaved == 0)
printk(KERN_ERR "ptrace: bogus breakpoint trap\n");
ptrace_cancel_bpt(tsk); ptrace_cancel_bpt(tsk);
info.si_signo = SIGTRAP; info.si_signo = SIGTRAP;
info.si_errno = 0; info.si_errno = 0;
info.si_code = TRAP_BRKPT; info.si_code = TRAP_BRKPT;
info.si_addr = (void *)instruction_pointer(regs) - info.si_addr = (void *)instruction_pointer(regs);
(thumb_mode(regs) ? 2 : 4);
force_sig_info(SIGTRAP, &info, tsk); force_sig_info(SIGTRAP, &info, tsk);
} }
static int break_trap(struct pt_regs *regs, unsigned int instr)
{
ptrace_break(current, regs);
return 0;
}
static struct undef_hook arm_break_hook = {
.instr_mask = 0x0fffffff,
.instr_val = 0x07f001f0,
.cpsr_mask = PSR_T_BIT,
.cpsr_val = 0,
.fn = break_trap,
};
static struct undef_hook thumb_break_hook = {
.instr_mask = 0xffff,
.instr_val = 0xde01,
.cpsr_mask = PSR_T_BIT,
.cpsr_val = PSR_T_BIT,
.fn = break_trap,
};
static int __init ptrace_break_init(void)
{
register_undef_hook(&arm_break_hook);
register_undef_hook(&thumb_break_hook);
return 0;
}
core_initcall(ptrace_break_init);
/* /*
* Read the word at offset "off" into the "struct user". We * Read the word at offset "off" into the "struct user". We
* actually access the pt_regs stored on the kernel stack. * actually access the pt_regs stored on the kernel stack.
......
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
#include <asm/system.h> #include <asm/system.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/unistd.h> #include <asm/unistd.h>
#include <asm/semaphore.h> #include <asm/traps.h>
#include "ptrace.h" #include "ptrace.h"
...@@ -240,17 +240,56 @@ void die_if_kernel(const char *str, struct pt_regs *regs, int err) ...@@ -240,17 +240,56 @@ void die_if_kernel(const char *str, struct pt_regs *regs, int err)
die(str, regs, err); die(str, regs, err);
} }
static LIST_HEAD(undef_hook);
static spinlock_t undef_lock = SPIN_LOCK_UNLOCKED;
void register_undef_hook(struct undef_hook *hook)
{
spin_lock_irq(&undef_lock);
list_add(&hook->node, &undef_hook);
spin_unlock_irq(&undef_lock);
}
void unregister_undef_hook(struct undef_hook *hook)
{
spin_lock_irq(&undef_lock);
list_del(&hook->node);
spin_unlock_irq(&undef_lock);
}
asmlinkage void do_undefinstr(struct pt_regs *regs) asmlinkage void do_undefinstr(struct pt_regs *regs)
{ {
unsigned long *pc; unsigned int correction = thumb_mode(regs) ? 2 : 4;
unsigned int instr;
struct undef_hook *hook;
siginfo_t info; siginfo_t info;
void *pc;
/* /*
* According to the ARM ARM, PC is 2 or 4 bytes ahead, depending * According to the ARM ARM, PC is 2 or 4 bytes ahead,
* whether we're in Thumb mode or not. * depending whether we're in Thumb mode or not.
* Correct this offset.
*/ */
regs->ARM_pc -= thumb_mode(regs) ? 2 : 4; regs->ARM_pc -= correction;
pc = (unsigned long *)instruction_pointer(regs);
pc = (void *)instruction_pointer(regs);
if (thumb_mode(regs)) {
get_user(instr, (u16 *)pc);
} else {
get_user(instr, (u32 *)pc);
}
spin_lock_irq(&undef_lock);
list_for_each_entry(hook, &undef_hook, node) {
if ((instr & hook->instr_mask) == hook->instr_val &&
(regs->ARM_cpsr & hook->cpsr_mask) == hook->cpsr_val) {
if (hook->fn(regs, instr) == 0) {
spin_unlock_irq(&undef_lock);
return;
}
}
}
spin_unlock_irq(&undef_lock);
#ifdef CONFIG_DEBUG_USER #ifdef CONFIG_DEBUG_USER
printk(KERN_INFO "%s (%d): undefined instruction: pc=%p\n", printk(KERN_INFO "%s (%d): undefined instruction: pc=%p\n",
...@@ -377,6 +416,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) ...@@ -377,6 +416,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
return 0; return 0;
case NR(breakpoint): /* SWI BREAK_POINT */ case NR(breakpoint): /* SWI BREAK_POINT */
regs->ARM_pc -= thumb_mode(regs) ? 2 : 4;
ptrace_break(current, regs); ptrace_break(current, regs);
return regs->ARM_r0; return regs->ARM_r0;
......
...@@ -13,11 +13,7 @@ ...@@ -13,11 +13,7 @@
#include <asm/assembler.h> #include <asm/assembler.h>
#include <asm/constants.h> #include <asm/constants.h>
#ifndef PLD #define COPY_COUNT (PAGE_SZ/64 PLD( -1 ))
#define COPY_COUNT PAGE_SZ/64
#else
#define COPY_COUNT PAGE_SZ/64-1
#endif
.text .text
.align 5 .align 5
......
...@@ -65,7 +65,7 @@ dc21285_read_config(struct pci_bus *bus, unsigned int devfn, int where, ...@@ -65,7 +65,7 @@ dc21285_read_config(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 *value) int size, u32 *value)
{ {
unsigned long addr = dc21285_base_address(bus, devfn); unsigned long addr = dc21285_base_address(bus, devfn);
u32 v; u32 v = 0xffffffff;
if (addr) if (addr)
switch (size) { switch (size) {
...@@ -82,8 +82,6 @@ dc21285_read_config(struct pci_bus *bus, unsigned int devfn, int where, ...@@ -82,8 +82,6 @@ dc21285_read_config(struct pci_bus *bus, unsigned int devfn, int where,
: "=r" (v) : "r" (addr), "r" (where)); : "=r" (v) : "r" (addr), "r" (where));
break; break;
} }
else
v = 0xffffffff;
*value = v; *value = v;
...@@ -154,7 +152,7 @@ static void dc21285_enable_error(unsigned long __data) ...@@ -154,7 +152,7 @@ static void dc21285_enable_error(unsigned long __data)
/* /*
* Warn on PCI errors. * Warn on PCI errors.
*/ */
static void dc21285_abort_irq(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t dc21285_abort_irq(int irq, void *dev_id, struct pt_regs *regs)
{ {
unsigned int cmd; unsigned int cmd;
unsigned int status; unsigned int status;
...@@ -180,9 +178,11 @@ static void dc21285_abort_irq(int irq, void *dev_id, struct pt_regs *regs) ...@@ -180,9 +178,11 @@ static void dc21285_abort_irq(int irq, void *dev_id, struct pt_regs *regs)
} }
*CSR_PCICMD = cmd; *CSR_PCICMD = cmd;
return IRQ_HANDLED;
} }
static void dc21285_serr_irq(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t dc21285_serr_irq(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct timer_list *timer = dev_id; struct timer_list *timer = dev_id;
unsigned int cntl; unsigned int cntl;
...@@ -200,15 +200,19 @@ static void dc21285_serr_irq(int irq, void *dev_id, struct pt_regs *regs) ...@@ -200,15 +200,19 @@ static void dc21285_serr_irq(int irq, void *dev_id, struct pt_regs *regs)
disable_irq(irq); disable_irq(irq);
timer->expires = jiffies + HZ; timer->expires = jiffies + HZ;
add_timer(timer); add_timer(timer);
return IRQ_HANDLED;
} }
static void dc21285_discard_irq(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t dc21285_discard_irq(int irq, void *dev_id, struct pt_regs *regs)
{ {
printk(KERN_DEBUG "PCI: discard timer expired\n"); printk(KERN_DEBUG "PCI: discard timer expired\n");
*CSR_SA110_CNTL &= 0xffffde07; *CSR_SA110_CNTL &= 0xffffde07;
return IRQ_HANDLED;
} }
static void dc21285_dparity_irq(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t dc21285_dparity_irq(int irq, void *dev_id, struct pt_regs *regs)
{ {
unsigned int cmd; unsigned int cmd;
...@@ -218,9 +222,11 @@ static void dc21285_dparity_irq(int irq, void *dev_id, struct pt_regs *regs) ...@@ -218,9 +222,11 @@ static void dc21285_dparity_irq(int irq, void *dev_id, struct pt_regs *regs)
cmd = *CSR_PCICMD & 0xffff; cmd = *CSR_PCICMD & 0xffff;
*CSR_PCICMD = cmd | 1 << 24; *CSR_PCICMD = cmd | 1 << 24;
return IRQ_HANDLED;
} }
static void dc21285_parity_irq(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t dc21285_parity_irq(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct timer_list *timer = dev_id; struct timer_list *timer = dev_id;
unsigned int cmd; unsigned int cmd;
...@@ -238,6 +244,8 @@ static void dc21285_parity_irq(int irq, void *dev_id, struct pt_regs *regs) ...@@ -238,6 +244,8 @@ static void dc21285_parity_irq(int irq, void *dev_id, struct pt_regs *regs)
disable_irq(irq); disable_irq(irq);
timer->expires = jiffies + HZ; timer->expires = jiffies + HZ;
add_timer(timer); add_timer(timer);
return IRQ_HANDLED;
} }
int __init dc21285_setup(int nr, struct pci_sys_data *sys) int __init dc21285_setup(int nr, struct pci_sys_data *sys)
......
...@@ -43,8 +43,6 @@ ...@@ -43,8 +43,6 @@
* f1500000 15000000 RTC * f1500000 15000000 RTC
* f1600000 16000000 UART 0 * f1600000 16000000 UART 0
* f1700000 17000000 UART 1 * f1700000 17000000 UART 1
* f1800000 18000000 Keyboard
* f1900000 19000000 Mouse
* f1a00000 1a000000 Debug LEDs * f1a00000 1a000000 Debug LEDs
* f1b00000 1b000000 GPIO * f1b00000 1b000000 GPIO
*/ */
...@@ -58,8 +56,6 @@ static struct map_desc integrator_io_desc[] __initdata = { ...@@ -58,8 +56,6 @@ static struct map_desc integrator_io_desc[] __initdata = {
{ IO_ADDRESS(INTEGRATOR_RTC_BASE), INTEGRATOR_RTC_BASE, SZ_4K, MT_DEVICE }, { IO_ADDRESS(INTEGRATOR_RTC_BASE), INTEGRATOR_RTC_BASE, SZ_4K, MT_DEVICE },
{ IO_ADDRESS(INTEGRATOR_UART0_BASE), INTEGRATOR_UART0_BASE, SZ_4K, MT_DEVICE }, { IO_ADDRESS(INTEGRATOR_UART0_BASE), INTEGRATOR_UART0_BASE, SZ_4K, MT_DEVICE },
{ IO_ADDRESS(INTEGRATOR_UART1_BASE), INTEGRATOR_UART1_BASE, SZ_4K, MT_DEVICE }, { IO_ADDRESS(INTEGRATOR_UART1_BASE), INTEGRATOR_UART1_BASE, SZ_4K, MT_DEVICE },
{ IO_ADDRESS(INTEGRATOR_KBD_BASE), INTEGRATOR_KBD_BASE, SZ_4K, MT_DEVICE },
{ IO_ADDRESS(INTEGRATOR_MOUSE_BASE), INTEGRATOR_MOUSE_BASE, SZ_4K, MT_DEVICE },
{ IO_ADDRESS(INTEGRATOR_DBG_BASE), INTEGRATOR_DBG_BASE, SZ_4K, MT_DEVICE }, { IO_ADDRESS(INTEGRATOR_DBG_BASE), INTEGRATOR_DBG_BASE, SZ_4K, MT_DEVICE },
{ IO_ADDRESS(INTEGRATOR_GPIO_BASE), INTEGRATOR_GPIO_BASE, SZ_4K, MT_DEVICE }, { IO_ADDRESS(INTEGRATOR_GPIO_BASE), INTEGRATOR_GPIO_BASE, SZ_4K, MT_DEVICE },
{ PCI_MEMORY_VADDR, PHYS_PCI_MEM_BASE, SZ_16M, MT_DEVICE }, { PCI_MEMORY_VADDR, PHYS_PCI_MEM_BASE, SZ_16M, MT_DEVICE },
......
...@@ -50,9 +50,9 @@ static struct irqchip pxa_internal_chip = { ...@@ -50,9 +50,9 @@ static struct irqchip pxa_internal_chip = {
* Use this instead of directly setting GRER/GFER. * Use this instead of directly setting GRER/GFER.
*/ */
static int GPIO_IRQ_rising_edge[3]; static long GPIO_IRQ_rising_edge[3];
static int GPIO_IRQ_falling_edge[3]; static long GPIO_IRQ_falling_edge[3];
static int GPIO_IRQ_mask[3]; static long GPIO_IRQ_mask[3];
static int pxa_gpio_irq_type(unsigned int irq, unsigned int type) static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
{ {
...@@ -189,7 +189,6 @@ static struct irqchip pxa_muxed_gpio_chip = { ...@@ -189,7 +189,6 @@ static struct irqchip pxa_muxed_gpio_chip = {
.ack = pxa_ack_muxed_gpio, .ack = pxa_ack_muxed_gpio,
.mask = pxa_mask_muxed_gpio, .mask = pxa_mask_muxed_gpio,
.unmask = pxa_unmask_muxed_gpio, .unmask = pxa_unmask_muxed_gpio,
.rerun = pxa_manual_rerun,
.type = pxa_gpio_irq_type, .type = pxa_gpio_irq_type,
}; };
...@@ -217,21 +216,18 @@ void __init pxa_init_irq(void) ...@@ -217,21 +216,18 @@ void __init pxa_init_irq(void)
/* GPIO 0 and 1 must have their mask bit always set */ /* GPIO 0 and 1 must have their mask bit always set */
GPIO_IRQ_mask[0] = 3; GPIO_IRQ_mask[0] = 3;
for (irq = PXA_IRQ(PXA_IRQ_SKIP); irq <= PXA_IRQ(31); irq++) {
set_irq_chip(irq, &pxa_internal_chip);
set_irq_handler(irq, do_level_IRQ);
set_irq_flags(irq, IRQF_VALID);
}
for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) { for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) {
set_irq_chip(irq, &pxa_low_gpio_chip); set_irq_chip(irq, &pxa_low_gpio_chip);
set_irq_handler(irq, do_edge_IRQ); set_irq_handler(irq, do_edge_IRQ);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
} }
for (irq = PXA_IRQ(11); irq <= PXA_IRQ(31); irq++) {
set_irq_chip(irq, &pxa_internal_chip);
set_irq_handler(irq, do_level_IRQ);
set_irq_flags(irq, IRQF_VALID);
}
/* Those are reserved */
set_irq_flags(PXA_IRQ(15), 0);
set_irq_flags(PXA_IRQ(16), 0);
for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(80); irq++) { for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(80); irq++) {
set_irq_chip(irq, &pxa_muxed_gpio_chip); set_irq_chip(irq, &pxa_muxed_gpio_chip);
set_irq_handler(irq, do_edge_IRQ); set_irq_handler(irq, do_edge_IRQ);
......
...@@ -33,57 +33,41 @@ ...@@ -33,57 +33,41 @@
#include "generic.h" #include "generic.h"
static void lubbock_ack_irq(unsigned int irq)
{ static unsigned long lubbock_irq_enabled;
int lubbock_irq = (irq - LUBBOCK_IRQ(0));
LUB_IRQ_SET_CLR &= ~(1 << lubbock_irq);
}
static void lubbock_mask_irq(unsigned int irq) static void lubbock_mask_irq(unsigned int irq)
{ {
int lubbock_irq = (irq - LUBBOCK_IRQ(0)); int lubbock_irq = (irq - LUBBOCK_IRQ(0));
LUB_IRQ_MASK_EN &= ~(1 << lubbock_irq); LUB_IRQ_MASK_EN = (lubbock_irq_enabled &= ~(1 << lubbock_irq));
} }
static void lubbock_unmask_irq(unsigned int irq) static void lubbock_unmask_irq(unsigned int irq)
{ {
int lubbock_irq = (irq - LUBBOCK_IRQ(0)); int lubbock_irq = (irq - LUBBOCK_IRQ(0));
LUB_IRQ_MASK_EN |= (1 << lubbock_irq); /* the irq can be acknowledged only if deasserted, so it's done here */
LUB_IRQ_SET_CLR &= ~(1 << lubbock_irq);
LUB_IRQ_MASK_EN = (lubbock_irq_enabled |= (1 << lubbock_irq));
} }
static struct irqchip lubbock_irq_chip = { static struct irqchip lubbock_irq_chip = {
.ack = lubbock_ack_irq, .ack = lubbock_mask_irq,
.mask = lubbock_mask_irq, .mask = lubbock_mask_irq,
.unmask = lubbock_unmask_irq, .unmask = lubbock_unmask_irq,
}; };
void lubbock_irq_handler(unsigned int irq, struct irqdesc *desc, static void lubbock_irq_handler(unsigned int irq, struct irqdesc *desc,
struct pt_regs *regs) struct pt_regs *regs)
{ {
unsigned int enabled, pending; unsigned long pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled;
/* get active pending irq mask */
enabled = LUB_IRQ_MASK_EN & 0x003f;
pending = LUB_IRQ_SET_CLR & enabled;
do { do {
//printk("%s a: set_clr %#x, mask_en %#x LR/DR %d/%d\n", __FUNCTION__, LUB_IRQ_SET_CLR, LUB_IRQ_MASK_EN, GPLR(0)&1, GEDR(0)&1 ); GEDR(0) = GPIO_bit(0); /* clear our parent irq */
/* clear our parent irq */ if (likely(pending)) {
GEDR(0) = GPIO_bit(0); irq = LUBBOCK_IRQ(0) + __ffs(pending);
desc = irq_desc + irq;
/* process them */ desc->handle(irq, desc, regs);
irq = LUBBOCK_IRQ(0); }
desc = irq_desc + irq; pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled;
do {
if (pending & 1)
desc->handle(irq, desc, regs);
irq++;
desc++;
pending >>= 1;
} while (pending);
//printk("%s b: set_clr %#x, mask_en %#x LR/DR %d/%d\n", __FUNCTION__, LUB_IRQ_SET_CLR, LUB_IRQ_MASK_EN, GPLR(0)&1, GEDR(0)&1 );
enabled = LUB_IRQ_MASK_EN & 0x003f;
pending = LUB_IRQ_SET_CLR & enabled;
} while (pending); } while (pending);
} }
......
...@@ -83,7 +83,7 @@ static void iomd_get_next_sg(struct scatterlist *sg, dma_t *dma) ...@@ -83,7 +83,7 @@ static void iomd_get_next_sg(struct scatterlist *sg, dma_t *dma)
sg->length |= flags; sg->length |= flags;
} }
static void iomd_dma_handle(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t iomd_dma_handle(int irq, void *dev_id, struct pt_regs *regs)
{ {
dma_t *dma = (dma_t *)dev_id; dma_t *dma = (dma_t *)dev_id;
unsigned long base = dma->dma_base; unsigned long base = dma->dma_base;
...@@ -93,7 +93,7 @@ static void iomd_dma_handle(int irq, void *dev_id, struct pt_regs *regs) ...@@ -93,7 +93,7 @@ static void iomd_dma_handle(int irq, void *dev_id, struct pt_regs *regs)
status = iomd_readb(base + ST); status = iomd_readb(base + ST);
if (!(status & DMA_ST_INT)) if (!(status & DMA_ST_INT))
return; return IRQ_HANDLED;
if (status & DMA_ST_OFL && !dma->sg) if (status & DMA_ST_OFL && !dma->sg)
break; break;
...@@ -117,6 +117,8 @@ static void iomd_dma_handle(int irq, void *dev_id, struct pt_regs *regs) ...@@ -117,6 +117,8 @@ static void iomd_dma_handle(int irq, void *dev_id, struct pt_regs *regs)
iomd_writeb(0, dma->dma_base + CR); iomd_writeb(0, dma->dma_base + CR);
disable_irq(irq); disable_irq(irq);
return IRQ_HANDLED;
} }
static int iomd_request_dma(dmach_t channel, dma_t *dma) static int iomd_request_dma(dmach_t channel, dma_t *dma)
......
...@@ -330,7 +330,7 @@ static int __init consistent_init(void) ...@@ -330,7 +330,7 @@ static int __init consistent_init(void)
core_initcall(consistent_init); core_initcall(consistent_init);
/* /*
* make an area consistent for devices. * Make an area consistent for devices.
*/ */
void consistent_sync(void *vaddr, size_t size, int direction) void consistent_sync(void *vaddr, size_t size, int direction)
{ {
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
# To add an entry into this database, please see Documentation/arm/README, # To add an entry into this database, please see Documentation/arm/README,
# or contact rmk@arm.linux.org.uk # or contact rmk@arm.linux.org.uk
# #
# Last update: Sat Apr 26 11:41:41 2003 # Last update: Wed May 7 23:43:08 2003
# #
# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
# #
...@@ -328,3 +328,14 @@ m7100 SA1100_M7100 M7100 316 ...@@ -328,3 +328,14 @@ m7100 SA1100_M7100 M7100 316
nipc2 ARCH_NIPC2 NIPC2 317 nipc2 ARCH_NIPC2 NIPC2 317
fu7202 ARCH_FU7202 FU7202 318 fu7202 ARCH_FU7202 FU7202 318
adsagx ARCH_ADSAGX ADSAGX 319 adsagx ARCH_ADSAGX ADSAGX 319
pxa_pooh ARCH_PXA_POOH PXA_POOH 320
bandon ARCH_BANDON BANDON 321
pcm7210 ARCH_PCM7210 PCM7210 322
nms9200 ARCH_NMS9200 NMS9200 323
gealog ARCH_GEALOG GEALOG 324
m7140 SA1100_M7140 M7140 325
korebot ARCH_KOREBOT KOREBOT 326
iq31244 ARCH_IQ31244 IQ31244 327
koan393 SA1100_KOAN393 KOAN393 328
inhandftip3 ARCH_INHANDFTIP3 INHANDFTIP3 329
gonzo ARCH_GONZO GONZO 330
...@@ -68,7 +68,7 @@ static unsigned int net_debug = NET_DEBUG; ...@@ -68,7 +68,7 @@ static unsigned int net_debug = NET_DEBUG;
static int ether1_open(struct net_device *dev); static int ether1_open(struct net_device *dev);
static int ether1_sendpacket(struct sk_buff *skb, struct net_device *dev); static int ether1_sendpacket(struct sk_buff *skb, struct net_device *dev);
static void ether1_interrupt(int irq, void *dev_id, struct pt_regs *regs); static irqreturn_t ether1_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static int ether1_close(struct net_device *dev); static int ether1_close(struct net_device *dev);
static struct net_device_stats *ether1_getstats(struct net_device *dev); static struct net_device_stats *ether1_getstats(struct net_device *dev);
static void ether1_setmulticastlist(struct net_device *dev); static void ether1_setmulticastlist(struct net_device *dev);
...@@ -908,7 +908,7 @@ ether1_recv_done (struct net_device *dev) ...@@ -908,7 +908,7 @@ ether1_recv_done (struct net_device *dev)
} while (1); } while (1);
} }
static void static irqreturn_t
ether1_interrupt (int irq, void *dev_id, struct pt_regs *regs) ether1_interrupt (int irq, void *dev_id, struct pt_regs *regs)
{ {
struct net_device *dev = (struct net_device *)dev_id; struct net_device *dev = (struct net_device *)dev_id;
...@@ -953,7 +953,9 @@ ether1_interrupt (int irq, void *dev_id, struct pt_regs *regs) ...@@ -953,7 +953,9 @@ ether1_interrupt (int irq, void *dev_id, struct pt_regs *regs)
NORMALIRQS)); NORMALIRQS));
} }
} else } else
outb (CTRL_ACK, REG_CONTROL); outb (CTRL_ACK, REG_CONTROL);
return IRQ_HANDLED;
} }
static int static int
......
...@@ -82,7 +82,7 @@ static int ether3_rx(struct net_device *dev, struct dev_priv *priv, unsigned int ...@@ -82,7 +82,7 @@ static int ether3_rx(struct net_device *dev, struct dev_priv *priv, unsigned int
static void ether3_tx(struct net_device *dev, struct dev_priv *priv); static void ether3_tx(struct net_device *dev, struct dev_priv *priv);
static int ether3_open (struct net_device *dev); static int ether3_open (struct net_device *dev);
static int ether3_sendpacket (struct sk_buff *skb, struct net_device *dev); static int ether3_sendpacket (struct sk_buff *skb, struct net_device *dev);
static void ether3_interrupt (int irq, void *dev_id, struct pt_regs *regs); static irqreturn_t ether3_interrupt (int irq, void *dev_id, struct pt_regs *regs);
static int ether3_close (struct net_device *dev); static int ether3_close (struct net_device *dev);
static struct net_device_stats *ether3_getstats (struct net_device *dev); static struct net_device_stats *ether3_getstats (struct net_device *dev);
static void ether3_setmulticastlist (struct net_device *dev); static void ether3_setmulticastlist (struct net_device *dev);
...@@ -576,12 +576,12 @@ ether3_sendpacket(struct sk_buff *skb, struct net_device *dev) ...@@ -576,12 +576,12 @@ ether3_sendpacket(struct sk_buff *skb, struct net_device *dev)
return 0; return 0;
} }
static void static irqreturn_t
ether3_interrupt(int irq, void *dev_id, struct pt_regs *regs) ether3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct net_device *dev = (struct net_device *)dev_id; struct net_device *dev = (struct net_device *)dev_id;
struct dev_priv *priv; struct dev_priv *priv;
unsigned int status; unsigned int status, handled = IRQ_NONE;
#if NET_DEBUG > 1 #if NET_DEBUG > 1
if(net_debug & DEBUG_INT) if(net_debug & DEBUG_INT)
...@@ -595,17 +595,20 @@ ether3_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -595,17 +595,20 @@ ether3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (status & STAT_INTRX) { if (status & STAT_INTRX) {
ether3_outw(CMD_ACKINTRX | priv->regs.command, REG_COMMAND); ether3_outw(CMD_ACKINTRX | priv->regs.command, REG_COMMAND);
ether3_rx(dev, priv, 12); ether3_rx(dev, priv, 12);
handled = IRQ_HANDLED;
} }
if (status & STAT_INTTX) { if (status & STAT_INTTX) {
ether3_outw(CMD_ACKINTTX | priv->regs.command, REG_COMMAND); ether3_outw(CMD_ACKINTTX | priv->regs.command, REG_COMMAND);
ether3_tx(dev, priv); ether3_tx(dev, priv);
handled = IRQ_HANDLED;
} }
#if NET_DEBUG > 1 #if NET_DEBUG > 1
if(net_debug & DEBUG_INT) if(net_debug & DEBUG_INT)
printk("done\n"); printk("done\n");
#endif #endif
return handled;
} }
/* /*
......
...@@ -2466,18 +2466,14 @@ intr_ret_t acornscsi_sbicintr(AS_Host *host, int in_irq) ...@@ -2466,18 +2466,14 @@ intr_ret_t acornscsi_sbicintr(AS_Host *host, int in_irq)
* dev_id - device specific data (AS_Host structure) * dev_id - device specific data (AS_Host structure)
* regs - processor registers when interrupt occurred * regs - processor registers when interrupt occurred
*/ */
static static irqreturn_t
void acornscsi_intr(int irq, void *dev_id, struct pt_regs *regs) acornscsi_intr(int irq, void *dev_id, struct pt_regs *regs)
{ {
AS_Host *host = (AS_Host *)dev_id; AS_Host *host = (AS_Host *)dev_id;
intr_ret_t ret; intr_ret_t ret;
int iostatus; int iostatus;
int in_irq = 0; int in_irq = 0;
if (host->scsi.interrupt)
printk("scsi%d: interrupt re-entered\n", host->host->host_no);
host->scsi.interrupt = 1;
do { do {
ret = INTR_IDLE; ret = INTR_IDLE;
...@@ -2505,7 +2501,7 @@ void acornscsi_intr(int irq, void *dev_id, struct pt_regs *regs) ...@@ -2505,7 +2501,7 @@ void acornscsi_intr(int irq, void *dev_id, struct pt_regs *regs)
in_irq = 1; in_irq = 1;
} while (ret != INTR_IDLE); } while (ret != INTR_IDLE);
host->scsi.interrupt = 0; return IRQ_HANDLED;
} }
/*============================================================================================= /*=============================================================================================
......
...@@ -141,12 +141,12 @@ cumanascsi_2_terminator_ctl(struct Scsi_Host *host, int on_off) ...@@ -141,12 +141,12 @@ cumanascsi_2_terminator_ctl(struct Scsi_Host *host, int on_off)
* dev_id - user-defined (Scsi_Host structure) * dev_id - user-defined (Scsi_Host structure)
* regs - processor registers at interrupt * regs - processor registers at interrupt
*/ */
static void static irqreturn_t
cumanascsi_2_intr(int irq, void *dev_id, struct pt_regs *regs) cumanascsi_2_intr(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct cumanascsi2_info *info = dev_id; struct cumanascsi2_info *info = dev_id;
fas216_intr(&info->info); return fas216_intr(&info->info);
} }
/* Prototype: fasdmatype_t cumanascsi_2_dma_setup(host, SCpnt, direction, min_type) /* Prototype: fasdmatype_t cumanascsi_2_dma_setup(host, SCpnt, direction, min_type)
......
...@@ -141,12 +141,12 @@ eesoxscsi_terminator_ctl(struct Scsi_Host *host, int on_off) ...@@ -141,12 +141,12 @@ eesoxscsi_terminator_ctl(struct Scsi_Host *host, int on_off)
* dev_id - user-defined (Scsi_Host structure) * dev_id - user-defined (Scsi_Host structure)
* regs - processor registers at interrupt * regs - processor registers at interrupt
*/ */
static void static irqreturn_t
eesoxscsi_intr(int irq, void *dev_id, struct pt_regs *regs) eesoxscsi_intr(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct eesoxscsi_info *info = dev_id; struct eesoxscsi_info *info = dev_id;
fas216_intr(&info->info); return fas216_intr(&info->info);
} }
/* Prototype: fasdmatype_t eesoxscsi_dma_setup(host, SCpnt, direction, min_type) /* Prototype: fasdmatype_t eesoxscsi_dma_setup(host, SCpnt, direction, min_type)
......
...@@ -1824,9 +1824,10 @@ static void fas216_bus_reset(FAS216_Info *info) ...@@ -1824,9 +1824,10 @@ static void fas216_bus_reset(FAS216_Info *info)
* *
* Handle interrupts from the interface to progress a command * Handle interrupts from the interface to progress a command
*/ */
void fas216_intr(FAS216_Info *info) irqreturn_t fas216_intr(FAS216_Info *info)
{ {
unsigned char isr, ssr, stat; unsigned char isr, ssr, stat;
int handled = IRQ_NONE;
fas216_checkmagic(info); fas216_checkmagic(info);
...@@ -1857,7 +1858,9 @@ void fas216_intr(FAS216_Info *info) ...@@ -1857,7 +1858,9 @@ void fas216_intr(FAS216_Info *info)
fas216_log(info, 0, "unknown interrupt received:" fas216_log(info, 0, "unknown interrupt received:"
" phase %s isr %02X ssr %02X stat %02X", " phase %s isr %02X ssr %02X stat %02X",
fas216_drv_phase(info), isr, ssr, stat); fas216_drv_phase(info), isr, ssr, stat);
handled = IRQ_HANDLED;
} }
return handled;
} }
static void __fas216_start_command(FAS216_Info *info, Scsi_Cmnd *SCpnt) static void __fas216_start_command(FAS216_Info *info, Scsi_Cmnd *SCpnt)
......
...@@ -351,11 +351,11 @@ extern int fas216_queue_command (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); ...@@ -351,11 +351,11 @@ extern int fas216_queue_command (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
*/ */
extern int fas216_command (Scsi_Cmnd *); extern int fas216_command (Scsi_Cmnd *);
/* Function: void fas216_intr (FAS216_Info *info) /* Function: irqreturn_t fas216_intr (FAS216_Info *info)
* Purpose : handle interrupts from the interface to progress a command * Purpose : handle interrupts from the interface to progress a command
* Params : info - interface to service * Params : info - interface to service
*/ */
extern void fas216_intr (FAS216_Info *info); extern irqreturn_t fas216_intr (FAS216_Info *info);
extern void fas216_remove (struct Scsi_Host *instance); extern void fas216_remove (struct Scsi_Host *instance);
......
...@@ -113,12 +113,12 @@ powertecscsi_terminator_ctl(struct Scsi_Host *host, int on_off) ...@@ -113,12 +113,12 @@ powertecscsi_terminator_ctl(struct Scsi_Host *host, int on_off)
* dev_id - user-defined (Scsi_Host structure) * dev_id - user-defined (Scsi_Host structure)
* regs - processor registers at interrupt * regs - processor registers at interrupt
*/ */
static void static irqreturn_t
powertecscsi_intr(int irq, void *dev_id, struct pt_regs *regs) powertecscsi_intr(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct powertec_info *info = dev_id; struct powertec_info *info = dev_id;
fas216_intr(&info->info); return fas216_intr(&info->info);
} }
/* Prototype: fasdmatype_t powertecscsi_dma_setup(host, SCpnt, direction, min_type) /* Prototype: fasdmatype_t powertecscsi_dma_setup(host, SCpnt, direction, min_type)
......
...@@ -1616,7 +1616,8 @@ static int __make_request(request_queue_t *q, struct bio *bio) ...@@ -1616,7 +1616,8 @@ static int __make_request(request_queue_t *q, struct bio *bio)
sector = bio->bi_sector; sector = bio->bi_sector;
nr_sectors = bio_sectors(bio); nr_sectors = bio_sectors(bio);
cur_nr_sectors = bio_iovec(bio)->bv_len >> 9; cur_nr_sectors = bio_cur_sectors(bio);
rw = bio_data_dir(bio); rw = bio_data_dir(bio);
/* /*
...@@ -1672,7 +1673,10 @@ static int __make_request(request_queue_t *q, struct bio *bio) ...@@ -1672,7 +1673,10 @@ static int __make_request(request_queue_t *q, struct bio *bio)
} }
bio->bi_next = req->bio; bio->bi_next = req->bio;
req->bio = bio; req->cbio = req->bio = bio;
req->nr_cbio_segments = bio_segments(bio);
req->nr_cbio_sectors = bio_sectors(bio);
/* /*
* may not be valid. if the low level driver said * may not be valid. if the low level driver said
* it didn't need a bounce buffer then it better * it didn't need a bounce buffer then it better
...@@ -1740,9 +1744,11 @@ static int __make_request(request_queue_t *q, struct bio *bio) ...@@ -1740,9 +1744,11 @@ static int __make_request(request_queue_t *q, struct bio *bio)
req->current_nr_sectors = req->hard_cur_sectors = cur_nr_sectors; req->current_nr_sectors = req->hard_cur_sectors = cur_nr_sectors;
req->nr_phys_segments = bio_phys_segments(q, bio); req->nr_phys_segments = bio_phys_segments(q, bio);
req->nr_hw_segments = bio_hw_segments(q, bio); req->nr_hw_segments = bio_hw_segments(q, bio);
req->nr_cbio_segments = bio_segments(bio);
req->nr_cbio_sectors = bio_sectors(bio);
req->buffer = bio_data(bio); /* see ->buffer comment above */ req->buffer = bio_data(bio); /* see ->buffer comment above */
req->waiting = NULL; req->waiting = NULL;
req->bio = req->biotail = bio; req->cbio = req->bio = req->biotail = bio;
req->rq_disk = bio->bi_bdev->bd_disk; req->rq_disk = bio->bi_bdev->bd_disk;
req->start_time = jiffies; req->start_time = jiffies;
...@@ -1914,6 +1920,81 @@ int submit_bio(int rw, struct bio *bio) ...@@ -1914,6 +1920,81 @@ int submit_bio(int rw, struct bio *bio)
return 1; return 1;
} }
/**
* blk_rq_next_segment
* @rq: the request being processed
*
* Description:
* Points to the next segment in the request if the current segment
* is complete. Leaves things unchanged if this segment is not over
* or if no more segments are left in this request.
*
* Meant to be used for bio traversal during I/O submission
* Does not affect any I/O completions or update completion state
* in the request, and does not modify any bio fields.
*
* Decrementing rq->nr_sectors, rq->current_nr_sectors and
* rq->nr_cbio_sectors as data is transferred is the caller's
* responsibility and should be done before calling this routine.
**/
void blk_rq_next_segment(struct request *rq)
{
if (rq->current_nr_sectors > 0)
return;
if (rq->nr_cbio_sectors > 0) {
--rq->nr_cbio_segments;
rq->current_nr_sectors = blk_rq_vec(rq)->bv_len >> 9;
} else {
if ((rq->cbio = rq->cbio->bi_next)) {
rq->nr_cbio_segments = bio_segments(rq->cbio);
rq->nr_cbio_sectors = bio_sectors(rq->cbio);
rq->current_nr_sectors = bio_cur_sectors(rq->cbio);
}
}
/* remember the size of this segment before we start I/O */
rq->hard_cur_sectors = rq->current_nr_sectors;
}
/**
* process_that_request_first - process partial request submission
* @req: the request being processed
* @nr_sectors: number of sectors I/O has been submitted on
*
* Description:
* May be used for processing bio's while submitting I/O without
* signalling completion. Fails if more data is requested than is
* available in the request in which case it doesn't advance any
* pointers.
*
* Assumes a request is correctly set up. No sanity checks.
*
* Return:
* 0 - no more data left to submit (not processed)
* 1 - data available to submit for this request (processed)
**/
int process_that_request_first(struct request *req, unsigned int nr_sectors)
{
unsigned int nsect;
if (req->nr_sectors < nr_sectors)
return 0;
req->nr_sectors -= nr_sectors;
req->sector += nr_sectors;
while (nr_sectors) {
nsect = min_t(unsigned, req->current_nr_sectors, nr_sectors);
req->current_nr_sectors -= nsect;
nr_sectors -= nsect;
if (req->cbio) {
req->nr_cbio_sectors -= nsect;
blk_rq_next_segment(req);
}
}
return 1;
}
void blk_recalc_rq_segments(struct request *rq) void blk_recalc_rq_segments(struct request *rq)
{ {
struct bio *bio; struct bio *bio;
...@@ -1922,8 +2003,6 @@ void blk_recalc_rq_segments(struct request *rq) ...@@ -1922,8 +2003,6 @@ void blk_recalc_rq_segments(struct request *rq)
if (!rq->bio) if (!rq->bio)
return; return;
rq->buffer = bio_data(rq->bio);
nr_phys_segs = nr_hw_segs = 0; nr_phys_segs = nr_hw_segs = 0;
rq_for_each_bio(bio, rq) { rq_for_each_bio(bio, rq) {
/* Force bio hw/phys segs to be recalculated. */ /* Force bio hw/phys segs to be recalculated. */
...@@ -1941,11 +2020,24 @@ void blk_recalc_rq_sectors(struct request *rq, int nsect) ...@@ -1941,11 +2020,24 @@ void blk_recalc_rq_sectors(struct request *rq, int nsect)
{ {
if (blk_fs_request(rq)) { if (blk_fs_request(rq)) {
rq->hard_sector += nsect; rq->hard_sector += nsect;
rq->nr_sectors = rq->hard_nr_sectors -= nsect; rq->hard_nr_sectors -= nsect;
rq->sector = rq->hard_sector;
rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9; /*
rq->hard_cur_sectors = rq->current_nr_sectors; * Move the I/O submission pointers ahead if required,
* i.e. for drivers not aware of rq->cbio.
*/
if ((rq->nr_sectors >= rq->hard_nr_sectors) &&
(rq->sector <= rq->hard_sector)) {
rq->sector = rq->hard_sector;
rq->nr_sectors = rq->hard_nr_sectors;
rq->hard_cur_sectors = bio_cur_sectors(rq->bio);
rq->current_nr_sectors = rq->hard_cur_sectors;
rq->nr_cbio_segments = bio_segments(rq->bio);
rq->nr_cbio_sectors = bio_sectors(rq->bio);
rq->buffer = bio_data(rq->bio);
rq->cbio = rq->bio;
}
/* /*
* if total number of sectors is less than the first segment * if total number of sectors is less than the first segment
...@@ -2139,9 +2231,27 @@ void blk_rq_bio_prep(request_queue_t *q, struct request *rq, struct bio *bio) ...@@ -2139,9 +2231,27 @@ void blk_rq_bio_prep(request_queue_t *q, struct request *rq, struct bio *bio)
rq->current_nr_sectors = bio_cur_sectors(bio); rq->current_nr_sectors = bio_cur_sectors(bio);
rq->hard_cur_sectors = rq->current_nr_sectors; rq->hard_cur_sectors = rq->current_nr_sectors;
rq->hard_nr_sectors = rq->nr_sectors = bio_sectors(bio); rq->hard_nr_sectors = rq->nr_sectors = bio_sectors(bio);
rq->nr_cbio_segments = bio_segments(bio);
rq->nr_cbio_sectors = bio_sectors(bio);
rq->buffer = bio_data(bio); rq->buffer = bio_data(bio);
rq->bio = rq->biotail = bio; rq->cbio = rq->bio = rq->biotail = bio;
}
void blk_rq_prep_restart(struct request *rq)
{
struct bio *bio;
bio = rq->cbio = rq->bio;
if (bio) {
rq->nr_cbio_segments = bio_segments(bio);
rq->nr_cbio_sectors = bio_sectors(bio);
rq->hard_cur_sectors = bio_cur_sectors(bio);
rq->buffer = bio_data(bio);
}
rq->sector = rq->hard_sector;
rq->nr_sectors = rq->hard_nr_sectors;
rq->current_nr_sectors = rq->hard_cur_sectors;
} }
int __init blk_dev_init(void) int __init blk_dev_init(void)
...@@ -2169,6 +2279,7 @@ int __init blk_dev_init(void) ...@@ -2169,6 +2279,7 @@ int __init blk_dev_init(void)
return 0; return 0;
}; };
EXPORT_SYMBOL(process_that_request_first);
EXPORT_SYMBOL(end_that_request_first); EXPORT_SYMBOL(end_that_request_first);
EXPORT_SYMBOL(end_that_request_chunk); EXPORT_SYMBOL(end_that_request_chunk);
EXPORT_SYMBOL(end_that_request_last); EXPORT_SYMBOL(end_that_request_last);
......
...@@ -212,7 +212,7 @@ static int sg_io(request_queue_t *q, struct block_device *bdev, ...@@ -212,7 +212,7 @@ static int sg_io(request_queue_t *q, struct block_device *bdev,
} }
} }
rq = blk_get_request(q, WRITE, __GFP_WAIT); rq = blk_get_request(q, writing ? WRITE : READ, __GFP_WAIT);
/* /*
* fill in request structure * fill in request structure
...@@ -227,8 +227,6 @@ static int sg_io(request_queue_t *q, struct block_device *bdev, ...@@ -227,8 +227,6 @@ static int sg_io(request_queue_t *q, struct block_device *bdev,
rq->sense_len = 0; rq->sense_len = 0;
rq->flags |= REQ_BLOCK_PC; rq->flags |= REQ_BLOCK_PC;
if (writing)
rq->flags |= REQ_RW;
rq->hard_nr_sectors = rq->nr_sectors = nr_sectors; rq->hard_nr_sectors = rq->nr_sectors = nr_sectors;
rq->hard_cur_sectors = rq->current_nr_sectors = nr_sectors; rq->hard_cur_sectors = rq->current_nr_sectors = nr_sectors;
...@@ -329,7 +327,7 @@ static int sg_scsi_ioctl(request_queue_t *q, struct block_device *bdev, ...@@ -329,7 +327,7 @@ static int sg_scsi_ioctl(request_queue_t *q, struct block_device *bdev,
memset(buffer, 0, bytes); memset(buffer, 0, bytes);
} }
rq = blk_get_request(q, WRITE, __GFP_WAIT); rq = blk_get_request(q, in_len ? WRITE : READ, __GFP_WAIT);
cmdlen = COMMAND_SIZE(opcode); cmdlen = COMMAND_SIZE(opcode);
...@@ -373,8 +371,6 @@ static int sg_scsi_ioctl(request_queue_t *q, struct block_device *bdev, ...@@ -373,8 +371,6 @@ static int sg_scsi_ioctl(request_queue_t *q, struct block_device *bdev,
rq->data = buffer; rq->data = buffer;
rq->data_len = bytes; rq->data_len = bytes;
rq->flags |= REQ_BLOCK_PC; rq->flags |= REQ_BLOCK_PC;
if (in_len)
rq->flags |= REQ_RW;
blk_do_rq(q, bdev, rq); blk_do_rq(q, bdev, rq);
err = rq->errors & 0xff; /* only 8 bit SCSI status */ err = rq->errors & 0xff; /* only 8 bit SCSI status */
......
...@@ -146,7 +146,7 @@ static void button_sequence_finished (unsigned long parameters) ...@@ -146,7 +146,7 @@ static void button_sequence_finished (unsigned long parameters)
* increments the counter. * increments the counter.
*/ */
static void button_handler (int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t button_handler (int irq, void *dev_id, struct pt_regs *regs)
{ {
if (button_press_count) { if (button_press_count) {
del_timer (&button_timer); del_timer (&button_timer);
...@@ -156,6 +156,8 @@ static void button_handler (int irq, void *dev_id, struct pt_regs *regs) ...@@ -156,6 +156,8 @@ static void button_handler (int irq, void *dev_id, struct pt_regs *regs)
button_timer.function = button_sequence_finished; button_timer.function = button_sequence_finished;
button_timer.expires = (jiffies + bdelay); button_timer.expires = (jiffies + bdelay);
add_timer (&button_timer); add_timer (&button_timer);
return IRQ_HANDLED;
} }
/* /*
......
...@@ -2070,6 +2070,7 @@ static int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense) ...@@ -2070,6 +2070,7 @@ static int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
req.sense = sense; req.sense = sense;
req.cmd[0] = GPCMD_TEST_UNIT_READY; req.cmd[0] = GPCMD_TEST_UNIT_READY;
req.flags |= REQ_QUIET;
#if ! STANDARD_ATAPI #if ! STANDARD_ATAPI
/* the Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to /* the Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to
......
...@@ -1479,7 +1479,7 @@ static int probe_lba_addressing (ide_drive_t *drive, int arg) ...@@ -1479,7 +1479,7 @@ static int probe_lba_addressing (ide_drive_t *drive, int arg)
static int set_lba_addressing (ide_drive_t *drive, int arg) static int set_lba_addressing (ide_drive_t *drive, int arg)
{ {
return (probe_lba_addressing(drive, arg)); return probe_lba_addressing(drive, arg);
} }
static void idedisk_add_settings(ide_drive_t *drive) static void idedisk_add_settings(ide_drive_t *drive)
...@@ -1566,6 +1566,18 @@ static void idedisk_setup (ide_drive_t *drive) ...@@ -1566,6 +1566,18 @@ static void idedisk_setup (ide_drive_t *drive)
(void) probe_lba_addressing(drive, 1); (void) probe_lba_addressing(drive, 1);
if (drive->addressing == 1) {
ide_hwif_t *hwif = HWIF(drive);
int max_s = 2048;
if (max_s > hwif->rqsize)
max_s = hwif->rqsize;
blk_queue_max_sectors(&drive->queue, max_s);
}
printk("%s: max request size: %dKiB\n", drive->name, drive->queue.max_sectors / 2);
/* Extract geometry if we did not already have one for the drive */ /* Extract geometry if we did not already have one for the drive */
if (!drive->cyl || !drive->head || !drive->sect) { if (!drive->cyl || !drive->head || !drive->sect) {
drive->cyl = drive->bios_cyl = id->cyls; drive->cyl = drive->bios_cyl = id->cyls;
......
...@@ -998,6 +998,7 @@ EXPORT_SYMBOL(save_match); ...@@ -998,6 +998,7 @@ EXPORT_SYMBOL(save_match);
static void ide_init_queue(ide_drive_t *drive) static void ide_init_queue(ide_drive_t *drive)
{ {
request_queue_t *q = &drive->queue; request_queue_t *q = &drive->queue;
ide_hwif_t *hwif = HWIF(drive);
int max_sectors = 256; int max_sectors = 256;
/* /*
...@@ -1013,8 +1014,10 @@ static void ide_init_queue(ide_drive_t *drive) ...@@ -1013,8 +1014,10 @@ static void ide_init_queue(ide_drive_t *drive)
drive->queue_setup = 1; drive->queue_setup = 1;
blk_queue_segment_boundary(q, 0xffff); blk_queue_segment_boundary(q, 0xffff);
if (HWIF(drive)->rqsize) if (!hwif->rqsize)
max_sectors = HWIF(drive)->rqsize; hwif->rqsize = hwif->addressing ? 256 : 65536;
if (hwif->rqsize < max_sectors)
max_sectors = hwif->rqsize;
blk_queue_max_sectors(q, max_sectors); blk_queue_max_sectors(q, max_sectors);
/* IDE DMA can do PRD_ENTRIES number of segments. */ /* IDE DMA can do PRD_ENTRIES number of segments. */
......
...@@ -51,9 +51,58 @@ ...@@ -51,9 +51,58 @@
*/ */
#undef IDE_TCQ_FIDDLE_SI #undef IDE_TCQ_FIDDLE_SI
/*
* bad drive blacklist, for drives that raport tcq capability but don't
* work reliably with the default config. initially from freebsd table.
*/
struct ide_tcq_blacklist {
char *model;
char works;
unsigned int max_sectors;
};
static struct ide_tcq_blacklist ide_tcq_blacklist[] = {
{
.model = "IBM-DTTA",
.works = 1,
.max_sectors = 128,
},
{
.model = "IBM-DJNA",
.works = 0,
},
{
.model = "WDC AC",
.works = 0,
},
{
.model = NULL,
},
};
ide_startstop_t ide_dmaq_intr(ide_drive_t *drive); ide_startstop_t ide_dmaq_intr(ide_drive_t *drive);
ide_startstop_t ide_service(ide_drive_t *drive); ide_startstop_t ide_service(ide_drive_t *drive);
static struct ide_tcq_blacklist *ide_find_drive_blacklist(ide_drive_t *drive)
{
struct ide_tcq_blacklist *itb;
int i = 0;
do {
itb = &ide_tcq_blacklist[i];
if (!itb->model)
break;
if (!strncmp(drive->id->model, itb->model, strlen(itb->model)))
return itb;
i++;
} while (1);
return NULL;
}
static inline void drive_ctl_nien(ide_drive_t *drive, int set) static inline void drive_ctl_nien(ide_drive_t *drive, int set)
{ {
#ifdef IDE_TCQ_NIEN #ifdef IDE_TCQ_NIEN
...@@ -502,7 +551,7 @@ static int ide_tcq_configure(ide_drive_t *drive) ...@@ -502,7 +551,7 @@ static int ide_tcq_configure(ide_drive_t *drive)
return 0; return 0;
err: err:
kfree(args); kfree(args);
return 1; return -EIO;
} }
/* /*
...@@ -511,6 +560,7 @@ static int ide_tcq_configure(ide_drive_t *drive) ...@@ -511,6 +560,7 @@ static int ide_tcq_configure(ide_drive_t *drive)
*/ */
static int ide_enable_queued(ide_drive_t *drive, int on) static int ide_enable_queued(ide_drive_t *drive, int on)
{ {
struct ide_tcq_blacklist *itb;
int depth = drive->using_tcq ? drive->queue_depth : 0; int depth = drive->using_tcq ? drive->queue_depth : 0;
/* /*
...@@ -529,6 +579,17 @@ static int ide_enable_queued(ide_drive_t *drive, int on) ...@@ -529,6 +579,17 @@ static int ide_enable_queued(ide_drive_t *drive, int on)
return 1; return 1;
} }
/*
* some drives need limited transfer size in tcq
*/
itb = ide_find_drive_blacklist(drive);
if (itb && itb->max_sectors) {
if (itb->max_sectors > HWIF(drive)->rqsize)
itb->max_sectors = HWIF(drive)->rqsize;
blk_queue_max_sectors(&drive->queue, itb->max_sectors);
}
/* /*
* enable block tagging * enable block tagging
*/ */
...@@ -582,13 +643,36 @@ int ide_tcq_wait_dataphase(ide_drive_t *drive) ...@@ -582,13 +643,36 @@ int ide_tcq_wait_dataphase(ide_drive_t *drive)
return 0; return 0;
} }
static int ide_tcq_check_blacklist(ide_drive_t *drive)
{
struct ide_tcq_blacklist *itb = ide_find_drive_blacklist(drive);
if (!itb)
return 0;
return !itb->works;
}
int __ide_dma_queued_on(ide_drive_t *drive) int __ide_dma_queued_on(ide_drive_t *drive)
{ {
if (!drive->using_dma) if (!drive->using_dma)
return 1; return 1;
if (HWIF(drive)->chipset == ide_pdc4030)
return 1;
if (ide_tcq_check_blacklist(drive)) {
printk(KERN_WARNING "%s: tcq forbidden by blacklist\n",
drive->name);
return 1;
}
if (drive->next != drive) {
printk(KERN_WARNING "%s: only one drive on a channel supported"
" for tcq\n", drive->name);
return 1;
}
if (ata_pending_commands(drive)) { if (ata_pending_commands(drive)) {
printk(KERN_WARNING "ide-tcq; can't toggle tcq feature on busy drive\n"); printk(KERN_WARNING "ide-tcq; can't toggle tcq feature on "
"busy drive\n");
return 1; return 1;
} }
......
...@@ -49,7 +49,7 @@ static struct input_dev rpcmouse_dev = { ...@@ -49,7 +49,7 @@ static struct input_dev rpcmouse_dev = {
}, },
}; };
static void rpcmouse_irq(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t rpcmouse_irq(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct input_dev *dev = dev_id; struct input_dev *dev = dev_id;
short x, y, dx, dy, b; short x, y, dx, dy, b;
...@@ -74,6 +74,8 @@ static void rpcmouse_irq(int irq, void *dev_id, struct pt_regs *regs) ...@@ -74,6 +74,8 @@ static void rpcmouse_irq(int irq, void *dev_id, struct pt_regs *regs)
input_report_key(dev, BTN_RIGHT, b & 0x10); input_report_key(dev, BTN_RIGHT, b & 0x10);
input_sync(dev); input_sync(dev);
return IRQ_HANDLED;
} }
static int __init rpcmouse_init(void) static int __init rpcmouse_init(void)
......
...@@ -28,22 +28,27 @@ ...@@ -28,22 +28,27 @@
struct amba_kmi_port { struct amba_kmi_port {
struct serio io; struct serio io;
struct amba_kmi_port *next; struct amba_kmi_port *next;
unsigned long base; void *base;
unsigned int irq; unsigned int irq;
unsigned int divisor; unsigned int divisor;
char name[32]; char name[32];
char phys[16]; char phys[16];
struct resource *res;
}; };
static void amba_kmi_int(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t amba_kmi_int(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct amba_kmi_port *kmi = dev_id; struct amba_kmi_port *kmi = dev_id;
unsigned int status = __raw_readb(KMIIR); unsigned int status = readb(KMIIR);
int handled = IRQ_NONE;
while (status & KMIIR_RXINTR) { while (status & KMIIR_RXINTR) {
serio_interrupt(&kmi->io, __raw_readb(KMIDATA), 0, regs); serio_interrupt(&kmi->io, readb(KMIDATA), 0, regs);
status = __raw_readb(KMIIR); status = readb(KMIIR);
handled = IRQ_HANDLED;
} }
return handled;
} }
static int amba_kmi_write(struct serio *io, unsigned char val) static int amba_kmi_write(struct serio *io, unsigned char val)
...@@ -51,11 +56,11 @@ static int amba_kmi_write(struct serio *io, unsigned char val) ...@@ -51,11 +56,11 @@ static int amba_kmi_write(struct serio *io, unsigned char val)
struct amba_kmi_port *kmi = io->driver; struct amba_kmi_port *kmi = io->driver;
unsigned int timeleft = 10000; /* timeout in 100ms */ unsigned int timeleft = 10000; /* timeout in 100ms */
while ((__raw_readb(KMISTAT) & KMISTAT_TXEMPTY) == 0 && timeleft--) while ((readb(KMISTAT) & KMISTAT_TXEMPTY) == 0 && timeleft--)
udelay(10); udelay(10);
if (timeleft) if (timeleft)
__raw_writeb(val, KMIDATA); writeb(val, KMIDATA);
return timeleft ? 0 : SERIO_TIMEOUT; return timeleft ? 0 : SERIO_TIMEOUT;
} }
...@@ -65,17 +70,17 @@ static int amba_kmi_open(struct serio *io) ...@@ -65,17 +70,17 @@ static int amba_kmi_open(struct serio *io)
struct amba_kmi_port *kmi = io->driver; struct amba_kmi_port *kmi = io->driver;
int ret; int ret;
__raw_writeb(kmi->divisor, KMICLKDIV); writeb(kmi->divisor, KMICLKDIV);
__raw_writeb(KMICR_EN, KMICR); writeb(KMICR_EN, KMICR);
ret = request_irq(kmi->irq, amba_kmi_int, 0, kmi->phys, kmi); ret = request_irq(kmi->irq, amba_kmi_int, 0, kmi->phys, kmi);
if (ret) { if (ret) {
printk(KERN_ERR "kmi: failed to claim IRQ%d\n", kmi->irq); printk(KERN_ERR "kmi: failed to claim IRQ%d\n", kmi->irq);
__raw_writeb(0, KMICR); writeb(0, KMICR);
return ret; return ret;
} }
__raw_writeb(KMICR_EN | KMICR_RXINTREN, KMICR); writeb(KMICR_EN | KMICR_RXINTREN, KMICR);
return 0; return 0;
} }
...@@ -84,9 +89,9 @@ static void amba_kmi_close(struct serio *io) ...@@ -84,9 +89,9 @@ static void amba_kmi_close(struct serio *io)
{ {
struct amba_kmi_port *kmi = io->driver; struct amba_kmi_port *kmi = io->driver;
free_irq(kmi->irq, kmi); writeb(0, KMICR);
__raw_writeb(0, KMICR); free_irq(kmi->irq, kmi);
} }
static struct amba_kmi_port *list; static struct amba_kmi_port *list;
...@@ -109,24 +114,36 @@ static int __init amba_kmi_init_one(char *type, unsigned long base, int irq, int ...@@ -109,24 +114,36 @@ static int __init amba_kmi_init_one(char *type, unsigned long base, int irq, int
kmi->io.phys = kmi->phys; kmi->io.phys = kmi->phys;
kmi->io.driver = kmi; kmi->io.driver = kmi;
kmi->base = base; snprintf(kmi->name, sizeof(kmi->name), "AMBA KMI PS/2 %s port", type);
snprintf(kmi->phys, sizeof(kmi->phys), "amba/serio%d", nr);
kmi->res = request_mem_region(base, KMI_SIZE, kmi->phys);
if (!kmi->res) {
kfree(kmi);
return -EBUSY;
}
kmi->base = ioremap(base, KMI_SIZE);
if (!kmi->base) {
release_resource(kmi->res);
kfree(kmi);
return -ENOMEM;
}
kmi->irq = irq; kmi->irq = irq;
kmi->divisor = 24 / 8 - 1; kmi->divisor = 24 / 8 - 1;
kmi->next = list; kmi->next = list;
list = kmi; list = kmi;
snprintf(kmi->name, sizeof(kmi->name), "AMBA KMI PS/2 %s port", type);
snprintf(kmi->phys, sizeof(kmi->phys), "amba/serio%d", nr);
serio_register_port(&kmi->io); serio_register_port(&kmi->io);
return 0; return 0;
} }
static int __init amba_kmi_init(void) static int __init amba_kmi_init(void)
{ {
amba_kmi_init_one("keyboard", IO_ADDRESS(KMI0_BASE), IRQ_KMIINT0, 0); amba_kmi_init_one("keyboard", KMI0_BASE, IRQ_KMIINT0, 0);
amba_kmi_init_one("mouse", IO_ADDRESS(KMI1_BASE), IRQ_KMIINT1, 1); amba_kmi_init_one("mouse", KMI1_BASE, IRQ_KMIINT1, 1);
return 0; return 0;
} }
...@@ -139,6 +156,8 @@ static void __exit amba_kmi_exit(void) ...@@ -139,6 +156,8 @@ static void __exit amba_kmi_exit(void)
next = kmi->next; next = kmi->next;
serio_unregister_port(&kmi->io); serio_unregister_port(&kmi->io);
iounmap(kmi->base);
release_resource(kmi->res);
kfree(kmi); kfree(kmi);
kmi = next; kmi = next;
......
...@@ -54,20 +54,24 @@ static int rpckbd_write(struct serio *port, unsigned char val) ...@@ -54,20 +54,24 @@ static int rpckbd_write(struct serio *port, unsigned char val)
return 0; return 0;
} }
static void rpckbd_rx(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t rpckbd_rx(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct serio *port = dev_id; struct serio *port = dev_id;
unsigned int byte; unsigned int byte;
int handled = IRQ_NONE;
while (iomd_readb(IOMD_KCTRL) & (1 << 5)) { while (iomd_readb(IOMD_KCTRL) & (1 << 5)) {
byte = iomd_readb(IOMD_KARTRX); byte = iomd_readb(IOMD_KARTRX);
serio_interrupt(port, byte, 0, regs); serio_interrupt(port, byte, 0, regs);
handled = IRQ_HANDLED;
} }
return handled;
} }
static void rpckbd_tx(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t rpckbd_tx(int irq, void *dev_id, struct pt_regs *regs)
{ {
return IRQ_HANDLED;
} }
static int rpckbd_open(struct serio *port) static int rpckbd_open(struct serio *port)
......
...@@ -41,10 +41,11 @@ struct ps2if { ...@@ -41,10 +41,11 @@ struct ps2if {
* at the most one, but we loop for safety. If there was a * at the most one, but we loop for safety. If there was a
* framing error, we have to manually clear the status. * framing error, we have to manually clear the status.
*/ */
static void ps2_rxint(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t ps2_rxint(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct ps2if *ps2if = dev_id; struct ps2if *ps2if = dev_id;
unsigned int scancode, flag, status; unsigned int scancode, flag, status;
int handled = IRQ_NONE;
status = sa1111_readl(ps2if->base + SA1111_PS2STAT); status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
while (status & PS2STAT_RXF) { while (status & PS2STAT_RXF) {
...@@ -62,13 +63,17 @@ static void ps2_rxint(int irq, void *dev_id, struct pt_regs *regs) ...@@ -62,13 +63,17 @@ static void ps2_rxint(int irq, void *dev_id, struct pt_regs *regs)
serio_interrupt(&ps2if->io, scancode, flag, regs); serio_interrupt(&ps2if->io, scancode, flag, regs);
status = sa1111_readl(ps2if->base + SA1111_PS2STAT); status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
handled = IRQ_HANDLED;
} }
return handled;
} }
/* /*
* Completion of ps2 write * Completion of ps2 write
*/ */
static void ps2_txint(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t ps2_txint(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct ps2if *ps2if = dev_id; struct ps2if *ps2if = dev_id;
unsigned int status; unsigned int status;
...@@ -83,6 +88,8 @@ static void ps2_txint(int irq, void *dev_id, struct pt_regs *regs) ...@@ -83,6 +88,8 @@ static void ps2_txint(int irq, void *dev_id, struct pt_regs *regs)
ps2if->tail = (ps2if->tail + 1) & (sizeof(ps2if->buf) - 1); ps2if->tail = (ps2if->tail + 1) & (sizeof(ps2if->buf) - 1);
} }
spin_unlock(&ps2if->lock); spin_unlock(&ps2if->lock);
return IRQ_HANDLED;
} }
/* /*
......
...@@ -302,11 +302,8 @@ static int proc_read_clients(char *buf, char **start, off_t pos, ...@@ -302,11 +302,8 @@ static int proc_read_clients(char *buf, char **start, off_t pos,
======================================================================*/ ======================================================================*/
static int setup_socket(socket_info_t *); static int pccardd(void *__skt);
static void shutdown_socket(socket_info_t *); void pcmcia_unregister_socket(struct class_device *dev);
static void reset_socket(socket_info_t *);
static void unreset_socket(socket_info_t *);
static void parse_events(void *info, u_int events);
#define to_class_data(dev) dev->class_data #define to_class_data(dev) dev->class_data
...@@ -317,7 +314,7 @@ int pcmcia_register_socket(struct class_device *class_dev) ...@@ -317,7 +314,7 @@ int pcmcia_register_socket(struct class_device *class_dev)
{ {
struct pcmcia_socket_class_data *cls_d = class_get_devdata(class_dev); struct pcmcia_socket_class_data *cls_d = class_get_devdata(class_dev);
socket_info_t *s_info; socket_info_t *s_info;
unsigned int i, j; unsigned int i, j, ret;
if (!cls_d) if (!cls_d)
return -EINVAL; return -EINVAL;
...@@ -330,6 +327,7 @@ int pcmcia_register_socket(struct class_device *class_dev) ...@@ -330,6 +327,7 @@ int pcmcia_register_socket(struct class_device *class_dev)
memset(s_info, 0, cls_d->nsock * sizeof(socket_info_t)); memset(s_info, 0, cls_d->nsock * sizeof(socket_info_t));
cls_d->s_info = s_info; cls_d->s_info = s_info;
ret = 0;
/* socket initialization */ /* socket initialization */
for (i = 0; i < cls_d->nsock; i++) { for (i = 0; i < cls_d->nsock; i++) {
...@@ -344,7 +342,7 @@ int pcmcia_register_socket(struct class_device *class_dev) ...@@ -344,7 +342,7 @@ int pcmcia_register_socket(struct class_device *class_dev)
s->erase_busy.next = s->erase_busy.prev = &s->erase_busy; s->erase_busy.next = s->erase_busy.prev = &s->erase_busy;
INIT_LIST_HEAD(&s->cis_cache); INIT_LIST_HEAD(&s->cis_cache);
spin_lock_init(&s->lock); spin_lock_init(&s->lock);
/* TBD: remove usage of socket_table, use class_for_each_dev instead */ /* TBD: remove usage of socket_table, use class_for_each_dev instead */
for (j = 0; j < sockets; j++) for (j = 0; j < sockets; j++)
if (socket_table[j] == NULL) break; if (socket_table[j] == NULL) break;
...@@ -353,6 +351,20 @@ int pcmcia_register_socket(struct class_device *class_dev) ...@@ -353,6 +351,20 @@ int pcmcia_register_socket(struct class_device *class_dev)
init_socket(s); init_socket(s);
s->ss_entry->inquire_socket(s->sock, &s->cap); s->ss_entry->inquire_socket(s->sock, &s->cap);
init_completion(&s->thread_done);
init_waitqueue_head(&s->thread_wait);
init_MUTEX(&s->skt_sem);
spin_lock_init(&s->thread_lock);
ret = kernel_thread(pccardd, s, CLONE_KERNEL);
if (ret < 0) {
pcmcia_unregister_socket(class_dev);
break;
}
wait_for_completion(&s->thread_done);
BUG_ON(!s->thread);
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
if (proc_pccard) { if (proc_pccard) {
char name[3]; char name[3];
...@@ -368,7 +380,7 @@ int pcmcia_register_socket(struct class_device *class_dev) ...@@ -368,7 +380,7 @@ int pcmcia_register_socket(struct class_device *class_dev)
} }
#endif #endif
} }
return 0; return ret;
} /* pcmcia_register_socket */ } /* pcmcia_register_socket */
...@@ -407,8 +419,12 @@ void pcmcia_unregister_socket(struct class_device *class_dev) ...@@ -407,8 +419,12 @@ void pcmcia_unregister_socket(struct class_device *class_dev)
remove_proc_entry(name, proc_pccard); remove_proc_entry(name, proc_pccard);
} }
#endif #endif
if (s->thread) {
shutdown_socket(s); init_completion(&s->thread_done);
s->thread = NULL;
wake_up(&s->thread_wait);
wait_for_completion(&s->thread_done);
}
release_cis_mem(s); release_cis_mem(s);
while (s->clients) { while (s->clients) {
client = s->clients; client = s->clients;
...@@ -450,15 +466,6 @@ static void free_regions(memory_handle_t *list) ...@@ -450,15 +466,6 @@ static void free_regions(memory_handle_t *list)
static int send_event(socket_info_t *s, event_t event, int priority); static int send_event(socket_info_t *s, event_t event, int priority);
/*
* Sleep for n_cs centiseconds (1 cs = 1/100th of a second)
*/
static void cs_sleep(unsigned int n_cs)
{
current->state = TASK_INTERRUPTIBLE;
schedule_timeout( (n_cs * HZ + 99) / 100);
}
static void shutdown_socket(socket_info_t *s) static void shutdown_socket(socket_info_t *s)
{ {
client_t **c; client_t **c;
...@@ -505,132 +512,6 @@ static void shutdown_socket(socket_info_t *s) ...@@ -505,132 +512,6 @@ static void shutdown_socket(socket_info_t *s)
free_regions(&s->c_region); free_regions(&s->c_region);
} /* shutdown_socket */ } /* shutdown_socket */
/*
* Return zero if we think the card isn't actually present
*/
static int setup_socket(socket_info_t *s)
{
int val, ret;
int setup_timeout = 100;
/* Wait for "not pending" */
for (;;) {
get_socket_status(s, &val);
if (!(val & SS_PENDING))
break;
if (--setup_timeout) {
cs_sleep(10);
continue;
}
printk(KERN_NOTICE "cs: socket %p voltage interrogation"
" timed out\n", s);
ret = 0;
goto out;
}
if (val & SS_DETECT) {
DEBUG(1, "cs: setup_socket(%p): applying power\n", s);
s->state |= SOCKET_PRESENT;
s->socket.flags &= SS_DEBOUNCED;
if (val & SS_3VCARD)
s->socket.Vcc = s->socket.Vpp = 33;
else if (!(val & SS_XVCARD))
s->socket.Vcc = s->socket.Vpp = 50;
else {
printk(KERN_NOTICE "cs: socket %p: unsupported "
"voltage key\n", s);
s->socket.Vcc = 0;
}
if (val & SS_CARDBUS) {
s->state |= SOCKET_CARDBUS;
#ifndef CONFIG_CARDBUS
printk(KERN_NOTICE "cs: unsupported card type detected!\n");
#endif
}
set_socket(s, &s->socket);
cs_sleep(vcc_settle);
reset_socket(s);
ret = 1;
} else {
DEBUG(0, "cs: setup_socket(%p): no card!\n", s);
ret = 0;
}
out:
return ret;
} /* setup_socket */
/*======================================================================
Reset_socket() and unreset_socket() handle hard resets. Resets
have several causes: card insertion, a call to reset_socket, or
recovery from a suspend/resume cycle. Unreset_socket() sends
a CS event that matches the cause of the reset.
======================================================================*/
static void reset_socket(socket_info_t *s)
{
DEBUG(1, "cs: resetting socket %p\n", s);
s->socket.flags |= SS_OUTPUT_ENA | SS_RESET;
set_socket(s, &s->socket);
udelay((long)reset_time);
s->socket.flags &= ~SS_RESET;
set_socket(s, &s->socket);
cs_sleep(unreset_delay);
unreset_socket(s);
} /* reset_socket */
#define EVENT_MASK \
(SOCKET_SETUP_PENDING|SOCKET_SUSPEND|SOCKET_RESET_PENDING)
static void unreset_socket(socket_info_t *s)
{
int setup_timeout = unreset_limit;
int val;
/* Wait for "ready" */
for (;;) {
get_socket_status(s, &val);
if (val & SS_READY)
break;
DEBUG(2, "cs: socket %d not ready yet\n", s->sock);
if (--setup_timeout) {
cs_sleep(unreset_check);
continue;
}
printk(KERN_NOTICE "cs: socket %p timed out during"
" reset. Try increasing setup_delay.\n", s);
s->state &= ~EVENT_MASK;
return;
}
DEBUG(1, "cs: reset done on socket %p\n", s);
if (s->state & SOCKET_SUSPEND) {
s->state &= ~EVENT_MASK;
if (verify_cis_cache(s) != 0)
parse_events(s, SS_DETECT);
else
send_event(s, CS_EVENT_PM_RESUME, CS_EVENT_PRI_LOW);
} else if (s->state & SOCKET_SETUP_PENDING) {
#ifdef CONFIG_CARDBUS
if (s->state & SOCKET_CARDBUS) {
cb_alloc(s);
s->state |= SOCKET_CARDBUS_CONFIG;
}
#endif
send_event(s, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
s->state &= ~SOCKET_SETUP_PENDING;
} else {
send_event(s, CS_EVENT_CARD_RESET, CS_EVENT_PRI_LOW);
if (s->reset_handle) {
s->reset_handle->event_callback_args.info = NULL;
EVENT(s->reset_handle, CS_EVENT_RESET_COMPLETE,
CS_EVENT_PRI_LOW);
}
s->state &= ~EVENT_MASK;
}
} /* unreset_socket */
/*====================================================================== /*======================================================================
The central event handler. Send_event() sends an event to all The central event handler. Send_event() sends an event to all
...@@ -661,61 +542,266 @@ static int send_event(socket_info_t *s, event_t event, int priority) ...@@ -661,61 +542,266 @@ static int send_event(socket_info_t *s, event_t event, int priority)
return ret; return ret;
} /* send_event */ } /* send_event */
static void do_shutdown(socket_info_t *s) static void pcmcia_error(socket_info_t *skt, const char *fmt, ...)
{ {
client_t *client; static char buf[128];
if (s->state & SOCKET_SHUTDOWN_PENDING) va_list ap;
return; int len;
s->state |= SOCKET_SHUTDOWN_PENDING;
send_event(s, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH); va_start(ap, fmt);
for (client = s->clients; client; client = client->next) len = vsnprintf(buf, sizeof(buf), fmt, ap);
if (!(client->Attributes & INFO_MASTER_CLIENT)) va_end(ap);
client->state |= CLIENT_STALE; buf[len] = '\0';
if (s->state & (SOCKET_SETUP_PENDING|SOCKET_RESET_PENDING)) {
DEBUG(0, "cs: flushing pending setup\n"); printk(KERN_ERR "PCMCIA: socket %p: %s", skt, buf);
s->state &= ~EVENT_MASK;
}
cs_sleep(shutdown_delay);
s->state &= ~SOCKET_PRESENT;
shutdown_socket(s);
} }
static void parse_events(void *info, u_int events) #define cs_to_timeout(cs) (((cs) * HZ + 99) / 100)
static void socket_remove_drivers(socket_info_t *skt)
{ {
socket_info_t *s = info; client_t *client;
if (events & SS_DETECT) {
int status; send_event(skt, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH);
get_socket_status(s, &status); for (client = skt->clients; client; client = client->next)
if ((s->state & SOCKET_PRESENT) && if (!(client->Attributes & INFO_MASTER_CLIENT))
(!(s->state & SOCKET_SUSPEND) || client->state |= CLIENT_STALE;
!(status & SS_DETECT))) }
do_shutdown(s);
if (status & SS_DETECT) { static void socket_shutdown(socket_info_t *skt)
if (s->state & SOCKET_SETUP_PENDING) { {
DEBUG(1, "cs: delaying pending setup\n"); socket_remove_drivers(skt);
return; set_current_state(TASK_UNINTERRUPTIBLE);
} schedule_timeout(cs_to_timeout(shutdown_delay));
s->state |= SOCKET_SETUP_PENDING; skt->state &= ~SOCKET_PRESENT;
if (s->state & SOCKET_SUSPEND) shutdown_socket(skt);
cs_sleep(resume_delay); }
else
cs_sleep(setup_delay); static int socket_reset(socket_info_t *skt)
s->socket.flags |= SS_DEBOUNCED; {
if (setup_socket(s) == 0) int status, i;
s->state &= ~SOCKET_SETUP_PENDING;
s->socket.flags &= ~SS_DEBOUNCED; skt->socket.flags |= SS_OUTPUT_ENA | SS_RESET;
set_socket(skt, &skt->socket);
udelay((long)reset_time);
skt->socket.flags &= ~SS_RESET;
set_socket(skt, &skt->socket);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(cs_to_timeout(unreset_delay));
for (i = 0; i < unreset_limit; i++) {
get_socket_status(skt, &status);
if (!(status & SS_DETECT))
return CS_NO_CARD;
if (status & SS_READY)
return CS_SUCCESS;
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(cs_to_timeout(unreset_check));
} }
}
if (events & SS_BATDEAD) pcmcia_error(skt, "time out after reset.\n");
send_event(s, CS_EVENT_BATTERY_DEAD, CS_EVENT_PRI_LOW); return CS_GENERAL_FAILURE;
if (events & SS_BATWARN) }
send_event(s, CS_EVENT_BATTERY_LOW, CS_EVENT_PRI_LOW);
if (events & SS_READY) { static int socket_setup(socket_info_t *skt, int initial_delay)
if (!(s->state & SOCKET_RESET_PENDING)) {
send_event(s, CS_EVENT_READY_CHANGE, CS_EVENT_PRI_LOW); int status, i;
else DEBUG(1, "cs: ready change during reset\n");
} get_socket_status(skt, &status);
if (!(status & SS_DETECT))
return CS_NO_CARD;
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(cs_to_timeout(initial_delay));
for (i = 0; i < 100; i++) {
get_socket_status(skt, &status);
if (!(status & SS_DETECT))
return CS_NO_CARD;
if (!(status & SS_PENDING))
break;
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(cs_to_timeout(10));
}
if (status & SS_PENDING) {
pcmcia_error(skt, "voltage interrogation timed out.\n");
return CS_GENERAL_FAILURE;
}
if (status & SS_CARDBUS) {
skt->state |= SOCKET_CARDBUS;
#ifndef CONFIG_CARDBUS
pcmcia_error(skt, "cardbus cards are not supported.\n");
return CS_BAD_TYPE;
#endif
}
/*
* Decode the card voltage requirements, and apply power to the card.
*/
if (status & SS_3VCARD)
skt->socket.Vcc = skt->socket.Vpp = 33;
else if (!(status & SS_XVCARD))
skt->socket.Vcc = skt->socket.Vpp = 50;
else {
pcmcia_error(skt, "unsupported voltage key.\n");
return CS_BAD_TYPE;
}
skt->state |= SOCKET_PRESENT;
skt->socket.flags = SS_DEBOUNCED;
set_socket(skt, &skt->socket);
/*
* Wait "vcc_settle" for the supply to stabilise.
*/
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(cs_to_timeout(vcc_settle));
return socket_reset(skt);
}
/*
* Handle card insertion. Setup the socket, reset the card,
* and then tell the rest of PCMCIA that a card is present.
*/
static int socket_insert(socket_info_t *skt)
{
int ret;
ret = socket_setup(skt, setup_delay);
if (ret == CS_SUCCESS) {
#ifdef CONFIG_CARDBUS
if (skt->state & SOCKET_CARDBUS) {
cb_alloc(skt);
skt->state |= SOCKET_CARDBUS_CONFIG;
}
#endif
send_event(skt, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
skt->socket.flags &= ~SS_DEBOUNCED;
} else
socket_shutdown(skt);
return ret;
}
static int socket_suspend(socket_info_t *skt)
{
if (skt->state & SOCKET_SUSPEND)
return CS_IN_USE;
send_event(skt, CS_EVENT_PM_SUSPEND, CS_EVENT_PRI_LOW);
suspend_socket(skt);
skt->state |= SOCKET_SUSPEND;
return CS_SUCCESS;
}
/*
* Resume a socket. If a card is present, verify its CIS against
* our cached copy. If they are different, the card has been
* replaced, and we need to tell the drivers.
*/
static int socket_resume(socket_info_t *skt)
{
int ret;
if (!(skt->state & SOCKET_SUSPEND))
return CS_IN_USE;
init_socket(skt);
ret = socket_setup(skt, resume_delay);
if (ret == CS_SUCCESS) {
/*
* FIXME: need a better check here for cardbus cards.
*/
if (verify_cis_cache(skt) != 0) {
socket_remove_drivers(skt);
destroy_cis_cache(skt);
send_event(skt, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
} else {
send_event(skt, CS_EVENT_PM_RESUME, CS_EVENT_PRI_LOW);
}
skt->socket.flags &= ~SS_DEBOUNCED;
} else
socket_shutdown(skt);
skt->state &= ~SOCKET_SUSPEND;
return CS_SUCCESS;
}
static int pccardd(void *__skt)
{
socket_info_t *skt = __skt;
DECLARE_WAITQUEUE(wait, current);
daemonize("pccardd");
skt->thread = current;
complete(&skt->thread_done);
add_wait_queue(&skt->thread_wait, &wait);
for (;;) {
unsigned long flags;
unsigned int events;
set_current_state(TASK_INTERRUPTIBLE);
spin_lock_irqsave(&skt->thread_lock, flags);
events = skt->thread_events;
skt->thread_events = 0;
spin_unlock_irqrestore(&skt->thread_lock, flags);
if (events) {
down(&skt->skt_sem);
if (events & SS_DETECT && !(skt->state & SOCKET_SUSPEND)) {
int status;
get_socket_status(skt, &status);
if ((skt->state & SOCKET_PRESENT) &&
!(status & SS_DETECT))
socket_shutdown(skt);
if (status & SS_DETECT)
socket_insert(skt);
}
if (events & SS_BATDEAD)
send_event(skt, CS_EVENT_BATTERY_DEAD, CS_EVENT_PRI_LOW);
if (events & SS_BATWARN)
send_event(skt, CS_EVENT_BATTERY_LOW, CS_EVENT_PRI_LOW);
if (events & SS_READY)
send_event(skt, CS_EVENT_READY_CHANGE, CS_EVENT_PRI_LOW);
up(&skt->skt_sem);
continue;
}
schedule();
if (!skt->thread)
break;
}
remove_wait_queue(&skt->thread_wait, &wait);
socket_shutdown(skt);
complete_and_exit(&skt->thread_done, 0);
}
static void parse_events(void *info, u_int events)
{
socket_info_t *s = info;
spin_lock(&s->thread_lock);
s->thread_events |= events;
spin_unlock(&s->thread_lock);
wake_up(&s->thread_wait);
} /* parse_events */ } /* parse_events */
/*====================================================================== /*======================================================================
...@@ -727,27 +813,18 @@ static void parse_events(void *info, u_int events) ...@@ -727,27 +813,18 @@ static void parse_events(void *info, u_int events)
======================================================================*/ ======================================================================*/
void pcmcia_suspend_socket (socket_info_t *s) void pcmcia_suspend_socket (socket_info_t *skt)
{ {
if ((s->state & SOCKET_PRESENT) && !(s->state & SOCKET_SUSPEND)) { down(&skt->skt_sem);
send_event(s, CS_EVENT_PM_SUSPEND, CS_EVENT_PRI_LOW); socket_suspend(skt);
suspend_socket(s); up(&skt->skt_sem);
s->state |= SOCKET_SUSPEND;
}
} }
void pcmcia_resume_socket (socket_info_t *s) void pcmcia_resume_socket (socket_info_t *skt)
{ {
int stat; down(&skt->skt_sem);
socket_resume(skt);
/* Do this just to reinitialize the socket */ up(&skt->skt_sem);
init_socket(s);
get_socket_status(s, &stat);
/* If there was or is a card here, we need to do something
about it... but parse_events will sort it all out. */
if ((s->state & SOCKET_PRESENT) || (stat & SS_DETECT))
parse_events(s, SS_DETECT);
} }
...@@ -1461,15 +1538,8 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) ...@@ -1461,15 +1538,8 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req)
s = socket_table[ns]; s = socket_table[ns];
if (++s->real_clients == 1) { if (++s->real_clients == 1) {
int status;
register_callback(s, &parse_events, s); register_callback(s, &parse_events, s);
get_socket_status(s, &status); parse_events(s, SS_DETECT);
if ((status & SS_DETECT) &&
!(s->state & SOCKET_SETUP_PENDING)) {
s->state |= SOCKET_SETUP_PENDING;
if (setup_socket(s) == 0)
s->state &= ~SOCKET_SETUP_PENDING;
}
} }
*handle = client; *handle = client;
...@@ -2022,30 +2092,44 @@ int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle ...@@ -2022,30 +2092,44 @@ int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle
int pcmcia_reset_card(client_handle_t handle, client_req_t *req) int pcmcia_reset_card(client_handle_t handle, client_req_t *req)
{ {
int i, ret; socket_info_t *skt;
socket_info_t *s; int ret;
if (CHECK_HANDLE(handle)) if (CHECK_HANDLE(handle))
return CS_BAD_HANDLE; return CS_BAD_HANDLE;
i = handle->Socket; s = socket_table[i]; DEBUG(1, "cs: resetting socket %d\n", handle->Socket);
if (!(s->state & SOCKET_PRESENT)) skt = SOCKET(handle);
return CS_NO_CARD;
if (s->state & SOCKET_RESET_PENDING) down(&skt->skt_sem);
return CS_IN_USE; do {
s->state |= SOCKET_RESET_PENDING; if (!(skt->state & SOCKET_PRESENT)) {
ret = CS_NO_CARD;
break;
}
if (skt->state & SOCKET_SUSPEND) {
ret = CS_IN_USE;
break;
}
if (skt->state & SOCKET_CARDBUS) {
ret = CS_UNSUPPORTED_FUNCTION;
break;
}
ret = send_event(s, CS_EVENT_RESET_REQUEST, CS_EVENT_PRI_LOW); ret = send_event(skt, CS_EVENT_RESET_REQUEST, CS_EVENT_PRI_LOW);
if (ret != 0) { if (ret == 0) {
s->state &= ~SOCKET_RESET_PENDING; send_event(skt, CS_EVENT_RESET_PHYSICAL, CS_EVENT_PRI_LOW);
handle->event_callback_args.info = (void *)(u_long)ret; if (socket_reset(skt) == CS_SUCCESS)
EVENT(handle, CS_EVENT_RESET_COMPLETE, CS_EVENT_PRI_LOW); send_event(skt, CS_EVENT_CARD_RESET, CS_EVENT_PRI_LOW);
} else { }
DEBUG(1, "cs: resetting socket %d\n", i);
send_event(s, CS_EVENT_RESET_PHYSICAL, CS_EVENT_PRI_LOW); handle->event_callback_args.info = (void *)(u_long)ret;
s->reset_handle = handle; EVENT(handle, CS_EVENT_RESET_COMPLETE, CS_EVENT_PRI_LOW);
reset_socket(s);
} ret = CS_SUCCESS;
return CS_SUCCESS; } while (0);
up(&skt->skt_sem);
return ret;
} /* reset_card */ } /* reset_card */
/*====================================================================== /*======================================================================
...@@ -2057,42 +2141,56 @@ int pcmcia_reset_card(client_handle_t handle, client_req_t *req) ...@@ -2057,42 +2141,56 @@ int pcmcia_reset_card(client_handle_t handle, client_req_t *req)
int pcmcia_suspend_card(client_handle_t handle, client_req_t *req) int pcmcia_suspend_card(client_handle_t handle, client_req_t *req)
{ {
int i; socket_info_t *skt;
socket_info_t *s; int ret;
if (CHECK_HANDLE(handle)) if (CHECK_HANDLE(handle))
return CS_BAD_HANDLE; return CS_BAD_HANDLE;
i = handle->Socket; s = socket_table[i]; DEBUG(1, "cs: suspending socket %d\n", handle->Socket);
if (!(s->state & SOCKET_PRESENT)) skt = SOCKET(handle);
return CS_NO_CARD;
if (s->state & SOCKET_SUSPEND) down(&skt->skt_sem);
return CS_IN_USE; do {
if (!(skt->state & SOCKET_PRESENT)) {
DEBUG(1, "cs: suspending socket %d\n", i); ret = CS_NO_CARD;
send_event(s, CS_EVENT_PM_SUSPEND, CS_EVENT_PRI_LOW); break;
suspend_socket(s); }
s->state |= SOCKET_SUSPEND; if (skt->state & SOCKET_CARDBUS) {
ret = CS_UNSUPPORTED_FUNCTION;
break;
}
ret = socket_suspend(skt);
} while (0);
up(&skt->skt_sem);
return CS_SUCCESS; return ret;
} /* suspend_card */ } /* suspend_card */
int pcmcia_resume_card(client_handle_t handle, client_req_t *req) int pcmcia_resume_card(client_handle_t handle, client_req_t *req)
{ {
int i; socket_info_t *skt;
socket_info_t *s; int ret;
if (CHECK_HANDLE(handle)) if (CHECK_HANDLE(handle))
return CS_BAD_HANDLE; return CS_BAD_HANDLE;
i = handle->Socket; s = socket_table[i]; DEBUG(1, "cs: waking up socket %d\n", handle->Socket);
if (!(s->state & SOCKET_PRESENT)) skt = SOCKET(handle);
return CS_NO_CARD;
if (!(s->state & SOCKET_SUSPEND)) down(&skt->skt_sem);
return CS_IN_USE; do {
if (!(skt->state & SOCKET_PRESENT)) {
DEBUG(1, "cs: waking up socket %d\n", i); ret = CS_NO_CARD;
setup_socket(s); break;
}
if (skt->state & SOCKET_CARDBUS) {
ret = CS_UNSUPPORTED_FUNCTION;
break;
}
ret = socket_resume(skt);
} while (0);
up(&skt->skt_sem);
return CS_SUCCESS; return ret;
} /* resume_card */ } /* resume_card */
/*====================================================================== /*======================================================================
...@@ -2103,57 +2201,58 @@ int pcmcia_resume_card(client_handle_t handle, client_req_t *req) ...@@ -2103,57 +2201,58 @@ int pcmcia_resume_card(client_handle_t handle, client_req_t *req)
int pcmcia_eject_card(client_handle_t handle, client_req_t *req) int pcmcia_eject_card(client_handle_t handle, client_req_t *req)
{ {
int i, ret; socket_info_t *skt;
socket_info_t *s; int ret;
u_long flags;
if (CHECK_HANDLE(handle)) if (CHECK_HANDLE(handle))
return CS_BAD_HANDLE; return CS_BAD_HANDLE;
i = handle->Socket; s = socket_table[i]; DEBUG(1, "cs: user eject request on socket %d\n", handle->Socket);
if (!(s->state & SOCKET_PRESENT)) skt = SOCKET(handle);
return CS_NO_CARD;
down(&skt->skt_sem);
do {
if (!(skt->state & SOCKET_PRESENT)) {
ret = CS_NO_CARD;
break;
}
DEBUG(1, "cs: user eject request on socket %d\n", i); ret = send_event(skt, CS_EVENT_EJECTION_REQUEST, CS_EVENT_PRI_LOW);
if (ret != 0)
break;
ret = send_event(s, CS_EVENT_EJECTION_REQUEST, CS_EVENT_PRI_LOW); socket_shutdown(skt);
if (ret != 0) ret = CS_SUCCESS;
return ret; } while (0);
up(&skt->skt_sem);
spin_lock_irqsave(&s->lock, flags); return ret;
do_shutdown(s);
spin_unlock_irqrestore(&s->lock, flags);
return CS_SUCCESS;
} /* eject_card */ } /* eject_card */
int pcmcia_insert_card(client_handle_t handle, client_req_t *req) int pcmcia_insert_card(client_handle_t handle, client_req_t *req)
{ {
int i, status; socket_info_t *skt;
socket_info_t *s; int ret;
u_long flags;
if (CHECK_HANDLE(handle))
return CS_BAD_HANDLE;
i = handle->Socket; s = socket_table[i];
if (s->state & SOCKET_PRESENT)
return CS_IN_USE;
DEBUG(1, "cs: user insert request on socket %d\n", i);
spin_lock_irqsave(&s->lock, flags); if (CHECK_HANDLE(handle))
if (!(s->state & SOCKET_SETUP_PENDING)) { return CS_BAD_HANDLE;
s->state |= SOCKET_SETUP_PENDING; DEBUG(1, "cs: user insert request on socket %d\n", handle->Socket);
spin_unlock_irqrestore(&s->lock, flags); skt = SOCKET(handle);
get_socket_status(s, &status);
if ((status & SS_DETECT) == 0 || (setup_socket(s) == 0)) { down(&skt->skt_sem);
s->state &= ~SOCKET_SETUP_PENDING; do {
return CS_NO_CARD; if (skt->state & SOCKET_PRESENT) {
} ret = CS_IN_USE;
} else break;
spin_unlock_irqrestore(&s->lock, flags); }
if (socket_insert(skt) == CS_NO_CARD) {
ret = CS_NO_CARD;
break;
}
ret = CS_SUCCESS;
} while (0);
up(&skt->skt_sem);
return CS_SUCCESS; return ret;
} /* insert_card */ } /* insert_card */
/*====================================================================== /*======================================================================
......
...@@ -133,7 +133,6 @@ typedef struct socket_info_t { ...@@ -133,7 +133,6 @@ typedef struct socket_info_t {
u_short lock_count; u_short lock_count;
client_handle_t clients; client_handle_t clients;
u_int real_clients; u_int real_clients;
client_handle_t reset_handle;
pccard_mem_map cis_mem; pccard_mem_map cis_mem;
u_char *cis_virt; u_char *cis_virt;
config_t *config; config_t *config;
...@@ -155,6 +154,14 @@ typedef struct socket_info_t { ...@@ -155,6 +154,14 @@ typedef struct socket_info_t {
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc; struct proc_dir_entry *proc;
#endif #endif
struct semaphore skt_sem; /* protects socket h/w state */
struct task_struct *thread;
struct completion thread_done;
wait_queue_head_t thread_wait;
spinlock_t thread_lock; /* protects thread_events */
unsigned int thread_events;
} socket_info_t; } socket_info_t;
/* Flags in config state */ /* Flags in config state */
......
...@@ -120,7 +120,6 @@ sa1100_pcmcia_set_mecr(struct sa1100_pcmcia_socket *skt, unsigned int cpu_clock) ...@@ -120,7 +120,6 @@ sa1100_pcmcia_set_mecr(struct sa1100_pcmcia_socket *skt, unsigned int cpu_clock)
unsigned long flags; unsigned long flags;
unsigned short speed; unsigned short speed;
unsigned int bs_io, bs_mem, bs_attr; unsigned int bs_io, bs_mem, bs_attr;
int i;
speed = calc_speed(skt->spd_io, MAX_IO_WIN, SA1100_PCMCIA_IO_ACCESS); speed = calc_speed(skt->spd_io, MAX_IO_WIN, SA1100_PCMCIA_IO_ACCESS);
bs_io = skt->ops->socket_get_timing(skt, cpu_clock, speed); bs_io = skt->ops->socket_get_timing(skt, cpu_clock, speed);
...@@ -324,13 +323,15 @@ static void sa1100_pcmcia_poll_event(unsigned long dummy) ...@@ -324,13 +323,15 @@ static void sa1100_pcmcia_poll_event(unsigned long dummy)
* handling code performs scheduling operations which cannot be * handling code performs scheduling operations which cannot be
* executed from within an interrupt context. * executed from within an interrupt context.
*/ */
static void sa1100_pcmcia_interrupt(int irq, void *dev, struct pt_regs *regs) static irqreturn_t sa1100_pcmcia_interrupt(int irq, void *dev, struct pt_regs *regs)
{ {
struct sa1100_pcmcia_socket *skt = dev; struct sa1100_pcmcia_socket *skt = dev;
DEBUG(3, "%s(): servicing IRQ %d\n", __FUNCTION__, irq); DEBUG(3, "%s(): servicing IRQ %d\n", __FUNCTION__, irq);
schedule_work(&skt->work); schedule_work(&skt->work);
return IRQ_HANDLED;
} }
/* sa1100_pcmcia_register_callback() /* sa1100_pcmcia_register_callback()
......
...@@ -85,7 +85,7 @@ static void serial21285_enable_ms(struct uart_port *port) ...@@ -85,7 +85,7 @@ static void serial21285_enable_ms(struct uart_port *port)
{ {
} }
static void serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct uart_port *port = dev_id; struct uart_port *port = dev_id;
struct tty_struct *tty = port->info->tty; struct tty_struct *tty = port->info->tty;
...@@ -97,7 +97,7 @@ static void serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *regs) ...@@ -97,7 +97,7 @@ static void serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *regs)
tty->flip.work.func((void *)tty); tty->flip.work.func((void *)tty);
if (tty->flip.count >= TTY_FLIPBUF_SIZE) { if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
printk(KERN_WARNING "TTY_DONT_FLIP set\n"); printk(KERN_WARNING "TTY_DONT_FLIP set\n");
return; goto out;
} }
} }
...@@ -143,9 +143,12 @@ static void serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *regs) ...@@ -143,9 +143,12 @@ static void serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *regs)
status = *CSR_UARTFLG; status = *CSR_UARTFLG;
} }
tty_flip_buffer_push(tty); tty_flip_buffer_push(tty);
out:
return IRQ_HANDLED;
} }
static void serial21285_tx_chars(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t serial21285_tx_chars(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct uart_port *port = dev_id; struct uart_port *port = dev_id;
struct circ_buf *xmit = &port->info->xmit; struct circ_buf *xmit = &port->info->xmit;
...@@ -155,11 +158,11 @@ static void serial21285_tx_chars(int irq, void *dev_id, struct pt_regs *regs) ...@@ -155,11 +158,11 @@ static void serial21285_tx_chars(int irq, void *dev_id, struct pt_regs *regs)
*CSR_UARTDR = port->x_char; *CSR_UARTDR = port->x_char;
port->icount.tx++; port->icount.tx++;
port->x_char = 0; port->x_char = 0;
return; goto out;
} }
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
serial21285_stop_tx(port, 0); serial21285_stop_tx(port, 0);
return; goto out;
} }
do { do {
...@@ -175,6 +178,9 @@ static void serial21285_tx_chars(int irq, void *dev_id, struct pt_regs *regs) ...@@ -175,6 +178,9 @@ static void serial21285_tx_chars(int irq, void *dev_id, struct pt_regs *regs)
if (uart_circ_empty(xmit)) if (uart_circ_empty(xmit))
serial21285_stop_tx(port, 0); serial21285_stop_tx(port, 0);
out:
return IRQ_HANDLED;
} }
static unsigned int serial21285_tx_empty(struct uart_port *port) static unsigned int serial21285_tx_empty(struct uart_port *port)
......
...@@ -278,7 +278,7 @@ static void ambauart_modem_status(struct uart_port *port) ...@@ -278,7 +278,7 @@ static void ambauart_modem_status(struct uart_port *port)
wake_up_interruptible(&uap->port.info->delta_msr_wait); wake_up_interruptible(&uap->port.info->delta_msr_wait);
} }
static void ambauart_int(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t ambauart_int(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct uart_port *port = dev_id; struct uart_port *port = dev_id;
unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT; unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT;
...@@ -302,6 +302,8 @@ static void ambauart_int(int irq, void *dev_id, struct pt_regs *regs) ...@@ -302,6 +302,8 @@ static void ambauart_int(int irq, void *dev_id, struct pt_regs *regs)
status = UART_GET_INT_STATUS(port); status = UART_GET_INT_STATUS(port);
} while (status & (AMBA_UARTIIR_RTIS | AMBA_UARTIIR_RIS | } while (status & (AMBA_UARTIIR_RTIS | AMBA_UARTIIR_RIS |
AMBA_UARTIIR_TIS)); AMBA_UARTIIR_TIS));
return IRQ_HANDLED;
} }
static unsigned int ambauart_tx_empty(struct uart_port *port) static unsigned int ambauart_tx_empty(struct uart_port *port)
......
...@@ -312,7 +312,7 @@ static void sa1100_tx_chars(struct sa1100_port *sport) ...@@ -312,7 +312,7 @@ static void sa1100_tx_chars(struct sa1100_port *sport)
sa1100_stop_tx(&sport->port, 0); sa1100_stop_tx(&sport->port, 0);
} }
static void sa1100_int(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t sa1100_int(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct sa1100_port *sport = dev_id; struct sa1100_port *sport = dev_id;
unsigned int status, pass_counter = 0; unsigned int status, pass_counter = 0;
...@@ -347,6 +347,8 @@ static void sa1100_int(int irq, void *dev_id, struct pt_regs *regs) ...@@ -347,6 +347,8 @@ static void sa1100_int(int irq, void *dev_id, struct pt_regs *regs)
~UTSR0_TFS; ~UTSR0_TFS;
} while (status & (UTSR0_TFS | UTSR0_RFS | UTSR0_RID)); } while (status & (UTSR0_TFS | UTSR0_RFS | UTSR0_RID));
spin_unlock(&sport->port.lock); spin_unlock(&sport->port.lock);
return IRQ_HANDLED;
} }
/* /*
...@@ -830,7 +832,7 @@ static struct console sa1100_console = { ...@@ -830,7 +832,7 @@ static struct console sa1100_console = {
.setup = sa1100_console_setup, .setup = sa1100_console_setup,
.flags = CON_PRINTBUFFER, .flags = CON_PRINTBUFFER,
.index = -1, .index = -1,
.data = sa1100_reg, .data = &sa1100_reg,
}; };
static int __init sa1100_rs_console_init(void) static int __init sa1100_rs_console_init(void)
......
...@@ -14,10 +14,11 @@ ...@@ -14,10 +14,11 @@
#ifndef __ASM_ARCH_TIME_H #ifndef __ASM_ARCH_TIME_H
#define __ASM_ARCH_TIME_H #define __ASM_ARCH_TIME_H
static void static irqreturn_t
anakin_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) anakin_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
do_timer(regs); do_timer(regs);
return IRQ_HANDLED;
} }
void __init time_init(void) void __init time_init(void)
......
...@@ -14,11 +14,13 @@ ...@@ -14,11 +14,13 @@
*/ */
extern void ioctime_init(void); extern void ioctime_init(void);
static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t
timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
do_timer(regs); do_timer(regs);
do_set_rtc(); do_set_rtc();
do_profile(regs); do_profile(regs);
return IRQ_HANDLED;
} }
/* /*
......
...@@ -11,7 +11,8 @@ ...@@ -11,7 +11,8 @@
extern void ioctime_init(void); extern void ioctime_init(void);
static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t
timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
do_timer(regs); do_timer(regs);
do_set_rtc(); do_set_rtc();
...@@ -26,6 +27,7 @@ static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -26,6 +27,7 @@ static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
*((volatile unsigned int *)LED_ADDRESS) = state; *((volatile unsigned int *)LED_ADDRESS) = state;
} }
} }
return IRQ_HANDLED;
} }
/* /*
......
...@@ -25,11 +25,13 @@ extern void clps711x_setup_timer(void); ...@@ -25,11 +25,13 @@ extern void clps711x_setup_timer(void);
/* /*
* IRQ handler for the timer * IRQ handler for the timer
*/ */
static void p720t_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t
p720t_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
do_leds(); do_leds();
do_timer(regs); do_timer(regs);
do_profile(regs); do_profile(regs);
return IRQ_HANDLED;
} }
/* /*
......
...@@ -74,7 +74,8 @@ static unsigned long ebsa110_gettimeoffset(void) ...@@ -74,7 +74,8 @@ static unsigned long ebsa110_gettimeoffset(void)
return offset; return offset;
} }
static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t
timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
u32 count; u32 count;
...@@ -91,6 +92,8 @@ static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -91,6 +92,8 @@ static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
do_leds(); do_leds();
do_timer(regs); do_timer(regs);
do_profile(regs); do_profile(regs);
return IRQ_HANDLED;
} }
/* /*
......
...@@ -69,7 +69,8 @@ static unsigned long isa_gettimeoffset(void) ...@@ -69,7 +69,8 @@ static unsigned long isa_gettimeoffset(void)
return count; return count;
} }
static void isa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t
isa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
if (machine_is_netwinder()) if (machine_is_netwinder())
do_leds(); do_leds();
...@@ -77,6 +78,8 @@ static void isa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -77,6 +78,8 @@ static void isa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
do_timer(regs); do_timer(regs);
do_set_rtc(); do_set_rtc();
do_profile(regs); do_profile(regs);
return IRQ_HANDLED;
} }
static unsigned long __init get_isa_cmos_time(void) static unsigned long __init get_isa_cmos_time(void)
...@@ -186,7 +189,8 @@ static unsigned long timer1_gettimeoffset (void) ...@@ -186,7 +189,8 @@ static unsigned long timer1_gettimeoffset (void)
return ((tick_nsec / 1000) * value) / LATCH; return ((tick_nsec / 1000) * value) / LATCH;
} }
static void timer1_interrupt(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t
timer1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
*CSR_TIMER1_CLR = 0; *CSR_TIMER1_CLR = 0;
...@@ -195,6 +199,8 @@ static void timer1_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -195,6 +199,8 @@ static void timer1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
do_timer(regs); do_timer(regs);
do_set_rtc(); do_set_rtc();
do_profile(regs); do_profile(regs);
return IRQ_HANDLED;
} }
/* /*
......
...@@ -27,7 +27,8 @@ ...@@ -27,7 +27,8 @@
/* /*
* IRQ handler for the timer * IRQ handler for the timer
*/ */
static void excalibur_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t
excalibur_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
// ...clear the interrupt // ...clear the interrupt
...@@ -36,6 +37,8 @@ static void excalibur_timer_interrupt(int irq, void *dev_id, struct pt_regs *reg ...@@ -36,6 +37,8 @@ static void excalibur_timer_interrupt(int irq, void *dev_id, struct pt_regs *reg
do_leds(); do_leds();
do_timer(regs); do_timer(regs);
do_profile(regs); do_profile(regs);
return IRQ_HANDLED;
} }
/* /*
......
...@@ -98,7 +98,8 @@ static unsigned long integrator_gettimeoffset(void) ...@@ -98,7 +98,8 @@ static unsigned long integrator_gettimeoffset(void)
/* /*
* IRQ handler for the timer * IRQ handler for the timer
*/ */
static void integrator_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t
integrator_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
volatile TimerStruct_t *timer1 = (volatile TimerStruct_t *)TIMER1_VA_BASE; volatile TimerStruct_t *timer1 = (volatile TimerStruct_t *)TIMER1_VA_BASE;
...@@ -108,6 +109,8 @@ static void integrator_timer_interrupt(int irq, void *dev_id, struct pt_regs *re ...@@ -108,6 +109,8 @@ static void integrator_timer_interrupt(int irq, void *dev_id, struct pt_regs *re
do_leds(); do_leds();
do_timer(regs); do_timer(regs);
do_profile(regs); do_profile(regs);
return IRQ_HANDLED;
} }
/* /*
......
...@@ -42,11 +42,14 @@ ...@@ -42,11 +42,14 @@
/* /*
* Handler for RTC timer interrupt * Handler for RTC timer interrupt
*/ */
static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t
timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
do_timer(regs); do_timer(regs);
do_profile(regs); do_profile(regs);
RTC_RTCC = 0; /* Clear interrupt */ RTC_RTCC = 0; /* Clear interrupt */
return IRQ_HANDLED;
} }
/* /*
......
...@@ -14,7 +14,8 @@ ...@@ -14,7 +14,8 @@
* 2 of the License, or (at your option) any later version. * 2 of the License, or (at your option) any later version.
*/ */
static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t
timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
static int count = 25; static int count = 25;
unsigned char stat = __raw_readb(DUART_BASE + 0x14); unsigned char stat = __raw_readb(DUART_BASE + 0x14);
...@@ -40,7 +41,9 @@ static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -40,7 +41,9 @@ static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
__raw_readb(DUART_BASE + 0x14); __raw_readb(DUART_BASE + 0x14);
__raw_readb(DUART_BASE + 0x14); __raw_readb(DUART_BASE + 0x14);
do_timer(regs); do_timer(regs);
return IRQ_HANDLED;
} }
void __init time_init(void) void __init time_init(void)
......
...@@ -10,9 +10,10 @@ ...@@ -10,9 +10,10 @@
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#define PXA_IRQ_SKIP 8 /* The first 8 IRQs are reserved */ #define PXA_IRQ_SKIP 7 /* The first 7 IRQs are not yet used */
#define PXA_IRQ(x) ((x) - PXA_IRQ_SKIP) #define PXA_IRQ(x) ((x) - PXA_IRQ_SKIP)
#define IRQ_HWUART PXA_IRQ(7) /* HWUART Transmit/Receive/Error */
#define IRQ_GPIO0 PXA_IRQ(8) /* GPIO0 Edge Detect */ #define IRQ_GPIO0 PXA_IRQ(8) /* GPIO0 Edge Detect */
#define IRQ_GPIO1 PXA_IRQ(9) /* GPIO1 Edge Detect */ #define IRQ_GPIO1 PXA_IRQ(9) /* GPIO1 Edge Detect */
#define IRQ_GPIO_2_80 PXA_IRQ(10) /* GPIO[2-80] Edge Detect */ #define IRQ_GPIO_2_80 PXA_IRQ(10) /* GPIO[2-80] Edge Detect */
...@@ -20,6 +21,8 @@ ...@@ -20,6 +21,8 @@
#define IRQ_PMU PXA_IRQ(12) /* Performance Monitoring Unit */ #define IRQ_PMU PXA_IRQ(12) /* Performance Monitoring Unit */
#define IRQ_I2S PXA_IRQ(13) /* I2S Interrupt */ #define IRQ_I2S PXA_IRQ(13) /* I2S Interrupt */
#define IRQ_AC97 PXA_IRQ(14) /* AC97 Interrupt */ #define IRQ_AC97 PXA_IRQ(14) /* AC97 Interrupt */
#define IRQ_ASSP PXA_IRQ(15) /* Audio SSP Service Request */
#define IRQ_NSSP PXA_IRQ(16) /* Network SSP Service Request */
#define IRQ_LCD PXA_IRQ(17) /* LCD Controller Service Request */ #define IRQ_LCD PXA_IRQ(17) /* LCD Controller Service Request */
#define IRQ_I2C PXA_IRQ(18) /* I2C Service Request */ #define IRQ_I2C PXA_IRQ(18) /* I2C Service Request */
#define IRQ_ICP PXA_IRQ(19) /* ICP Transmit/Receive/Error */ #define IRQ_ICP PXA_IRQ(19) /* ICP Transmit/Receive/Error */
......
...@@ -47,7 +47,8 @@ static unsigned long pxa_gettimeoffset (void) ...@@ -47,7 +47,8 @@ static unsigned long pxa_gettimeoffset (void)
return usec; return usec;
} }
static void pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t
pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
int next_match; int next_match;
...@@ -66,6 +67,8 @@ static void pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -66,6 +67,8 @@ static void pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
OSSR = OSSR_M0; /* Clear match on timer 0 */ OSSR = OSSR_M0; /* Clear match on timer 0 */
next_match = (OSMR0 += LATCH); next_match = (OSMR0 += LATCH);
} while( (signed long)(next_match - OSCR) <= 0 ); } while( (signed long)(next_match - OSCR) <= 0 );
return IRQ_HANDLED;
} }
void __init time_init(void) void __init time_init(void)
......
...@@ -14,11 +14,14 @@ ...@@ -14,11 +14,14 @@
*/ */
extern void ioctime_init(void); extern void ioctime_init(void);
static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t
timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
do_timer(regs); do_timer(regs);
do_set_rtc(); do_set_rtc();
do_profile(regs); do_profile(regs);
return IRQ_HANDLED;
} }
/* /*
......
...@@ -72,7 +72,8 @@ static unsigned long sa1100_gettimeoffset (void) ...@@ -72,7 +72,8 @@ static unsigned long sa1100_gettimeoffset (void)
* lost_ticks (updated in do_timer()) and the match reg value, so we * lost_ticks (updated in do_timer()) and the match reg value, so we
* can use do_gettimeofday() from interrupt handlers. * can use do_gettimeofday() from interrupt handlers.
*/ */
static void sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t
sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
unsigned int next_match; unsigned int next_match;
...@@ -85,6 +86,8 @@ static void sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -85,6 +86,8 @@ static void sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
} while ((signed long)(next_match - OSCR) <= 0); } while ((signed long)(next_match - OSCR) <= 0);
do_profile(regs); do_profile(regs);
return IRQ_HANDLED;
} }
void __init time_init(void) void __init time_init(void)
......
...@@ -13,11 +13,14 @@ ...@@ -13,11 +13,14 @@
#define IRQ_TIMER 0 #define IRQ_TIMER 0
#define HZ_TIME ((1193180 + HZ/2) / HZ) #define HZ_TIME ((1193180 + HZ/2) / HZ)
static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t
timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
do_leds(); do_leds();
do_timer(regs); do_timer(regs);
do_profile(regs); do_profile(regs);
return IRQ_HANDLED;
} }
/* /*
......
...@@ -20,13 +20,16 @@ ...@@ -20,13 +20,16 @@
#define update_rtc() #define update_rtc()
static void timer_interrupt (int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t
timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
{ {
/* Clear irq */ /* Clear irq */
__raw_writel(1, FPGA1CONT + 0xc); __raw_writel(1, FPGA1CONT + 0xc);
__raw_writel(0, FPGA1CONT + 0xc); __raw_writel(0, FPGA1CONT + 0xc);
do_timer(regs); do_timer(regs);
return IRQ_HANDLED;
} }
void __init time_init(void) void __init time_init(void)
......
...@@ -173,7 +173,7 @@ static inline int __test_and_change_bit(int nr, volatile unsigned long *p) ...@@ -173,7 +173,7 @@ static inline int __test_and_change_bit(int nr, volatile unsigned long *p)
*/ */
static inline int __test_bit(int nr, const unsigned long * p) static inline int __test_bit(int nr, const unsigned long * p)
{ {
return p[nr >> 5] & (1UL << (nr & 31)); return (p[nr >> 5] >> (nr & 31)) & 1UL;
} }
/* /*
...@@ -277,6 +277,8 @@ extern int _find_next_zero_bit_be(void * p, int size, int offset); ...@@ -277,6 +277,8 @@ extern int _find_next_zero_bit_be(void * p, int size, int offset);
#endif #endif
#if __LINUX_ARM_ARCH__ < 5
/* /*
* ffz = Find First Zero in word. Undefined if no zero exists, * ffz = Find First Zero in word. Undefined if no zero exists,
* so code should check against ~0UL first.. * so code should check against ~0UL first..
...@@ -326,6 +328,23 @@ static inline unsigned long __ffs(unsigned long word) ...@@ -326,6 +328,23 @@ static inline unsigned long __ffs(unsigned long word)
#define ffs(x) generic_ffs(x) #define ffs(x) generic_ffs(x)
#else
/*
* On ARMv5 and above those functions can be implemented around
* the clz instruction for much better code efficiency.
*/
extern __inline__ int generic_fls(int x);
#define fls(x) \
( __builtin_constant_p(x) ? generic_fls(x) : \
({ int __r; asm("clz%?\t%0, %1" : "=r"(__r) : "r"(x)); 32-__r; }) )
#define ffs(x) ({ unsigned long __t = (x); fls(__t & -__t); })
#define __ffs(x) (ffs(x) - 1)
#define ffz(x) __ffs( ~(x) )
#endif
/* /*
* Find first bit set in a 168-bit bitmap, where the first * Find first bit set in a 168-bit bitmap, where the first
* 128 bits are unlikely to be set. * 128 bits are unlikely to be set.
......
...@@ -10,8 +10,6 @@ ...@@ -10,8 +10,6 @@
#ifndef __ASM_BUGS_H #ifndef __ASM_BUGS_H
#define __ASM_BUGS_H #define __ASM_BUGS_H
#include <asm/proc-fns.h>
#define check_bugs() do { } while (0) #define check_bugs() do { } while (0)
#endif #endif
...@@ -54,39 +54,37 @@ struct machine_desc { ...@@ -54,39 +54,37 @@ struct machine_desc {
#define MACHINE_START(_type,_name) \ #define MACHINE_START(_type,_name) \
const struct machine_desc __mach_desc_##_type \ const struct machine_desc __mach_desc_##_type \
__attribute__((__section__(".arch.info"))) = { \ __attribute__((__section__(".arch.info"))) = { \
nr: MACH_TYPE_##_type, \ .nr = MACH_TYPE_##_type, \
name: _name, .name = _name,
#define MAINTAINER(n) #define MAINTAINER(n)
#define BOOT_MEM(_pram,_pio,_vio) \ #define BOOT_MEM(_pram,_pio,_vio) \
phys_ram: _pram, \ .phys_ram = _pram, \
phys_io: _pio, \ .phys_io = _pio, \
io_pg_offst: ((_vio)>>18)&0xfffc, .io_pg_offst = ((_vio)>>18)&0xfffc,
#define BOOT_PARAMS(_params) \ #define BOOT_PARAMS(_params) \
param_offset: _params, .param_offset = _params,
#define VIDEO(_start,_end) \ #define VIDEO(_start,_end) \
video_start: _start, \ .video_start = _start, \
video_end: _end, .video_end = _end,
#define DISABLE_PARPORT(_n) \ #define DISABLE_PARPORT(_n) \
reserve_lp##_n: 1, .reserve_lp##_n = 1,
#define BROKEN_HLT /* unused */
#define SOFT_REBOOT \ #define SOFT_REBOOT \
soft_reboot: 1, .soft_reboot = 1,
#define FIXUP(_func) \ #define FIXUP(_func) \
fixup: _func, .fixup = _func,
#define MAPIO(_func) \ #define MAPIO(_func) \
map_io: _func, .map_io = _func,
#define INITIRQ(_func) \ #define INITIRQ(_func) \
init_irq: _func, .init_irq = _func,
#define MACHINE_END \ #define MACHINE_END \
}; };
......
...@@ -74,6 +74,29 @@ unsigned long get_wchan(struct task_struct *p); ...@@ -74,6 +74,29 @@ unsigned long get_wchan(struct task_struct *p);
*/ */
extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
/*
* Prefetching support - only ARMv5.
*/
#if __LINUX_ARM_ARCH__ >= 5
#define ARCH_HAS_PREFETCH
#define prefetch(ptr) \
({ \
__asm__ __volatile__( \
"pld\t%0" \
: \
: "o" (*(char *)(ptr)) \
: "cc"); \
})
#define ARCH_HAS_PREFETCHW
#define prefetchw(ptr) prefetch(ptr)
#define ARCH_HAS_SPINLOCK_PREFETCH
#define spin_lock_prefetch(x) do { } while (0)
#endif
#endif #endif
#endif /* __ASM_ARM_PROCESSOR_H */ #endif /* __ASM_ARM_PROCESSOR_H */
#ifndef _ASMARM_TRAP_H
#define _ASMARM_TRAP_H
#include <linux/list.h>
struct undef_hook {
struct list_head node;
u32 instr_mask;
u32 instr_val;
u32 cpsr_mask;
u32 cpsr_val;
int (*fn)(struct pt_regs *regs, unsigned int instr);
};
void register_undef_hook(struct undef_hook *hook);
void unregister_undef_hook(struct undef_hook *hook);
#endif
...@@ -131,6 +131,7 @@ struct bio { ...@@ -131,6 +131,7 @@ struct bio {
#define bio_iovec(bio) bio_iovec_idx((bio), (bio)->bi_idx) #define bio_iovec(bio) bio_iovec_idx((bio), (bio)->bi_idx)
#define bio_page(bio) bio_iovec((bio))->bv_page #define bio_page(bio) bio_iovec((bio))->bv_page
#define bio_offset(bio) bio_iovec((bio))->bv_offset #define bio_offset(bio) bio_iovec((bio))->bv_offset
#define bio_segments(bio) ((bio)->bi_vcnt - (bio)->bi_idx)
#define bio_sectors(bio) ((bio)->bi_size >> 9) #define bio_sectors(bio) ((bio)->bi_size >> 9)
#define bio_cur_sectors(bio) (bio_iovec(bio)->bv_len >> 9) #define bio_cur_sectors(bio) (bio_iovec(bio)->bv_len >> 9)
#define bio_data(bio) (page_address(bio_page((bio))) + bio_offset((bio))) #define bio_data(bio) (page_address(bio_page((bio))) + bio_offset((bio)))
...@@ -226,12 +227,12 @@ extern void bio_check_pages_dirty(struct bio *bio); ...@@ -226,12 +227,12 @@ extern void bio_check_pages_dirty(struct bio *bio);
#ifdef CONFIG_HIGHMEM #ifdef CONFIG_HIGHMEM
/* /*
* remember to add offset! and never ever reenable interrupts between a * remember to add offset! and never ever reenable interrupts between a
* bio_kmap_irq and bio_kunmap_irq!! * bvec_kmap_irq and bvec_kunmap_irq!!
* *
* This function MUST be inlined - it plays with the CPU interrupt flags. * This function MUST be inlined - it plays with the CPU interrupt flags.
* Hence the `extern inline'. * Hence the `extern inline'.
*/ */
extern inline char *bio_kmap_irq(struct bio *bio, unsigned long *flags) extern inline char *bvec_kmap_irq(struct bio_vec *bvec, unsigned long *flags)
{ {
unsigned long addr; unsigned long addr;
...@@ -240,15 +241,15 @@ extern inline char *bio_kmap_irq(struct bio *bio, unsigned long *flags) ...@@ -240,15 +241,15 @@ extern inline char *bio_kmap_irq(struct bio *bio, unsigned long *flags)
* balancing is a lot nicer this way * balancing is a lot nicer this way
*/ */
local_irq_save(*flags); local_irq_save(*flags);
addr = (unsigned long) kmap_atomic(bio_page(bio), KM_BIO_SRC_IRQ); addr = (unsigned long) kmap_atomic(bvec->bv_page, KM_BIO_SRC_IRQ);
if (addr & ~PAGE_MASK) if (addr & ~PAGE_MASK)
BUG(); BUG();
return (char *) addr + bio_offset(bio); return (char *) addr + bvec->bv_offset;
} }
extern inline void bio_kunmap_irq(char *buffer, unsigned long *flags) extern inline void bvec_kunmap_irq(char *buffer, unsigned long *flags)
{ {
unsigned long ptr = (unsigned long) buffer & PAGE_MASK; unsigned long ptr = (unsigned long) buffer & PAGE_MASK;
...@@ -257,8 +258,19 @@ extern inline void bio_kunmap_irq(char *buffer, unsigned long *flags) ...@@ -257,8 +258,19 @@ extern inline void bio_kunmap_irq(char *buffer, unsigned long *flags)
} }
#else #else
#define bio_kmap_irq(bio, flags) (bio_data(bio)) #define bvec_kmap_irq(bvec, flags) (page_address((bvec)->bv_page) + (bvec)->bv_offset)
#define bio_kunmap_irq(buf, flags) do { *(flags) = 0; } while (0) #define bvec_kunmap_irq(buf, flags) do { *(flags) = 0; } while (0)
#endif #endif
extern inline char *__bio_kmap_irq(struct bio *bio, unsigned short idx,
unsigned long *flags)
{
return bvec_kmap_irq(bio_iovec_idx(bio, idx), flags);
}
#define __bio_kunmap_irq(buf, flags) bvec_kunmap_irq(buf, flags)
#define bio_kmap_irq(bio, flags) \
__bio_kmap_irq((bio), (bio)->bi_idx, (flags))
#define bio_kunmap_irq(buf,flags) __bio_kunmap_irq(buf, flags)
#endif /* __LINUX_BIO_H */ #endif /* __LINUX_BIO_H */
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/backing-dev.h> #include <linux/backing-dev.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/mempool.h> #include <linux/mempool.h>
#include <linux/bio.h>
#include <asm/scatterlist.h> #include <asm/scatterlist.h>
...@@ -36,25 +37,35 @@ struct request { ...@@ -36,25 +37,35 @@ struct request {
* blkdev_dequeue_request! */ * blkdev_dequeue_request! */
unsigned long flags; /* see REQ_ bits below */ unsigned long flags; /* see REQ_ bits below */
sector_t sector; /* Maintain bio traversal state for part by part I/O submission.
unsigned long nr_sectors; * hard_* are block layer internals, no driver should touch them!
*/
sector_t sector; /* next sector to submit */
unsigned long nr_sectors; /* no. of sectors left to submit */
/* no. of sectors left to submit in the current segment */
unsigned int current_nr_sectors; unsigned int current_nr_sectors;
sector_t hard_sector; /* next sector to complete */
unsigned long hard_nr_sectors; /* no. of sectors left to complete */
/* no. of sectors left to complete in the current segment */
unsigned int hard_cur_sectors;
/* no. of segments left to submit in the current bio */
unsigned short nr_cbio_segments;
/* no. of sectors left to submit in the current bio */
unsigned long nr_cbio_sectors;
struct bio *cbio; /* next bio to submit */
struct bio *bio; /* next unfinished bio to complete */
struct bio *biotail;
void *elevator_private; void *elevator_private;
int rq_status; /* should split this into a few status bits */ int rq_status; /* should split this into a few status bits */
struct gendisk *rq_disk; struct gendisk *rq_disk;
int errors; int errors;
unsigned long start_time; unsigned long start_time;
sector_t hard_sector; /* the hard_* are block layer
* internals, no driver should
* touch them
*/
unsigned long hard_nr_sectors;
unsigned int hard_cur_sectors;
struct bio *bio;
struct bio *biotail;
/* Number of scatter-gather DMA addr+len pairs after /* Number of scatter-gather DMA addr+len pairs after
* physical address coalescing is performed. * physical address coalescing is performed.
...@@ -284,6 +295,32 @@ struct request_queue ...@@ -284,6 +295,32 @@ struct request_queue
*/ */
#define blk_queue_headactive(q, head_active) #define blk_queue_headactive(q, head_active)
/* current index into bio being processed for submission */
#define blk_rq_idx(rq) ((rq)->cbio->bi_vcnt - (rq)->nr_cbio_segments)
/* current bio vector being processed */
#define blk_rq_vec(rq) (bio_iovec_idx((rq)->cbio, blk_rq_idx(rq)))
/* current offset with respect to start of the segment being submitted */
#define blk_rq_offset(rq) \
(((rq)->hard_cur_sectors - (rq)->current_nr_sectors) << 9)
/*
* temporarily mapping a (possible) highmem bio (typically for PIO transfer)
*/
/* Assumes rq->cbio != NULL */
static inline char * rq_map_buffer(struct request *rq, unsigned long *flags)
{
return (__bio_kmap_irq(rq->cbio, blk_rq_idx(rq), flags)
+ blk_rq_offset(rq));
}
static inline void rq_unmap_buffer(char *buffer, unsigned long *flags)
{
__bio_kunmap_irq(buffer, flags);
}
/* /*
* q->prep_rq_fn return values * q->prep_rq_fn return values
*/ */
...@@ -362,6 +399,7 @@ static inline request_queue_t *bdev_get_queue(struct block_device *bdev) ...@@ -362,6 +399,7 @@ static inline request_queue_t *bdev_get_queue(struct block_device *bdev)
extern int end_that_request_first(struct request *, int, int); extern int end_that_request_first(struct request *, int, int);
extern int end_that_request_chunk(struct request *, int, int); extern int end_that_request_chunk(struct request *, int, int);
extern void end_that_request_last(struct request *); extern void end_that_request_last(struct request *);
extern int process_that_request_first(struct request *, unsigned int);
extern void end_request(struct request *req, int uptodate); extern void end_request(struct request *req, int uptodate);
static inline void blkdev_dequeue_request(struct request *req) static inline void blkdev_dequeue_request(struct request *req)
......
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