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
*
* Generate definitions needed by assembly language modules.
......@@ -24,12 +24,21 @@
#if defined(__APCS_26__)
#error Sorry, your compiler targets APCS-26 but this kernel requires APCS-32
#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.
#endif
#if __GNUC__ == 2 && __GNUC_MINOR__ == 95
/* shame we can't detect the .1 or .2 releases */
#warning GCC 2.95.2 and earlier miscompiles kernels.
/*
* GCC 2.95.1, 2.95.2: ignores register clobber list in asm().
* GCC 3.0, 3.1: general bad code generation.
* GCC 3.2.0: incorrect function argument offset calculation.
* GCC 3.2.x: miscompiles NEW_AUX_ENT in fs/binfmt_elf.c
* (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
/* Use marker if you need to separate the values later */
......@@ -62,7 +71,6 @@ int main(void)
DEFINE(LPTE_EXEC, L_PTE_EXEC);
DEFINE(LPTE_DIRTY, L_PTE_DIRTY);
BLANK();
BLANK();
DEFINE(PAGE_SZ, PAGE_SIZE);
BLANK();
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
* it under the terms of the GNU General Public License version 2 as
......
......@@ -621,7 +621,7 @@ ENTRY(anakin_active_irqs)
rsb \irqstat, \irqnr, #0
and \irqstat, \irqstat, \irqnr
clz \irqnr, \irqstat
rsb \irqnr, \irqnr, #23
rsb \irqnr, \irqnr, #(31 - PXA_IRQ_SKIP)
1001:
.endm
......
......@@ -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)
{
irq_err_count += 1;
......@@ -222,6 +227,7 @@ static void
__do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs)
{
unsigned int status;
int retval = 0;
spin_unlock(&irq_controller_lock);
......@@ -231,7 +237,7 @@ __do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs)
status = 0;
do {
status |= action->flags;
action->handler(irq, action->dev_id, regs);
retval |= action->handler(irq, action->dev_id, regs);
action = action->next;
} while (action);
......@@ -239,6 +245,19 @@ __do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs)
add_interrupt_randomness(irq);
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)
* 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 retval;
......
......@@ -16,10 +16,18 @@
#include <asm/leds.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 ret;
if (!pm_do_suspend)
return -ENOSYS;
/*
* Suspend "legacy" devices.
*/
......@@ -82,9 +90,26 @@ int suspend(void)
}
#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/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:
* Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
......@@ -102,13 +127,23 @@ int suspend(void)
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}
};
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}
};
......
......@@ -18,10 +18,12 @@
#include <linux/ptrace.h>
#include <linux/user.h>
#include <linux/security.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/system.h>
#include <asm/traps.h>
#include "ptrace.h"
......@@ -32,7 +34,7 @@
* in exit.c or in signal.c.
*/
#if 1
#if 0
/*
* Breakpoint SWI instruction: SWI &9F0001
*/
......@@ -479,25 +481,47 @@ void ptrace_break(struct task_struct *tsk, struct pt_regs *regs)
{
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);
info.si_signo = SIGTRAP;
info.si_errno = 0;
info.si_code = TRAP_BRKPT;
info.si_addr = (void *)instruction_pointer(regs) -
(thumb_mode(regs) ? 2 : 4);
info.si_addr = (void *)instruction_pointer(regs);
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
* actually access the pt_regs stored on the kernel stack.
......
......@@ -34,7 +34,7 @@
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
#include <asm/semaphore.h>
#include <asm/traps.h>
#include "ptrace.h"
......@@ -240,17 +240,56 @@ void die_if_kernel(const char *str, struct pt_regs *regs, int 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)
{
unsigned long *pc;
unsigned int correction = thumb_mode(regs) ? 2 : 4;
unsigned int instr;
struct undef_hook *hook;
siginfo_t info;
void *pc;
/*
* According to the ARM ARM, PC is 2 or 4 bytes ahead, depending
* whether we're in Thumb mode or not.
* According to the ARM ARM, PC is 2 or 4 bytes ahead,
* depending whether we're in Thumb mode or not.
* Correct this offset.
*/
regs->ARM_pc -= thumb_mode(regs) ? 2 : 4;
pc = (unsigned long *)instruction_pointer(regs);
regs->ARM_pc -= correction;
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
printk(KERN_INFO "%s (%d): undefined instruction: pc=%p\n",
......@@ -377,6 +416,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
return 0;
case NR(breakpoint): /* SWI BREAK_POINT */
regs->ARM_pc -= thumb_mode(regs) ? 2 : 4;
ptrace_break(current, regs);
return regs->ARM_r0;
......
......@@ -13,11 +13,7 @@
#include <asm/assembler.h>
#include <asm/constants.h>
#ifndef PLD
#define COPY_COUNT PAGE_SZ/64
#else
#define COPY_COUNT PAGE_SZ/64-1
#endif
#define COPY_COUNT (PAGE_SZ/64 PLD( -1 ))
.text
.align 5
......
......@@ -65,7 +65,7 @@ dc21285_read_config(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 *value)
{
unsigned long addr = dc21285_base_address(bus, devfn);
u32 v;
u32 v = 0xffffffff;
if (addr)
switch (size) {
......@@ -82,8 +82,6 @@ dc21285_read_config(struct pci_bus *bus, unsigned int devfn, int where,
: "=r" (v) : "r" (addr), "r" (where));
break;
}
else
v = 0xffffffff;
*value = v;
......@@ -154,7 +152,7 @@ static void dc21285_enable_error(unsigned long __data)
/*
* 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 status;
......@@ -180,9 +178,11 @@ static void dc21285_abort_irq(int irq, void *dev_id, struct pt_regs *regs)
}
*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;
unsigned int cntl;
......@@ -200,15 +200,19 @@ static void dc21285_serr_irq(int irq, void *dev_id, struct pt_regs *regs)
disable_irq(irq);
timer->expires = jiffies + HZ;
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");
*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;
......@@ -218,9 +222,11 @@ static void dc21285_dparity_irq(int irq, void *dev_id, struct pt_regs *regs)
cmd = *CSR_PCICMD & 0xffff;
*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;
unsigned int cmd;
......@@ -238,6 +244,8 @@ static void dc21285_parity_irq(int irq, void *dev_id, struct pt_regs *regs)
disable_irq(irq);
timer->expires = jiffies + HZ;
add_timer(timer);
return IRQ_HANDLED;
}
int __init dc21285_setup(int nr, struct pci_sys_data *sys)
......
......@@ -43,8 +43,6 @@
* f1500000 15000000 RTC
* f1600000 16000000 UART 0
* f1700000 17000000 UART 1
* f1800000 18000000 Keyboard
* f1900000 19000000 Mouse
* f1a00000 1a000000 Debug LEDs
* f1b00000 1b000000 GPIO
*/
......@@ -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_UART0_BASE), INTEGRATOR_UART0_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_GPIO_BASE), INTEGRATOR_GPIO_BASE, SZ_4K, MT_DEVICE },
{ PCI_MEMORY_VADDR, PHYS_PCI_MEM_BASE, SZ_16M, MT_DEVICE },
......
......@@ -50,9 +50,9 @@ static struct irqchip pxa_internal_chip = {
* Use this instead of directly setting GRER/GFER.
*/
static int GPIO_IRQ_rising_edge[3];
static int GPIO_IRQ_falling_edge[3];
static int GPIO_IRQ_mask[3];
static long GPIO_IRQ_rising_edge[3];
static long GPIO_IRQ_falling_edge[3];
static long GPIO_IRQ_mask[3];
static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
{
......@@ -189,7 +189,6 @@ static struct irqchip pxa_muxed_gpio_chip = {
.ack = pxa_ack_muxed_gpio,
.mask = pxa_mask_muxed_gpio,
.unmask = pxa_unmask_muxed_gpio,
.rerun = pxa_manual_rerun,
.type = pxa_gpio_irq_type,
};
......@@ -217,21 +216,18 @@ void __init pxa_init_irq(void)
/* GPIO 0 and 1 must have their mask bit always set */
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++) {
set_irq_chip(irq, &pxa_low_gpio_chip);
set_irq_handler(irq, do_edge_IRQ);
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++) {
set_irq_chip(irq, &pxa_muxed_gpio_chip);
set_irq_handler(irq, do_edge_IRQ);
......
......@@ -33,57 +33,41 @@
#include "generic.h"
static void lubbock_ack_irq(unsigned int irq)
{
int lubbock_irq = (irq - LUBBOCK_IRQ(0));
LUB_IRQ_SET_CLR &= ~(1 << lubbock_irq);
}
static unsigned long lubbock_irq_enabled;
static void lubbock_mask_irq(unsigned int irq)
{
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)
{
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 = {
.ack = lubbock_ack_irq,
.ack = lubbock_mask_irq,
.mask = lubbock_mask_irq,
.unmask = lubbock_unmask_irq,
};
void lubbock_irq_handler(unsigned int irq, struct irqdesc *desc,
struct pt_regs *regs)
static void lubbock_irq_handler(unsigned int irq, struct irqdesc *desc,
struct pt_regs *regs)
{
unsigned int enabled, pending;
/* get active pending irq mask */
enabled = LUB_IRQ_MASK_EN & 0x003f;
pending = LUB_IRQ_SET_CLR & enabled;
unsigned long pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled;
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 );
/* clear our parent irq */
GEDR(0) = GPIO_bit(0);
/* process them */
irq = LUBBOCK_IRQ(0);
desc = irq_desc + irq;
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;
GEDR(0) = GPIO_bit(0); /* clear our parent irq */
if (likely(pending)) {
irq = LUBBOCK_IRQ(0) + __ffs(pending);
desc = irq_desc + irq;
desc->handle(irq, desc, regs);
}
pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled;
} while (pending);
}
......
......@@ -83,7 +83,7 @@ static void iomd_get_next_sg(struct scatterlist *sg, dma_t *dma)
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;
unsigned long base = dma->dma_base;
......@@ -93,7 +93,7 @@ static void iomd_dma_handle(int irq, void *dev_id, struct pt_regs *regs)
status = iomd_readb(base + ST);
if (!(status & DMA_ST_INT))
return;
return IRQ_HANDLED;
if (status & DMA_ST_OFL && !dma->sg)
break;
......@@ -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);
disable_irq(irq);
return IRQ_HANDLED;
}
static int iomd_request_dma(dmach_t channel, dma_t *dma)
......
......@@ -330,7 +330,7 @@ static int __init consistent_init(void)
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)
{
......
......@@ -6,7 +6,7 @@
# To add an entry into this database, please see Documentation/arm/README,
# 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
#
......@@ -328,3 +328,14 @@ m7100 SA1100_M7100 M7100 316
nipc2 ARCH_NIPC2 NIPC2 317
fu7202 ARCH_FU7202 FU7202 318
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;
static int ether1_open(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 struct net_device_stats *ether1_getstats(struct net_device *dev);
static void ether1_setmulticastlist(struct net_device *dev);
......@@ -908,7 +908,7 @@ ether1_recv_done (struct net_device *dev)
} while (1);
}
static void
static irqreturn_t
ether1_interrupt (int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = (struct net_device *)dev_id;
......@@ -953,7 +953,9 @@ ether1_interrupt (int irq, void *dev_id, struct pt_regs *regs)
NORMALIRQS));
}
} else
outb (CTRL_ACK, REG_CONTROL);
outb (CTRL_ACK, REG_CONTROL);
return IRQ_HANDLED;
}
static 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 int ether3_open (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 struct net_device_stats *ether3_getstats (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)
return 0;
}
static void
static irqreturn_t
ether3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = (struct net_device *)dev_id;
struct dev_priv *priv;
unsigned int status;
unsigned int status, handled = IRQ_NONE;
#if NET_DEBUG > 1
if(net_debug & DEBUG_INT)
......@@ -595,17 +595,20 @@ ether3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (status & STAT_INTRX) {
ether3_outw(CMD_ACKINTRX | priv->regs.command, REG_COMMAND);
ether3_rx(dev, priv, 12);
handled = IRQ_HANDLED;
}
if (status & STAT_INTTX) {
ether3_outw(CMD_ACKINTTX | priv->regs.command, REG_COMMAND);
ether3_tx(dev, priv);
handled = IRQ_HANDLED;
}
#if NET_DEBUG > 1
if(net_debug & DEBUG_INT)
printk("done\n");
#endif
return handled;
}
/*
......
......@@ -2466,18 +2466,14 @@ intr_ret_t acornscsi_sbicintr(AS_Host *host, int in_irq)
* dev_id - device specific data (AS_Host structure)
* regs - processor registers when interrupt occurred
*/
static
void acornscsi_intr(int irq, void *dev_id, struct pt_regs *regs)
static irqreturn_t
acornscsi_intr(int irq, void *dev_id, struct pt_regs *regs)
{
AS_Host *host = (AS_Host *)dev_id;
intr_ret_t ret;
int iostatus;
int in_irq = 0;
if (host->scsi.interrupt)
printk("scsi%d: interrupt re-entered\n", host->host->host_no);
host->scsi.interrupt = 1;
do {
ret = INTR_IDLE;
......@@ -2505,7 +2501,7 @@ void acornscsi_intr(int irq, void *dev_id, struct pt_regs *regs)
in_irq = 1;
} 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)
* dev_id - user-defined (Scsi_Host structure)
* regs - processor registers at interrupt
*/
static void
static irqreturn_t
cumanascsi_2_intr(int irq, void *dev_id, struct pt_regs *regs)
{
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)
......
......@@ -141,12 +141,12 @@ eesoxscsi_terminator_ctl(struct Scsi_Host *host, int on_off)
* dev_id - user-defined (Scsi_Host structure)
* regs - processor registers at interrupt
*/
static void
static irqreturn_t
eesoxscsi_intr(int irq, void *dev_id, struct pt_regs *regs)
{
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)
......
......@@ -1824,9 +1824,10 @@ static void fas216_bus_reset(FAS216_Info *info)
*
* 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;
int handled = IRQ_NONE;
fas216_checkmagic(info);
......@@ -1857,7 +1858,9 @@ void fas216_intr(FAS216_Info *info)
fas216_log(info, 0, "unknown interrupt received:"
" phase %s isr %02X ssr %02X stat %02X",
fas216_drv_phase(info), isr, ssr, stat);
handled = IRQ_HANDLED;
}
return handled;
}
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 *));
*/
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
* 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);
......
......@@ -113,12 +113,12 @@ powertecscsi_terminator_ctl(struct Scsi_Host *host, int on_off)
* dev_id - user-defined (Scsi_Host structure)
* regs - processor registers at interrupt
*/
static void
static irqreturn_t
powertecscsi_intr(int irq, void *dev_id, struct pt_regs *regs)
{
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)
......
......@@ -1616,7 +1616,8 @@ static int __make_request(request_queue_t *q, struct bio *bio)
sector = bio->bi_sector;
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);
/*
......@@ -1672,7 +1673,10 @@ static int __make_request(request_queue_t *q, struct bio *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
* 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)
req->current_nr_sectors = req->hard_cur_sectors = cur_nr_sectors;
req->nr_phys_segments = bio_phys_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->waiting = NULL;
req->bio = req->biotail = bio;
req->cbio = req->bio = req->biotail = bio;
req->rq_disk = bio->bi_bdev->bd_disk;
req->start_time = jiffies;
......@@ -1914,6 +1920,81 @@ int submit_bio(int rw, struct bio *bio)
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)
{
struct bio *bio;
......@@ -1922,8 +2003,6 @@ void blk_recalc_rq_segments(struct request *rq)
if (!rq->bio)
return;
rq->buffer = bio_data(rq->bio);
nr_phys_segs = nr_hw_segs = 0;
rq_for_each_bio(bio, rq) {
/* Force bio hw/phys segs to be recalculated. */
......@@ -1941,11 +2020,24 @@ void blk_recalc_rq_sectors(struct request *rq, int nsect)
{
if (blk_fs_request(rq)) {
rq->hard_sector += nsect;
rq->nr_sectors = rq->hard_nr_sectors -= nsect;
rq->sector = rq->hard_sector;
rq->hard_nr_sectors -= nsect;
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
......@@ -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->hard_cur_sectors = rq->current_nr_sectors;
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->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)
......@@ -2169,6 +2279,7 @@ int __init blk_dev_init(void)
return 0;
};
EXPORT_SYMBOL(process_that_request_first);
EXPORT_SYMBOL(end_that_request_first);
EXPORT_SYMBOL(end_that_request_chunk);
EXPORT_SYMBOL(end_that_request_last);
......
......@@ -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
......@@ -227,8 +227,6 @@ static int sg_io(request_queue_t *q, struct block_device *bdev,
rq->sense_len = 0;
rq->flags |= REQ_BLOCK_PC;
if (writing)
rq->flags |= REQ_RW;
rq->hard_nr_sectors = rq->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,
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);
......@@ -373,8 +371,6 @@ static int sg_scsi_ioctl(request_queue_t *q, struct block_device *bdev,
rq->data = buffer;
rq->data_len = bytes;
rq->flags |= REQ_BLOCK_PC;
if (in_len)
rq->flags |= REQ_RW;
blk_do_rq(q, bdev, rq);
err = rq->errors & 0xff; /* only 8 bit SCSI status */
......
......@@ -146,7 +146,7 @@ static void button_sequence_finished (unsigned long parameters)
* 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) {
del_timer (&button_timer);
......@@ -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.expires = (jiffies + bdelay);
add_timer (&button_timer);
return IRQ_HANDLED;
}
/*
......
......@@ -2070,6 +2070,7 @@ static int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
req.sense = sense;
req.cmd[0] = GPCMD_TEST_UNIT_READY;
req.flags |= REQ_QUIET;
#if ! STANDARD_ATAPI
/* 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)
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)
......@@ -1566,6 +1566,18 @@ static void idedisk_setup (ide_drive_t *drive)
(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 */
if (!drive->cyl || !drive->head || !drive->sect) {
drive->cyl = drive->bios_cyl = id->cyls;
......
......@@ -998,6 +998,7 @@ EXPORT_SYMBOL(save_match);
static void ide_init_queue(ide_drive_t *drive)
{
request_queue_t *q = &drive->queue;
ide_hwif_t *hwif = HWIF(drive);
int max_sectors = 256;
/*
......@@ -1013,8 +1014,10 @@ static void ide_init_queue(ide_drive_t *drive)
drive->queue_setup = 1;
blk_queue_segment_boundary(q, 0xffff);
if (HWIF(drive)->rqsize)
max_sectors = HWIF(drive)->rqsize;
if (!hwif->rqsize)
hwif->rqsize = hwif->addressing ? 256 : 65536;
if (hwif->rqsize < max_sectors)
max_sectors = hwif->rqsize;
blk_queue_max_sectors(q, max_sectors);
/* IDE DMA can do PRD_ENTRIES number of segments. */
......
......@@ -51,9 +51,58 @@
*/
#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_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)
{
#ifdef IDE_TCQ_NIEN
......@@ -502,7 +551,7 @@ static int ide_tcq_configure(ide_drive_t *drive)
return 0;
err:
kfree(args);
return 1;
return -EIO;
}
/*
......@@ -511,6 +560,7 @@ static int ide_tcq_configure(ide_drive_t *drive)
*/
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;
/*
......@@ -529,6 +579,17 @@ static int ide_enable_queued(ide_drive_t *drive, int on)
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
*/
......@@ -582,13 +643,36 @@ int ide_tcq_wait_dataphase(ide_drive_t *drive)
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)
{
if (!drive->using_dma)
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)) {
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;
}
......
......@@ -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;
short x, y, dx, dy, b;
......@@ -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_sync(dev);
return IRQ_HANDLED;
}
static int __init rpcmouse_init(void)
......
......@@ -28,22 +28,27 @@
struct amba_kmi_port {
struct serio io;
struct amba_kmi_port *next;
unsigned long base;
void *base;
unsigned int irq;
unsigned int divisor;
char name[32];
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;
unsigned int status = __raw_readb(KMIIR);
unsigned int status = readb(KMIIR);
int handled = IRQ_NONE;
while (status & KMIIR_RXINTR) {
serio_interrupt(&kmi->io, __raw_readb(KMIDATA), 0, regs);
status = __raw_readb(KMIIR);
serio_interrupt(&kmi->io, readb(KMIDATA), 0, regs);
status = readb(KMIIR);
handled = IRQ_HANDLED;
}
return handled;
}
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;
unsigned int timeleft = 10000; /* timeout in 100ms */
while ((__raw_readb(KMISTAT) & KMISTAT_TXEMPTY) == 0 && timeleft--)
while ((readb(KMISTAT) & KMISTAT_TXEMPTY) == 0 && timeleft--)
udelay(10);
if (timeleft)
__raw_writeb(val, KMIDATA);
writeb(val, KMIDATA);
return timeleft ? 0 : SERIO_TIMEOUT;
}
......@@ -65,17 +70,17 @@ static int amba_kmi_open(struct serio *io)
struct amba_kmi_port *kmi = io->driver;
int ret;
__raw_writeb(kmi->divisor, KMICLKDIV);
__raw_writeb(KMICR_EN, KMICR);
writeb(kmi->divisor, KMICLKDIV);
writeb(KMICR_EN, KMICR);
ret = request_irq(kmi->irq, amba_kmi_int, 0, kmi->phys, kmi);
if (ret) {
printk(KERN_ERR "kmi: failed to claim IRQ%d\n", kmi->irq);
__raw_writeb(0, KMICR);
writeb(0, KMICR);
return ret;
}
__raw_writeb(KMICR_EN | KMICR_RXINTREN, KMICR);
writeb(KMICR_EN | KMICR_RXINTREN, KMICR);
return 0;
}
......@@ -84,9 +89,9 @@ static void amba_kmi_close(struct serio *io)
{
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;
......@@ -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.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->divisor = 24 / 8 - 1;
kmi->next = list;
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);
return 0;
}
static int __init amba_kmi_init(void)
{
amba_kmi_init_one("keyboard", IO_ADDRESS(KMI0_BASE), IRQ_KMIINT0, 0);
amba_kmi_init_one("mouse", IO_ADDRESS(KMI1_BASE), IRQ_KMIINT1, 1);
amba_kmi_init_one("keyboard", KMI0_BASE, IRQ_KMIINT0, 0);
amba_kmi_init_one("mouse", KMI1_BASE, IRQ_KMIINT1, 1);
return 0;
}
......@@ -139,6 +156,8 @@ static void __exit amba_kmi_exit(void)
next = kmi->next;
serio_unregister_port(&kmi->io);
iounmap(kmi->base);
release_resource(kmi->res);
kfree(kmi);
kmi = next;
......
......@@ -54,20 +54,24 @@ static int rpckbd_write(struct serio *port, unsigned char val)
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;
unsigned int byte;
int handled = IRQ_NONE;
while (iomd_readb(IOMD_KCTRL) & (1 << 5)) {
byte = iomd_readb(IOMD_KARTRX);
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)
......
......@@ -41,10 +41,11 @@ struct ps2if {
* at the most one, but we loop for safety. If there was a
* 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;
unsigned int scancode, flag, status;
int handled = IRQ_NONE;
status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
while (status & PS2STAT_RXF) {
......@@ -62,13 +63,17 @@ static void ps2_rxint(int irq, void *dev_id, struct pt_regs *regs)
serio_interrupt(&ps2if->io, scancode, flag, regs);
status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
handled = IRQ_HANDLED;
}
return handled;
}
/*
* 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;
unsigned int status;
......@@ -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);
}
spin_unlock(&ps2if->lock);
return IRQ_HANDLED;
}
/*
......
......@@ -302,11 +302,8 @@ static int proc_read_clients(char *buf, char **start, off_t pos,
======================================================================*/
static int setup_socket(socket_info_t *);
static void shutdown_socket(socket_info_t *);
static void reset_socket(socket_info_t *);
static void unreset_socket(socket_info_t *);
static void parse_events(void *info, u_int events);
static int pccardd(void *__skt);
void pcmcia_unregister_socket(struct class_device *dev);
#define to_class_data(dev) dev->class_data
......@@ -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);
socket_info_t *s_info;
unsigned int i, j;
unsigned int i, j, ret;
if (!cls_d)
return -EINVAL;
......@@ -330,6 +327,7 @@ int pcmcia_register_socket(struct class_device *class_dev)
memset(s_info, 0, cls_d->nsock * sizeof(socket_info_t));
cls_d->s_info = s_info;
ret = 0;
/* socket initialization */
for (i = 0; i < cls_d->nsock; i++) {
......@@ -344,7 +342,7 @@ int pcmcia_register_socket(struct class_device *class_dev)
s->erase_busy.next = s->erase_busy.prev = &s->erase_busy;
INIT_LIST_HEAD(&s->cis_cache);
spin_lock_init(&s->lock);
/* TBD: remove usage of socket_table, use class_for_each_dev instead */
for (j = 0; j < sockets; j++)
if (socket_table[j] == NULL) break;
......@@ -353,6 +351,20 @@ int pcmcia_register_socket(struct class_device *class_dev)
init_socket(s);
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
if (proc_pccard) {
char name[3];
......@@ -368,7 +380,7 @@ int pcmcia_register_socket(struct class_device *class_dev)
}
#endif
}
return 0;
return ret;
} /* pcmcia_register_socket */
......@@ -407,8 +419,12 @@ void pcmcia_unregister_socket(struct class_device *class_dev)
remove_proc_entry(name, proc_pccard);
}
#endif
shutdown_socket(s);
if (s->thread) {
init_completion(&s->thread_done);
s->thread = NULL;
wake_up(&s->thread_wait);
wait_for_completion(&s->thread_done);
}
release_cis_mem(s);
while (s->clients) {
client = s->clients;
......@@ -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);
/*
* 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)
{
client_t **c;
......@@ -505,132 +512,6 @@ static void shutdown_socket(socket_info_t *s)
free_regions(&s->c_region);
} /* 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
......@@ -661,61 +542,266 @@ static int send_event(socket_info_t *s, event_t event, int priority)
return ret;
} /* send_event */
static void do_shutdown(socket_info_t *s)
static void pcmcia_error(socket_info_t *skt, const char *fmt, ...)
{
client_t *client;
if (s->state & SOCKET_SHUTDOWN_PENDING)
return;
s->state |= SOCKET_SHUTDOWN_PENDING;
send_event(s, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH);
for (client = s->clients; client; client = client->next)
if (!(client->Attributes & INFO_MASTER_CLIENT))
client->state |= CLIENT_STALE;
if (s->state & (SOCKET_SETUP_PENDING|SOCKET_RESET_PENDING)) {
DEBUG(0, "cs: flushing pending setup\n");
s->state &= ~EVENT_MASK;
}
cs_sleep(shutdown_delay);
s->state &= ~SOCKET_PRESENT;
shutdown_socket(s);
static char buf[128];
va_list ap;
int len;
va_start(ap, fmt);
len = vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
buf[len] = '\0';
printk(KERN_ERR "PCMCIA: socket %p: %s", skt, buf);
}
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;
if (events & SS_DETECT) {
int status;
get_socket_status(s, &status);
if ((s->state & SOCKET_PRESENT) &&
(!(s->state & SOCKET_SUSPEND) ||
!(status & SS_DETECT)))
do_shutdown(s);
if (status & SS_DETECT) {
if (s->state & SOCKET_SETUP_PENDING) {
DEBUG(1, "cs: delaying pending setup\n");
return;
}
s->state |= SOCKET_SETUP_PENDING;
if (s->state & SOCKET_SUSPEND)
cs_sleep(resume_delay);
else
cs_sleep(setup_delay);
s->socket.flags |= SS_DEBOUNCED;
if (setup_socket(s) == 0)
s->state &= ~SOCKET_SETUP_PENDING;
s->socket.flags &= ~SS_DEBOUNCED;
client_t *client;
send_event(skt, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH);
for (client = skt->clients; client; client = client->next)
if (!(client->Attributes & INFO_MASTER_CLIENT))
client->state |= CLIENT_STALE;
}
static void socket_shutdown(socket_info_t *skt)
{
socket_remove_drivers(skt);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(cs_to_timeout(shutdown_delay));
skt->state &= ~SOCKET_PRESENT;
shutdown_socket(skt);
}
static int socket_reset(socket_info_t *skt)
{
int status, i;
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)
send_event(s, CS_EVENT_BATTERY_DEAD, CS_EVENT_PRI_LOW);
if (events & SS_BATWARN)
send_event(s, CS_EVENT_BATTERY_LOW, CS_EVENT_PRI_LOW);
if (events & SS_READY) {
if (!(s->state & SOCKET_RESET_PENDING))
send_event(s, CS_EVENT_READY_CHANGE, CS_EVENT_PRI_LOW);
else DEBUG(1, "cs: ready change during reset\n");
}
pcmcia_error(skt, "time out after reset.\n");
return CS_GENERAL_FAILURE;
}
static int socket_setup(socket_info_t *skt, int initial_delay)
{
int status, i;
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 */
/*======================================================================
......@@ -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)) {
send_event(s, CS_EVENT_PM_SUSPEND, CS_EVENT_PRI_LOW);
suspend_socket(s);
s->state |= SOCKET_SUSPEND;
}
down(&skt->skt_sem);
socket_suspend(skt);
up(&skt->skt_sem);
}
void pcmcia_resume_socket (socket_info_t *s)
void pcmcia_resume_socket (socket_info_t *skt)
{
int stat;
/* Do this just to reinitialize the socket */
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);
down(&skt->skt_sem);
socket_resume(skt);
up(&skt->skt_sem);
}
......@@ -1461,15 +1538,8 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req)
s = socket_table[ns];
if (++s->real_clients == 1) {
int status;
register_callback(s, &parse_events, s);
get_socket_status(s, &status);
if ((status & SS_DETECT) &&
!(s->state & SOCKET_SETUP_PENDING)) {
s->state |= SOCKET_SETUP_PENDING;
if (setup_socket(s) == 0)
s->state &= ~SOCKET_SETUP_PENDING;
}
parse_events(s, SS_DETECT);
}
*handle = client;
......@@ -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 i, ret;
socket_info_t *s;
socket_info_t *skt;
int ret;
if (CHECK_HANDLE(handle))
return CS_BAD_HANDLE;
i = handle->Socket; s = socket_table[i];
if (!(s->state & SOCKET_PRESENT))
return CS_NO_CARD;
if (s->state & SOCKET_RESET_PENDING)
return CS_IN_USE;
s->state |= SOCKET_RESET_PENDING;
if (CHECK_HANDLE(handle))
return CS_BAD_HANDLE;
DEBUG(1, "cs: resetting socket %d\n", handle->Socket);
skt = SOCKET(handle);
down(&skt->skt_sem);
do {
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);
if (ret != 0) {
s->state &= ~SOCKET_RESET_PENDING;
handle->event_callback_args.info = (void *)(u_long)ret;
EVENT(handle, CS_EVENT_RESET_COMPLETE, CS_EVENT_PRI_LOW);
} else {
DEBUG(1, "cs: resetting socket %d\n", i);
send_event(s, CS_EVENT_RESET_PHYSICAL, CS_EVENT_PRI_LOW);
s->reset_handle = handle;
reset_socket(s);
}
return CS_SUCCESS;
ret = send_event(skt, CS_EVENT_RESET_REQUEST, CS_EVENT_PRI_LOW);
if (ret == 0) {
send_event(skt, CS_EVENT_RESET_PHYSICAL, CS_EVENT_PRI_LOW);
if (socket_reset(skt) == CS_SUCCESS)
send_event(skt, CS_EVENT_CARD_RESET, CS_EVENT_PRI_LOW);
}
handle->event_callback_args.info = (void *)(u_long)ret;
EVENT(handle, CS_EVENT_RESET_COMPLETE, CS_EVENT_PRI_LOW);
ret = CS_SUCCESS;
} while (0);
up(&skt->skt_sem);
return ret;
} /* reset_card */
/*======================================================================
......@@ -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 i;
socket_info_t *s;
socket_info_t *skt;
int ret;
if (CHECK_HANDLE(handle))
return CS_BAD_HANDLE;
i = handle->Socket; s = socket_table[i];
if (!(s->state & SOCKET_PRESENT))
return CS_NO_CARD;
if (s->state & SOCKET_SUSPEND)
return CS_IN_USE;
DEBUG(1, "cs: suspending socket %d\n", i);
send_event(s, CS_EVENT_PM_SUSPEND, CS_EVENT_PRI_LOW);
suspend_socket(s);
s->state |= SOCKET_SUSPEND;
if (CHECK_HANDLE(handle))
return CS_BAD_HANDLE;
DEBUG(1, "cs: suspending socket %d\n", handle->Socket);
skt = SOCKET(handle);
down(&skt->skt_sem);
do {
if (!(skt->state & SOCKET_PRESENT)) {
ret = CS_NO_CARD;
break;
}
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 */
int pcmcia_resume_card(client_handle_t handle, client_req_t *req)
{
int i;
socket_info_t *s;
socket_info_t *skt;
int ret;
if (CHECK_HANDLE(handle))
return CS_BAD_HANDLE;
i = handle->Socket; s = socket_table[i];
if (!(s->state & SOCKET_PRESENT))
return CS_NO_CARD;
if (!(s->state & SOCKET_SUSPEND))
return CS_IN_USE;
DEBUG(1, "cs: waking up socket %d\n", i);
setup_socket(s);
if (CHECK_HANDLE(handle))
return CS_BAD_HANDLE;
DEBUG(1, "cs: waking up socket %d\n", handle->Socket);
skt = SOCKET(handle);
down(&skt->skt_sem);
do {
if (!(skt->state & SOCKET_PRESENT)) {
ret = CS_NO_CARD;
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 */
/*======================================================================
......@@ -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 i, ret;
socket_info_t *s;
u_long flags;
socket_info_t *skt;
int ret;
if (CHECK_HANDLE(handle))
return CS_BAD_HANDLE;
i = handle->Socket; s = socket_table[i];
if (!(s->state & SOCKET_PRESENT))
return CS_NO_CARD;
if (CHECK_HANDLE(handle))
return CS_BAD_HANDLE;
DEBUG(1, "cs: user eject request on socket %d\n", handle->Socket);
skt = SOCKET(handle);
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);
if (ret != 0)
return ret;
socket_shutdown(skt);
ret = CS_SUCCESS;
} while (0);
up(&skt->skt_sem);
spin_lock_irqsave(&s->lock, flags);
do_shutdown(s);
spin_unlock_irqrestore(&s->lock, flags);
return CS_SUCCESS;
return ret;
} /* eject_card */
int pcmcia_insert_card(client_handle_t handle, client_req_t *req)
{
int i, status;
socket_info_t *s;
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);
socket_info_t *skt;
int ret;
spin_lock_irqsave(&s->lock, flags);
if (!(s->state & SOCKET_SETUP_PENDING)) {
s->state |= SOCKET_SETUP_PENDING;
spin_unlock_irqrestore(&s->lock, flags);
get_socket_status(s, &status);
if ((status & SS_DETECT) == 0 || (setup_socket(s) == 0)) {
s->state &= ~SOCKET_SETUP_PENDING;
return CS_NO_CARD;
}
} else
spin_unlock_irqrestore(&s->lock, flags);
if (CHECK_HANDLE(handle))
return CS_BAD_HANDLE;
DEBUG(1, "cs: user insert request on socket %d\n", handle->Socket);
skt = SOCKET(handle);
down(&skt->skt_sem);
do {
if (skt->state & SOCKET_PRESENT) {
ret = CS_IN_USE;
break;
}
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 */
/*======================================================================
......
......@@ -133,7 +133,6 @@ typedef struct socket_info_t {
u_short lock_count;
client_handle_t clients;
u_int real_clients;
client_handle_t reset_handle;
pccard_mem_map cis_mem;
u_char *cis_virt;
config_t *config;
......@@ -155,6 +154,14 @@ typedef struct socket_info_t {
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc;
#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;
/* Flags in config state */
......
......@@ -120,7 +120,6 @@ sa1100_pcmcia_set_mecr(struct sa1100_pcmcia_socket *skt, unsigned int cpu_clock)
unsigned long flags;
unsigned short speed;
unsigned int bs_io, bs_mem, bs_attr;
int i;
speed = calc_speed(skt->spd_io, MAX_IO_WIN, SA1100_PCMCIA_IO_ACCESS);
bs_io = skt->ops->socket_get_timing(skt, cpu_clock, speed);
......@@ -324,13 +323,15 @@ static void sa1100_pcmcia_poll_event(unsigned long dummy)
* handling code performs scheduling operations which cannot be
* 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;
DEBUG(3, "%s(): servicing IRQ %d\n", __FUNCTION__, irq);
schedule_work(&skt->work);
return IRQ_HANDLED;
}
/* sa1100_pcmcia_register_callback()
......
......@@ -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 tty_struct *tty = port->info->tty;
......@@ -97,7 +97,7 @@ static void serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *regs)
tty->flip.work.func((void *)tty);
if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
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)
status = *CSR_UARTFLG;
}
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 circ_buf *xmit = &port->info->xmit;
......@@ -155,11 +158,11 @@ static void serial21285_tx_chars(int irq, void *dev_id, struct pt_regs *regs)
*CSR_UARTDR = port->x_char;
port->icount.tx++;
port->x_char = 0;
return;
goto out;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
serial21285_stop_tx(port, 0);
return;
goto out;
}
do {
......@@ -175,6 +178,9 @@ static void serial21285_tx_chars(int irq, void *dev_id, struct pt_regs *regs)
if (uart_circ_empty(xmit))
serial21285_stop_tx(port, 0);
out:
return IRQ_HANDLED;
}
static unsigned int serial21285_tx_empty(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);
}
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;
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)
status = UART_GET_INT_STATUS(port);
} while (status & (AMBA_UARTIIR_RTIS | AMBA_UARTIIR_RIS |
AMBA_UARTIIR_TIS));
return IRQ_HANDLED;
}
static unsigned int ambauart_tx_empty(struct uart_port *port)
......
......@@ -312,7 +312,7 @@ static void sa1100_tx_chars(struct sa1100_port *sport)
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;
unsigned int status, pass_counter = 0;
......@@ -347,6 +347,8 @@ static void sa1100_int(int irq, void *dev_id, struct pt_regs *regs)
~UTSR0_TFS;
} while (status & (UTSR0_TFS | UTSR0_RFS | UTSR0_RID));
spin_unlock(&sport->port.lock);
return IRQ_HANDLED;
}
/*
......@@ -830,7 +832,7 @@ static struct console sa1100_console = {
.setup = sa1100_console_setup,
.flags = CON_PRINTBUFFER,
.index = -1,
.data = sa1100_reg,
.data = &sa1100_reg,
};
static int __init sa1100_rs_console_init(void)
......
......@@ -14,10 +14,11 @@
#ifndef __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)
{
do_timer(regs);
return IRQ_HANDLED;
}
void __init time_init(void)
......
......@@ -14,11 +14,13 @@
*/
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_set_rtc();
do_profile(regs);
return IRQ_HANDLED;
}
/*
......
......@@ -11,7 +11,8 @@
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_set_rtc();
......@@ -26,6 +27,7 @@ static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
*((volatile unsigned int *)LED_ADDRESS) = state;
}
}
return IRQ_HANDLED;
}
/*
......
......@@ -25,11 +25,13 @@ extern void clps711x_setup_timer(void);
/*
* 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_timer(regs);
do_profile(regs);
return IRQ_HANDLED;
}
/*
......
......@@ -74,7 +74,8 @@ static unsigned long ebsa110_gettimeoffset(void)
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;
......@@ -91,6 +92,8 @@ static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
do_leds();
do_timer(regs);
do_profile(regs);
return IRQ_HANDLED;
}
/*
......
......@@ -69,7 +69,8 @@ static unsigned long isa_gettimeoffset(void)
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())
do_leds();
......@@ -77,6 +78,8 @@ static void isa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
do_timer(regs);
do_set_rtc();
do_profile(regs);
return IRQ_HANDLED;
}
static unsigned long __init get_isa_cmos_time(void)
......@@ -186,7 +189,8 @@ static unsigned long timer1_gettimeoffset (void)
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;
......@@ -195,6 +199,8 @@ static void timer1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
do_timer(regs);
do_set_rtc();
do_profile(regs);
return IRQ_HANDLED;
}
/*
......
......@@ -27,7 +27,8 @@
/*
* 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
......@@ -36,6 +37,8 @@ static void excalibur_timer_interrupt(int irq, void *dev_id, struct pt_regs *reg
do_leds();
do_timer(regs);
do_profile(regs);
return IRQ_HANDLED;
}
/*
......
......@@ -98,7 +98,8 @@ static unsigned long integrator_gettimeoffset(void)
/*
* 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;
......@@ -108,6 +109,8 @@ static void integrator_timer_interrupt(int irq, void *dev_id, struct pt_regs *re
do_leds();
do_timer(regs);
do_profile(regs);
return IRQ_HANDLED;
}
/*
......
......@@ -42,11 +42,14 @@
/*
* 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_profile(regs);
RTC_RTCC = 0; /* Clear interrupt */
return IRQ_HANDLED;
}
/*
......
......@@ -14,7 +14,8 @@
* 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;
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)
__raw_readb(DUART_BASE + 0x14);
__raw_readb(DUART_BASE + 0x14);
do_timer(regs);
do_timer(regs);
return IRQ_HANDLED;
}
void __init time_init(void)
......
......@@ -10,9 +10,10 @@
* 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 IRQ_HWUART PXA_IRQ(7) /* HWUART Transmit/Receive/Error */
#define IRQ_GPIO0 PXA_IRQ(8) /* GPIO0 Edge Detect */
#define IRQ_GPIO1 PXA_IRQ(9) /* GPIO1 Edge Detect */
#define IRQ_GPIO_2_80 PXA_IRQ(10) /* GPIO[2-80] Edge Detect */
......@@ -20,6 +21,8 @@
#define IRQ_PMU PXA_IRQ(12) /* Performance Monitoring Unit */
#define IRQ_I2S PXA_IRQ(13) /* I2S 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_I2C PXA_IRQ(18) /* I2C Service Request */
#define IRQ_ICP PXA_IRQ(19) /* ICP Transmit/Receive/Error */
......
......@@ -47,7 +47,8 @@ static unsigned long pxa_gettimeoffset (void)
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;
......@@ -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 */
next_match = (OSMR0 += LATCH);
} while( (signed long)(next_match - OSCR) <= 0 );
return IRQ_HANDLED;
}
void __init time_init(void)
......
......@@ -14,11 +14,14 @@
*/
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_set_rtc();
do_profile(regs);
return IRQ_HANDLED;
}
/*
......
......@@ -72,7 +72,8 @@ static unsigned long sa1100_gettimeoffset (void)
* lost_ticks (updated in do_timer()) and the match reg value, so we
* 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;
......@@ -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);
do_profile(regs);
return IRQ_HANDLED;
}
void __init time_init(void)
......
......@@ -13,11 +13,14 @@
#define IRQ_TIMER 0
#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_timer(regs);
do_profile(regs);
return IRQ_HANDLED;
}
/*
......
......@@ -20,13 +20,16 @@
#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 */
__raw_writel(1, FPGA1CONT + 0xc);
__raw_writel(0, FPGA1CONT + 0xc);
do_timer(regs);
return IRQ_HANDLED;
}
void __init time_init(void)
......
......@@ -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)
{
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);
#endif
#if __LINUX_ARM_ARCH__ < 5
/*
* ffz = Find First Zero in word. Undefined if no zero exists,
* so code should check against ~0UL first..
......@@ -326,6 +328,23 @@ static inline unsigned long __ffs(unsigned long word)
#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
* 128 bits are unlikely to be set.
......
......@@ -10,8 +10,6 @@
#ifndef __ASM_BUGS_H
#define __ASM_BUGS_H
#include <asm/proc-fns.h>
#define check_bugs() do { } while (0)
#endif
......@@ -54,39 +54,37 @@ struct machine_desc {
#define MACHINE_START(_type,_name) \
const struct machine_desc __mach_desc_##_type \
__attribute__((__section__(".arch.info"))) = { \
nr: MACH_TYPE_##_type, \
name: _name,
.nr = MACH_TYPE_##_type, \
.name = _name,
#define MAINTAINER(n)
#define BOOT_MEM(_pram,_pio,_vio) \
phys_ram: _pram, \
phys_io: _pio, \
io_pg_offst: ((_vio)>>18)&0xfffc,
.phys_ram = _pram, \
.phys_io = _pio, \
.io_pg_offst = ((_vio)>>18)&0xfffc,
#define BOOT_PARAMS(_params) \
param_offset: _params,
.param_offset = _params,
#define VIDEO(_start,_end) \
video_start: _start, \
video_end: _end,
.video_start = _start, \
.video_end = _end,
#define DISABLE_PARPORT(_n) \
reserve_lp##_n: 1,
#define BROKEN_HLT /* unused */
.reserve_lp##_n = 1,
#define SOFT_REBOOT \
soft_reboot: 1,
.soft_reboot = 1,
#define FIXUP(_func) \
fixup: _func,
.fixup = _func,
#define MAPIO(_func) \
map_io: _func,
.map_io = _func,
#define INITIRQ(_func) \
init_irq: _func,
.init_irq = _func,
#define MACHINE_END \
};
......
......@@ -74,6 +74,29 @@ unsigned long get_wchan(struct task_struct *p);
*/
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 /* __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 {
#define bio_iovec(bio) bio_iovec_idx((bio), (bio)->bi_idx)
#define bio_page(bio) bio_iovec((bio))->bv_page
#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_cur_sectors(bio) (bio_iovec(bio)->bv_len >> 9)
#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);
#ifdef CONFIG_HIGHMEM
/*
* 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.
* 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;
......@@ -240,15 +241,15 @@ extern inline char *bio_kmap_irq(struct bio *bio, unsigned long *flags)
* balancing is a lot nicer this way
*/
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)
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;
......@@ -257,8 +258,19 @@ extern inline void bio_kunmap_irq(char *buffer, unsigned long *flags)
}
#else
#define bio_kmap_irq(bio, flags) (bio_data(bio))
#define bio_kunmap_irq(buf, flags) do { *(flags) = 0; } while (0)
#define bvec_kmap_irq(bvec, flags) (page_address((bvec)->bv_page) + (bvec)->bv_offset)
#define bvec_kunmap_irq(buf, flags) do { *(flags) = 0; } while (0)
#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 */
......@@ -11,6 +11,7 @@
#include <linux/backing-dev.h>
#include <linux/wait.h>
#include <linux/mempool.h>
#include <linux/bio.h>
#include <asm/scatterlist.h>
......@@ -36,25 +37,35 @@ struct request {
* blkdev_dequeue_request! */
unsigned long flags; /* see REQ_ bits below */
sector_t sector;
unsigned long nr_sectors;
/* Maintain bio traversal state for part by part I/O submission.
* 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;
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;
int rq_status; /* should split this into a few status bits */
struct gendisk *rq_disk;
int errors;
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
* physical address coalescing is performed.
......@@ -284,6 +295,32 @@ struct request_queue
*/
#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
*/
......@@ -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_chunk(struct request *, int, int);
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);
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