Commit 9707b271 authored by Jeff Garzik's avatar Jeff Garzik

Merge branch 'master'

parents 8fc65162 402a26f0
As of the Linux 2.6.10 kernel, it is now possible to change the
IO scheduler for a given block device on the fly (thus making it possible,
for instance, to set the CFQ scheduler for the system default, but
set a specific device to use the anticipatory or noop schedulers - which
can improve that device's throughput).
To set a specific scheduler, simply do this:
echo SCHEDNAME > /sys/block/DEV/queue/scheduler
where SCHEDNAME is the name of a defined IO scheduler, and DEV is the
device name (hda, hdb, sga, or whatever you happen to have).
The list of defined schedulers can be found by simply doing
a "cat /sys/block/DEV/queue/scheduler" - the list of valid names
will be displayed, with the currently selected scheduler in brackets:
# cat /sys/block/hda/queue/scheduler
noop anticipatory deadline [cfq]
# echo anticipatory > /sys/block/hda/queue/scheduler
# cat /sys/block/hda/queue/scheduler
noop [anticipatory] deadline cfq
...@@ -53,4 +53,4 @@ the CPUFreq Mailing list: ...@@ -53,4 +53,4 @@ the CPUFreq Mailing list:
* http://lists.linux.org.uk/mailman/listinfo/cpufreq * http://lists.linux.org.uk/mailman/listinfo/cpufreq
Clock and voltage scaling for the SA-1100: Clock and voltage scaling for the SA-1100:
* http://www.lart.tudelft.nl/projects/scaling * http://www.lartmaker.nl/projects/scaling
...@@ -25,8 +25,9 @@ Who: Adrian Bunk <bunk@stusta.de> ...@@ -25,8 +25,9 @@ Who: Adrian Bunk <bunk@stusta.de>
--------------------------- ---------------------------
What: drivers depending on OBSOLETE_OSS_DRIVER What: drivers that were depending on OBSOLETE_OSS_DRIVER
When: January 2006 (config options already removed)
When: before 2.6.19
Why: OSS drivers with ALSA replacements Why: OSS drivers with ALSA replacements
Who: Adrian Bunk <bunk@stusta.de> Who: Adrian Bunk <bunk@stusta.de>
......
...@@ -3,14 +3,11 @@ ...@@ -3,14 +3,11 @@
-------------------- --------------------
$Id: driver,v 1.10 2002/07/22 15:27:30 rmk Exp $
This document is meant as a brief overview of some aspects of the new serial This document is meant as a brief overview of some aspects of the new serial
driver. It is not complete, any questions you have should be directed to driver. It is not complete, any questions you have should be directed to
<rmk@arm.linux.org.uk> <rmk@arm.linux.org.uk>
The reference implementation is contained within serial_amba.c. The reference implementation is contained within amba_pl011.c.
...@@ -31,6 +28,11 @@ The serial core provides a few helper functions. This includes identifing ...@@ -31,6 +28,11 @@ The serial core provides a few helper functions. This includes identifing
the correct port structure (via uart_get_console) and decoding command line the correct port structure (via uart_get_console) and decoding command line
arguments (uart_parse_options). arguments (uart_parse_options).
There is also a helper function (uart_write_console) which performs a
character by character write, translating newlines to CRLF sequences.
Driver writers are recommended to use this function rather than implementing
their own version.
Locking Locking
------- -------
...@@ -86,6 +88,7 @@ hardware. ...@@ -86,6 +88,7 @@ hardware.
- TIOCM_DTR DTR signal. - TIOCM_DTR DTR signal.
- TIOCM_OUT1 OUT1 signal. - TIOCM_OUT1 OUT1 signal.
- TIOCM_OUT2 OUT2 signal. - TIOCM_OUT2 OUT2 signal.
- TIOCM_LOOP Set the port into loopback mode.
If the appropriate bit is set, the signal should be driven If the appropriate bit is set, the signal should be driven
active. If the bit is clear, the signal should be driven active. If the bit is clear, the signal should be driven
inactive. inactive.
...@@ -141,6 +144,10 @@ hardware. ...@@ -141,6 +144,10 @@ hardware.
enable_ms(port) enable_ms(port)
Enable the modem status interrupts. Enable the modem status interrupts.
This method may be called multiple times. Modem status
interrupts should be disabled when the shutdown method is
called.
Locking: port->lock taken. Locking: port->lock taken.
Interrupts: locally disabled. Interrupts: locally disabled.
This call must not sleep This call must not sleep
...@@ -160,6 +167,8 @@ hardware. ...@@ -160,6 +167,8 @@ hardware.
state. Enable the port for reception. It should not activate state. Enable the port for reception. It should not activate
RTS nor DTR; this will be done via a separate call to set_mctrl. RTS nor DTR; this will be done via a separate call to set_mctrl.
This method will only be called when the port is initially opened.
Locking: port_sem taken. Locking: port_sem taken.
Interrupts: globally disabled. Interrupts: globally disabled.
...@@ -169,6 +178,11 @@ hardware. ...@@ -169,6 +178,11 @@ hardware.
RTS nor DTR; this will have already been done via a separate RTS nor DTR; this will have already been done via a separate
call to set_mctrl. call to set_mctrl.
Drivers must not access port->info once this call has completed.
This method will only be called when there are no more users of
this port.
Locking: port_sem taken. Locking: port_sem taken.
Interrupts: caller dependent. Interrupts: caller dependent.
......
...@@ -32,7 +32,16 @@ The output of "cat /proc/meminfo" will have lines like: ...@@ -32,7 +32,16 @@ The output of "cat /proc/meminfo" will have lines like:
..... .....
HugePages_Total: xxx HugePages_Total: xxx
HugePages_Free: yyy HugePages_Free: yyy
Hugepagesize: zzz KB HugePages_Rsvd: www
Hugepagesize: zzz kB
where:
HugePages_Total is the size of the pool of hugepages.
HugePages_Free is the number of hugepages in the pool that are not yet
allocated.
HugePages_Rsvd is short for "reserved," and is the number of hugepages
for which a commitment to allocate from the pool has been made, but no
allocation has yet been made. It's vaguely analogous to overcommit.
/proc/filesystems should also show a filesystem of type "hugetlbfs" configured /proc/filesystems should also show a filesystem of type "hugetlbfs" configured
in the kernel. in the kernel.
......
...@@ -411,6 +411,7 @@ AX.25 NETWORK LAYER ...@@ -411,6 +411,7 @@ AX.25 NETWORK LAYER
P: Ralf Baechle P: Ralf Baechle
M: ralf@linux-mips.org M: ralf@linux-mips.org
L: linux-hams@vger.kernel.org L: linux-hams@vger.kernel.org
W: http://www.linux-ax25.org/
S: Maintained S: Maintained
BAYCOM/HDLCDRV DRIVERS FOR AX.25 BAYCOM/HDLCDRV DRIVERS FOR AX.25
...@@ -1463,6 +1464,13 @@ M: support@pathscale.com ...@@ -1463,6 +1464,13 @@ M: support@pathscale.com
L: openib-general@openib.org L: openib-general@openib.org
S: Supported S: Supported
IPMI SUBSYSTEM
P: Corey Minyard
M: minyard@acm.org
L: openipmi-developer@lists.sourceforge.net
W: http://openipmi.sourceforge.net/
S: Supported
IPX NETWORK LAYER IPX NETWORK LAYER
P: Arnaldo Carvalho de Melo P: Arnaldo Carvalho de Melo
M: acme@conectiva.com.br M: acme@conectiva.com.br
...@@ -1875,6 +1883,7 @@ NETROM NETWORK LAYER ...@@ -1875,6 +1883,7 @@ NETROM NETWORK LAYER
P: Ralf Baechle P: Ralf Baechle
M: ralf@linux-mips.org M: ralf@linux-mips.org
L: linux-hams@vger.kernel.org L: linux-hams@vger.kernel.org
W: http://www.linux-ax25.org/
S: Maintained S: Maintained
NETWORK BLOCK DEVICE NETWORK BLOCK DEVICE
...@@ -2266,6 +2275,7 @@ ROSE NETWORK LAYER ...@@ -2266,6 +2275,7 @@ ROSE NETWORK LAYER
P: Ralf Baechle P: Ralf Baechle
M: ralf@linux-mips.org M: ralf@linux-mips.org
L: linux-hams@vger.kernel.org L: linux-hams@vger.kernel.org
W: http://www.linux-ax25.org/
S: Maintained S: Maintained
RISCOM8 DRIVER RISCOM8 DRIVER
......
VERSION = 2 VERSION = 2
PATCHLEVEL = 6 PATCHLEVEL = 6
SUBLEVEL = 17 SUBLEVEL = 17
EXTRAVERSION =-rc1 EXTRAVERSION =-rc2
NAME=Sliding Snow Leopard NAME=Sliding Snow Leopard
# *DOCUMENTATION* # *DOCUMENTATION*
......
...@@ -165,10 +165,31 @@ CONFIGURING the kernel: ...@@ -165,10 +165,31 @@ CONFIGURING the kernel:
"make xconfig" X windows (Qt) based configuration tool. "make xconfig" X windows (Qt) based configuration tool.
"make gconfig" X windows (Gtk) based configuration tool. "make gconfig" X windows (Gtk) based configuration tool.
"make oldconfig" Default all questions based on the contents of "make oldconfig" Default all questions based on the contents of
your existing ./.config file. your existing ./.config file and asking about
new config symbols.
"make silentoldconfig" "make silentoldconfig"
Like above, but avoids cluttering the screen Like above, but avoids cluttering the screen
with questions already answered. with questions already answered.
"make defconfig" Create a ./.config file by using the default
symbol values from arch/$ARCH/defconfig.
"make allyesconfig"
Create a ./.config file by setting symbol
values to 'y' as much as possible.
"make allmodconfig"
Create a ./.config file by setting symbol
values to 'm' as much as possible.
"make allnoconfig" Create a ./.config file by setting symbol
values to 'n' as much as possible.
"make randconfig" Create a ./.config file by setting symbol
values to random values.
The allyesconfig/allmodconfig/allnoconfig/randconfig variants can
also use the environment variable KCONFIG_ALLCONFIG to specify a
filename that contains config options that the user requires to be
set to a specific value. If KCONFIG_ALLCONFIG=filename is not used,
"make *config" checks for a file named "all{yes/mod/no/random}.config"
for symbol values that are to be forced. If this file is not found,
it checks for a file named "all.config" to contain forced values.
NOTES on "make config": NOTES on "make config":
- having unnecessary drivers will make the kernel bigger, and can - having unnecessary drivers will make the kernel bigger, and can
......
...@@ -18,6 +18,18 @@ ...@@ -18,6 +18,18 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/hardware/scoop.h> #include <asm/hardware/scoop.h>
/* PCMCIA to Scoop linkage
There is no easy way to link multiple scoop devices into one
single entity for the pxa2xx_pcmcia device so this structure
is used which is setup by the platform code.
This file is never modular so this symbol is always
accessile to the board support files.
*/
struct scoop_pcmcia_config *platform_scoop_config;
EXPORT_SYMBOL(platform_scoop_config);
#define SCOOP_REG(d,adr) (*(volatile unsigned short*)(d +(adr))) #define SCOOP_REG(d,adr) (*(volatile unsigned short*)(d +(adr)))
struct scoop_dev { struct scoop_dev {
......
...@@ -194,13 +194,23 @@ void __init at91_add_device_eth(struct at91_eth_data *data) {} ...@@ -194,13 +194,23 @@ void __init at91_add_device_eth(struct at91_eth_data *data) {}
#if defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE) #if defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE)
static struct at91_cf_data cf_data; static struct at91_cf_data cf_data;
static struct resource at91_cf_resources[] = {
[0] = {
.start = AT91_CF_BASE,
/* ties up CS4, CS5, and CS6 */
.end = AT91_CF_BASE + (0x30000000 - 1),
.flags = IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT,
},
};
static struct platform_device at91rm9200_cf_device = { static struct platform_device at91rm9200_cf_device = {
.name = "at91_cf", .name = "at91_cf",
.id = -1, .id = -1,
.dev = { .dev = {
.platform_data = &cf_data, .platform_data = &cf_data,
}, },
.num_resources = 0, .resource = at91_cf_resources,
.num_resources = ARRAY_SIZE(at91_cf_resources),
}; };
void __init at91_add_device_cf(struct at91_cf_data *data) void __init at91_add_device_cf(struct at91_cf_data *data)
......
...@@ -196,12 +196,9 @@ static int __init corgi_ssp_probe(struct platform_device *dev) ...@@ -196,12 +196,9 @@ static int __init corgi_ssp_probe(struct platform_device *dev)
int ret; int ret;
/* Chip Select - Disable All */ /* Chip Select - Disable All */
GPDR(ssp_machinfo->cs_lcdcon) |= GPIO_bit(ssp_machinfo->cs_lcdcon); /* output */ pxa_gpio_mode(ssp_machinfo->cs_lcdcon | GPIO_OUT | GPIO_DFLT_HIGH);
GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); /* High - Disable LCD Control/Timing Gen */ pxa_gpio_mode(ssp_machinfo->cs_max1111 | GPIO_OUT | GPIO_DFLT_HIGH);
GPDR(ssp_machinfo->cs_max1111) |= GPIO_bit(ssp_machinfo->cs_max1111); /* output */ pxa_gpio_mode(ssp_machinfo->cs_ads7846 | GPIO_OUT | GPIO_DFLT_HIGH);
GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); /* High - Disable MAX1111*/
GPDR(ssp_machinfo->cs_ads7846) |= GPIO_bit(ssp_machinfo->cs_ads7846); /* output */
GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); /* High - Disable ADS7846*/
ret = ssp_init(&corgi_ssp_dev, ssp_machinfo->port, 0); ret = ssp_init(&corgi_ssp_dev, ssp_machinfo->port, 0);
......
...@@ -50,7 +50,7 @@ static struct mtd_partition smdk_default_nand_part[] = { ...@@ -50,7 +50,7 @@ static struct mtd_partition smdk_default_nand_part[] = {
.offset = 0, .offset = 0,
}, },
[1] = { [1] = {
.name = "S3C2410 flash parition 1", .name = "S3C2410 flash partition 1",
.offset = 0, .offset = 0,
.size = SZ_2M, .size = SZ_2M,
}, },
......
...@@ -139,7 +139,7 @@ static int s3c2440_clk_add(struct sys_device *sysdev) ...@@ -139,7 +139,7 @@ static int s3c2440_clk_add(struct sys_device *sysdev)
clkdivn = __raw_readl(S3C2410_CLKDIVN); clkdivn = __raw_readl(S3C2410_CLKDIVN);
clkdivn |= S3C2440_CLKDIVN_UCLK; clkdivn |= S3C2440_CLKDIVN_UCLK;
__raw_writel(camdivn, S3C2410_CLKDIVN); __raw_writel(clkdivn, S3C2410_CLKDIVN);
mutex_unlock(&clocks_mutex); mutex_unlock(&clocks_mutex);
} }
......
...@@ -81,4 +81,13 @@ config X86_MPPARSE ...@@ -81,4 +81,13 @@ config X86_MPPARSE
depends on X86_LOCAL_APIC && !X86_VISWS depends on X86_LOCAL_APIC && !X86_VISWS
default y default y
config DOUBLEFAULT
default y
bool "Enable doublefault exception handler" if EMBEDDED
help
This option allows trapping of rare doublefault exceptions that
would otherwise cause a system to silently reboot. Disabling this
option saves about 4k and might cause you much additional grey
hair.
endmenu endmenu
...@@ -168,7 +168,7 @@ int __init acpi_parse_mcfg(unsigned long phys_addr, unsigned long size) ...@@ -168,7 +168,7 @@ int __init acpi_parse_mcfg(unsigned long phys_addr, unsigned long size)
unsigned long i; unsigned long i;
int config_size; int config_size;
if (!phys_addr || !size || !cpu_has_apic) if (!phys_addr || !size)
return -EINVAL; return -EINVAL;
mcfg = (struct acpi_table_mcfg *)__acpi_map_table(phys_addr, size); mcfg = (struct acpi_table_mcfg *)__acpi_map_table(phys_addr, size);
...@@ -1102,6 +1102,9 @@ int __init acpi_boot_table_init(void) ...@@ -1102,6 +1102,9 @@ int __init acpi_boot_table_init(void)
dmi_check_system(acpi_dmi_table); dmi_check_system(acpi_dmi_table);
#endif #endif
if (!cpu_has_apic)
return -ENODEV;
/* /*
* If acpi_disabled, bail out * If acpi_disabled, bail out
* One exception: acpi=ht continues far enough to enumerate LAPICs * One exception: acpi=ht continues far enough to enumerate LAPICs
......
...@@ -1079,7 +1079,7 @@ static int apm_console_blank(int blank) ...@@ -1079,7 +1079,7 @@ static int apm_console_blank(int blank)
break; break;
} }
if (error == APM_NOT_ENGAGED && state != APM_STATE_READY) { if (error == APM_NOT_ENGAGED) {
static int tried; static int tried;
int eng_error; int eng_error;
if (tried++ == 0) { if (tried++ == 0) {
......
...@@ -207,6 +207,8 @@ static void __init init_amd(struct cpuinfo_x86 *c) ...@@ -207,6 +207,8 @@ static void __init init_amd(struct cpuinfo_x86 *c)
set_bit(X86_FEATURE_K7, c->x86_capability); set_bit(X86_FEATURE_K7, c->x86_capability);
break; break;
} }
if (c->x86 >= 6)
set_bit(X86_FEATURE_FXSAVE_LEAK, c->x86_capability);
display_cacheinfo(c); display_cacheinfo(c);
......
...@@ -905,14 +905,17 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi ...@@ -905,14 +905,17 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
{ {
cpumask_t oldmask = CPU_MASK_ALL; cpumask_t oldmask = CPU_MASK_ALL;
struct powernow_k8_data *data = powernow_data[pol->cpu]; struct powernow_k8_data *data = powernow_data[pol->cpu];
u32 checkfid = data->currfid; u32 checkfid;
u32 checkvid = data->currvid; u32 checkvid;
unsigned int newstate; unsigned int newstate;
int ret = -EIO; int ret = -EIO;
if (!data) if (!data)
return -EINVAL; return -EINVAL;
checkfid = data->currfid;
checkvid = data->currvid;
/* only run on specific CPU from here on */ /* only run on specific CPU from here on */
oldmask = current->cpus_allowed; oldmask = current->cpus_allowed;
set_cpus_allowed(current, cpumask_of_cpu(pol->cpu)); set_cpus_allowed(current, cpumask_of_cpu(pol->cpu));
...@@ -1106,9 +1109,6 @@ static unsigned int powernowk8_get (unsigned int cpu) ...@@ -1106,9 +1109,6 @@ static unsigned int powernowk8_get (unsigned int cpu)
data = powernow_data[first_cpu(cpu_core_map[cpu])]; data = powernow_data[first_cpu(cpu_core_map[cpu])];
if (!data)
return -EINVAL;
if (!data) if (!data)
return -EINVAL; return -EINVAL;
......
...@@ -168,7 +168,7 @@ static int cpuid_class_device_create(int i) ...@@ -168,7 +168,7 @@ static int cpuid_class_device_create(int i)
return err; return err;
} }
static int __devinit cpuid_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) static int cpuid_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
{ {
unsigned int cpu = (unsigned long)hcpu; unsigned int cpu = (unsigned long)hcpu;
......
...@@ -43,7 +43,7 @@ DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; ...@@ -43,7 +43,7 @@ DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
/* insert a jmp code */ /* insert a jmp code */
static inline void set_jmp_op(void *from, void *to) static __always_inline void set_jmp_op(void *from, void *to)
{ {
struct __arch_jmp_op { struct __arch_jmp_op {
char op; char op;
...@@ -57,7 +57,7 @@ static inline void set_jmp_op(void *from, void *to) ...@@ -57,7 +57,7 @@ static inline void set_jmp_op(void *from, void *to)
/* /*
* returns non-zero if opcodes can be boosted. * returns non-zero if opcodes can be boosted.
*/ */
static inline int can_boost(kprobe_opcode_t opcode) static __always_inline int can_boost(kprobe_opcode_t opcode)
{ {
switch (opcode & 0xf0 ) { switch (opcode & 0xf0 ) {
case 0x70: case 0x70:
...@@ -88,7 +88,7 @@ static inline int can_boost(kprobe_opcode_t opcode) ...@@ -88,7 +88,7 @@ static inline int can_boost(kprobe_opcode_t opcode)
/* /*
* returns non-zero if opcode modifies the interrupt flag. * returns non-zero if opcode modifies the interrupt flag.
*/ */
static inline int is_IF_modifier(kprobe_opcode_t opcode) static int __kprobes is_IF_modifier(kprobe_opcode_t opcode)
{ {
switch (opcode) { switch (opcode) {
case 0xfa: /* cli */ case 0xfa: /* cli */
...@@ -138,7 +138,7 @@ void __kprobes arch_remove_kprobe(struct kprobe *p) ...@@ -138,7 +138,7 @@ void __kprobes arch_remove_kprobe(struct kprobe *p)
mutex_unlock(&kprobe_mutex); mutex_unlock(&kprobe_mutex);
} }
static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb) static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
{ {
kcb->prev_kprobe.kp = kprobe_running(); kcb->prev_kprobe.kp = kprobe_running();
kcb->prev_kprobe.status = kcb->kprobe_status; kcb->prev_kprobe.status = kcb->kprobe_status;
...@@ -146,7 +146,7 @@ static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb) ...@@ -146,7 +146,7 @@ static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
kcb->prev_kprobe.saved_eflags = kcb->kprobe_saved_eflags; kcb->prev_kprobe.saved_eflags = kcb->kprobe_saved_eflags;
} }
static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb) static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
{ {
__get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp; __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
kcb->kprobe_status = kcb->prev_kprobe.status; kcb->kprobe_status = kcb->prev_kprobe.status;
...@@ -154,7 +154,7 @@ static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb) ...@@ -154,7 +154,7 @@ static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
kcb->kprobe_saved_eflags = kcb->prev_kprobe.saved_eflags; kcb->kprobe_saved_eflags = kcb->prev_kprobe.saved_eflags;
} }
static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs, static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
struct kprobe_ctlblk *kcb) struct kprobe_ctlblk *kcb)
{ {
__get_cpu_var(current_kprobe) = p; __get_cpu_var(current_kprobe) = p;
...@@ -164,7 +164,7 @@ static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs, ...@@ -164,7 +164,7 @@ static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
kcb->kprobe_saved_eflags &= ~IF_MASK; kcb->kprobe_saved_eflags &= ~IF_MASK;
} }
static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
{ {
regs->eflags |= TF_MASK; regs->eflags |= TF_MASK;
regs->eflags &= ~IF_MASK; regs->eflags &= ~IF_MASK;
...@@ -507,7 +507,7 @@ static void __kprobes resume_execution(struct kprobe *p, ...@@ -507,7 +507,7 @@ static void __kprobes resume_execution(struct kprobe *p,
* Interrupts are disabled on entry as trap1 is an interrupt gate and they * Interrupts are disabled on entry as trap1 is an interrupt gate and they
* remain disabled thoroughout this function. * remain disabled thoroughout this function.
*/ */
static inline int post_kprobe_handler(struct pt_regs *regs) static int __kprobes post_kprobe_handler(struct pt_regs *regs)
{ {
struct kprobe *cur = kprobe_running(); struct kprobe *cur = kprobe_running();
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
...@@ -543,7 +543,7 @@ static inline int post_kprobe_handler(struct pt_regs *regs) ...@@ -543,7 +543,7 @@ static inline int post_kprobe_handler(struct pt_regs *regs)
return 1; return 1;
} }
static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr) static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
{ {
struct kprobe *cur = kprobe_running(); struct kprobe *cur = kprobe_running();
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
......
...@@ -251,7 +251,7 @@ static int msr_class_device_create(int i) ...@@ -251,7 +251,7 @@ static int msr_class_device_create(int i)
return err; return err;
} }
static int __devinit msr_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) static int msr_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
{ {
unsigned int cpu = (unsigned long)hcpu; unsigned int cpu = (unsigned long)hcpu;
......
...@@ -120,7 +120,6 @@ static struct resource qic_res = { ...@@ -120,7 +120,6 @@ static struct resource qic_res = {
* It writes num_bits of the data buffer in msg starting at start_bit. * It writes num_bits of the data buffer in msg starting at start_bit.
* Note: This function assumes that any unused bit in the data stream * Note: This function assumes that any unused bit in the data stream
* is set to zero so that the ors will work correctly */ * is set to zero so that the ors will work correctly */
#define BITS_PER_BYTE 8
static void static void
cat_pack(__u8 *msg, const __u16 start_bit, __u8 *data, const __u16 num_bits) cat_pack(__u8 *msg, const __u16 start_bit, __u8 *data, const __u16 num_bits)
{ {
......
...@@ -251,7 +251,7 @@ static void __kprobes prepare_break_inst(uint template, uint slot, ...@@ -251,7 +251,7 @@ static void __kprobes prepare_break_inst(uint template, uint slot,
update_kprobe_inst_flag(template, slot, major_opcode, kprobe_inst, p); update_kprobe_inst_flag(template, slot, major_opcode, kprobe_inst, p);
} }
static inline void get_kprobe_inst(bundle_t *bundle, uint slot, static void __kprobes get_kprobe_inst(bundle_t *bundle, uint slot,
unsigned long *kprobe_inst, uint *major_opcode) unsigned long *kprobe_inst, uint *major_opcode)
{ {
unsigned long kprobe_inst_p0, kprobe_inst_p1; unsigned long kprobe_inst_p0, kprobe_inst_p1;
...@@ -278,7 +278,7 @@ static inline void get_kprobe_inst(bundle_t *bundle, uint slot, ...@@ -278,7 +278,7 @@ static inline void get_kprobe_inst(bundle_t *bundle, uint slot,
} }
/* Returns non-zero if the addr is in the Interrupt Vector Table */ /* Returns non-zero if the addr is in the Interrupt Vector Table */
static inline int in_ivt_functions(unsigned long addr) static int __kprobes in_ivt_functions(unsigned long addr)
{ {
return (addr >= (unsigned long)__start_ivt_text return (addr >= (unsigned long)__start_ivt_text
&& addr < (unsigned long)__end_ivt_text); && addr < (unsigned long)__end_ivt_text);
...@@ -308,19 +308,19 @@ static int __kprobes valid_kprobe_addr(int template, int slot, ...@@ -308,19 +308,19 @@ static int __kprobes valid_kprobe_addr(int template, int slot,
return 0; return 0;
} }
static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb) static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
{ {
kcb->prev_kprobe.kp = kprobe_running(); kcb->prev_kprobe.kp = kprobe_running();
kcb->prev_kprobe.status = kcb->kprobe_status; kcb->prev_kprobe.status = kcb->kprobe_status;
} }
static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb) static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
{ {
__get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp; __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
kcb->kprobe_status = kcb->prev_kprobe.status; kcb->kprobe_status = kcb->prev_kprobe.status;
} }
static inline void set_current_kprobe(struct kprobe *p, static void __kprobes set_current_kprobe(struct kprobe *p,
struct kprobe_ctlblk *kcb) struct kprobe_ctlblk *kcb)
{ {
__get_cpu_var(current_kprobe) = p; __get_cpu_var(current_kprobe) = p;
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
* Stack layout in 'ret_from_system_call': * Stack layout in 'ret_from_system_call':
* ptrace needs to have all regs on the stack. * ptrace needs to have all regs on the stack.
* if the order here is changed, it needs to be * if the order here is changed, it needs to be
* updated in fork.c:copy_process, signal.c:do_signal, * updated in fork.c:copy_thread, signal.c:do_signal,
* ptrace.c and ptrace.h * ptrace.c and ptrace.h
* *
* M32Rx/M32R2 M32R * M32Rx/M32R2 M32R
...@@ -41,18 +41,17 @@ ...@@ -41,18 +41,17 @@
* @(0x38,sp) - syscall_nr ditto * @(0x38,sp) - syscall_nr ditto
* @(0x3c,sp) - acc0h @(0x3c,sp) - acch * @(0x3c,sp) - acc0h @(0x3c,sp) - acch
* @(0x40,sp) - acc0l @(0x40,sp) - accl * @(0x40,sp) - acc0l @(0x40,sp) - accl
* @(0x44,sp) - acc1h @(0x44,sp) - psw * @(0x44,sp) - acc1h @(0x44,sp) - dummy_acc1h
* @(0x48,sp) - acc1l @(0x48,sp) - bpc * @(0x48,sp) - acc1l @(0x48,sp) - dummy_acc1l
* @(0x4c,sp) - psw @(0x4c,sp) - bbpsw * @(0x4c,sp) - psw ditto
* @(0x50,sp) - bpc @(0x50,sp) - bbpc * @(0x50,sp) - bpc ditto
* @(0x54,sp) - bbpsw @(0x54,sp) - spu (cr3) * @(0x54,sp) - bbpsw ditto
* @(0x58,sp) - bbpc @(0x58,sp) - fp (r13) * @(0x58,sp) - bbpc ditto
* @(0x5c,sp) - spu (cr3) @(0x5c,sp) - lr (r14) * @(0x5c,sp) - spu (cr3) ditto
* @(0x60,sp) - fp (r13) @(0x60,sp) - spi (cr12) * @(0x60,sp) - fp (r13) ditto
* @(0x64,sp) - lr (r14) @(0x64,sp) - orig_r0 * @(0x64,sp) - lr (r14) ditto
* @(0x68,sp) - spi (cr2) * @(0x68,sp) - spi (cr2) ditto
* @(0x6c,sp) - orig_r0 * @(0x6c,sp) - orig_r0 ditto
*
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -102,6 +101,12 @@ ...@@ -102,6 +101,12 @@
#define ACC0L(reg) @(0x40,reg) #define ACC0L(reg) @(0x40,reg)
#define ACC1H(reg) @(0x44,reg) #define ACC1H(reg) @(0x44,reg)
#define ACC1L(reg) @(0x48,reg) #define ACC1L(reg) @(0x48,reg)
#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
#define ACCH(reg) @(0x3C,reg)
#define ACCL(reg) @(0x40,reg)
#else
#error unknown isa configuration
#endif
#define PSW(reg) @(0x4C,reg) #define PSW(reg) @(0x4C,reg)
#define BPC(reg) @(0x50,reg) #define BPC(reg) @(0x50,reg)
#define BBPSW(reg) @(0x54,reg) #define BBPSW(reg) @(0x54,reg)
...@@ -111,21 +116,6 @@ ...@@ -111,21 +116,6 @@
#define LR(reg) @(0x64,reg) #define LR(reg) @(0x64,reg)
#define SP(reg) @(0x68,reg) #define SP(reg) @(0x68,reg)
#define ORIG_R0(reg) @(0x6C,reg) #define ORIG_R0(reg) @(0x6C,reg)
#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
#define ACCH(reg) @(0x3C,reg)
#define ACCL(reg) @(0x40,reg)
#define PSW(reg) @(0x44,reg)
#define BPC(reg) @(0x48,reg)
#define BBPSW(reg) @(0x4C,reg)
#define BBPC(reg) @(0x50,reg)
#define SPU(reg) @(0x54,reg)
#define FP(reg) @(0x58,reg) /* FP = R13 */
#define LR(reg) @(0x5C,reg)
#define SP(reg) @(0x60,reg)
#define ORIG_R0(reg) @(0x64,reg)
#else
#error unknown isa configuration
#endif
CF_MASK = 0x00000001 CF_MASK = 0x00000001
TF_MASK = 0x00000100 TF_MASK = 0x00000100
...@@ -142,7 +132,7 @@ VM_MASK = 0x00020000 ...@@ -142,7 +132,7 @@ VM_MASK = 0x00020000
#endif #endif
ENTRY(ret_from_fork) ENTRY(ret_from_fork)
ld r0, @sp+ pop r0
bl schedule_tail bl schedule_tail
GET_THREAD_INFO(r8) GET_THREAD_INFO(r8)
bra syscall_exit bra syscall_exit
...@@ -231,7 +221,7 @@ restore_all: ...@@ -231,7 +221,7 @@ restore_all:
RESTORE_ALL RESTORE_ALL
# perform work that needs to be done immediately before resumption # perform work that needs to be done immediately before resumption
# r9 : frags # r9 : flags
ALIGN ALIGN
work_pending: work_pending:
and3 r4, r9, #_TIF_NEED_RESCHED and3 r4, r9, #_TIF_NEED_RESCHED
...@@ -320,7 +310,7 @@ ENTRY(ei_handler) ...@@ -320,7 +310,7 @@ ENTRY(ei_handler)
; GET_ICU_STATUS; ; GET_ICU_STATUS;
seth r0, #shigh(M32R_ICU_ISTS_ADDR) seth r0, #shigh(M32R_ICU_ISTS_ADDR)
ld r0, @(low(M32R_ICU_ISTS_ADDR),r0) ld r0, @(low(M32R_ICU_ISTS_ADDR),r0)
st r0, @-sp push r0
#if defined(CONFIG_SMP) #if defined(CONFIG_SMP)
/* /*
* If IRQ == 0 --> Nothing to do, Not write IMASK * If IRQ == 0 --> Nothing to do, Not write IMASK
...@@ -557,7 +547,7 @@ check_end: ...@@ -557,7 +547,7 @@ check_end:
#endif /* CONFIG_PLAT_M32104UT */ #endif /* CONFIG_PLAT_M32104UT */
bl do_IRQ bl do_IRQ
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
ld r14, @sp+ pop r14
seth r0, #shigh(M32R_ICU_IMASK_ADDR) seth r0, #shigh(M32R_ICU_IMASK_ADDR)
st r14, @(low(M32R_ICU_IMASK_ADDR),r0) st r14, @(low(M32R_ICU_IMASK_ADDR),r0)
#else #else
...@@ -1015,4 +1005,3 @@ ENTRY(sys_call_table) ...@@ -1015,4 +1005,3 @@ ENTRY(sys_call_table)
.long sys_waitid .long sys_waitid
syscall_table_size=(.-sys_call_table) syscall_table_size=(.-sys_call_table)
...@@ -116,6 +116,10 @@ void cpu_idle (void) ...@@ -116,6 +116,10 @@ void cpu_idle (void)
void machine_restart(char *__unused) void machine_restart(char *__unused)
{ {
#if defined(CONFIG_PLAT_MAPPI3)
outw(1, (unsigned long)PLD_REBOOT);
#endif
printk("Please push reset button!\n"); printk("Please push reset button!\n");
while (1) while (1)
cpu_relax(); cpu_relax();
......
...@@ -118,6 +118,8 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, ...@@ -118,6 +118,8 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R) #elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
COPY(acch); COPY(acch);
COPY(accl); COPY(accl);
COPY(dummy_acc1h);
COPY(dummy_acc1l);
#else #else
#error unknown isa configuration #error unknown isa configuration
#endif #endif
...@@ -203,6 +205,8 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, ...@@ -203,6 +205,8 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R) #elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
COPY(acch); COPY(acch);
COPY(accl); COPY(accl);
COPY(dummy_acc1h);
COPY(dummy_acc1l);
#else #else
#error unknown isa configuration #error unknown isa configuration
#endif #endif
......
...@@ -816,6 +816,10 @@ config GENERIC_CALIBRATE_DELAY ...@@ -816,6 +816,10 @@ config GENERIC_CALIBRATE_DELAY
bool bool
default y default y
config SCHED_NO_NO_OMIT_FRAME_POINTER
bool
default y
# #
# Select some configuration options automatically based on user selections. # Select some configuration options automatically based on user selections.
# #
...@@ -1443,6 +1447,10 @@ choice ...@@ -1443,6 +1447,10 @@ choice
prompt "MIPS MT options" prompt "MIPS MT options"
depends on MIPS_MT depends on MIPS_MT
config MIPS_MT_SMTC
bool "SMTC: Use all TCs on all VPEs for SMP"
select SMP
config MIPS_MT_SMP config MIPS_MT_SMP
bool "Use 1 TC on each available VPE for SMP" bool "Use 1 TC on each available VPE for SMP"
select SMP select SMP
...@@ -1456,6 +1464,11 @@ config MIPS_VPE_LOADER ...@@ -1456,6 +1464,11 @@ config MIPS_VPE_LOADER
endchoice endchoice
config MIPS_MT_FPAFF
bool "Dynamic FPU affinity for FP-intensive threads"
depends on MIPS_MT
default y
config MIPS_VPE_LOADER_TOM config MIPS_VPE_LOADER_TOM
bool "Load VPE program into memory hidden from linux" bool "Load VPE program into memory hidden from linux"
depends on MIPS_VPE_LOADER depends on MIPS_VPE_LOADER
...@@ -1472,6 +1485,16 @@ config MIPS_VPE_APSP_API ...@@ -1472,6 +1485,16 @@ config MIPS_VPE_APSP_API
depends on MIPS_VPE_LOADER depends on MIPS_VPE_LOADER
help help
config MIPS_APSP_KSPD
bool "Enable KSPD"
depends on MIPS_VPE_APSP_API
default y
help
KSPD is a kernel daemon that accepts syscall requests from the SP
side, actions them and returns the results. It also handles the
"exit" syscall notifying other kernel modules the SP program is
exiting. You probably want to say yes here.
config SB1_PASS_1_WORKAROUNDS config SB1_PASS_1_WORKAROUNDS
bool bool
depends on CPU_SB1_PASS_1 depends on CPU_SB1_PASS_1
...@@ -1599,7 +1622,7 @@ source "mm/Kconfig" ...@@ -1599,7 +1622,7 @@ source "mm/Kconfig"
config SMP config SMP
bool "Multi-Processing support" bool "Multi-Processing support"
depends on CPU_RM9000 || ((SIBYTE_BCM1x80 || SIBYTE_BCM1x55 || SIBYTE_SB1250 || QEMU) && !SIBYTE_STANDALONE) || SGI_IP27 || MIPS_MT_SMP depends on CPU_RM9000 || ((SIBYTE_BCM1x80 || SIBYTE_BCM1x55 || SIBYTE_SB1250 || QEMU) && !SIBYTE_STANDALONE) || SGI_IP27 || MIPS_MT_SMP || MIPS_MT_SMTC
---help--- ---help---
This enables support for systems with more than one CPU. If you have This enables support for systems with more than one CPU. If you have
a system with only one CPU, like most personal computers, say N. If a system with only one CPU, like most personal computers, say N. If
......
...@@ -105,18 +105,18 @@ cflags-$(CONFIG_CPU_R4300) += -march=r4300 -Wa,--trap ...@@ -105,18 +105,18 @@ cflags-$(CONFIG_CPU_R4300) += -march=r4300 -Wa,--trap
cflags-$(CONFIG_CPU_VR41XX) += -march=r4100 -Wa,--trap cflags-$(CONFIG_CPU_VR41XX) += -march=r4100 -Wa,--trap
cflags-$(CONFIG_CPU_R4X00) += -march=r4600 -Wa,--trap cflags-$(CONFIG_CPU_R4X00) += -march=r4600 -Wa,--trap
cflags-$(CONFIG_CPU_TX49XX) += -march=r4600 -Wa,--trap cflags-$(CONFIG_CPU_TX49XX) += -march=r4600 -Wa,--trap
cflags-$(CONFIG_CPU_MIPS32_R1) += $(call cc-option,-march=mips32,-mips2 -mtune=r4600) \ cflags-$(CONFIG_CPU_MIPS32_R1) += $(call cc-option,-march=mips32,-mips32 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
-Wa,-mips32 -Wa,--trap -Wa,-mips32 -Wa,--trap
cflags-$(CONFIG_CPU_MIPS32_R2) += $(call cc-option,-march=mips32r2,-mips2 -mtune=r4600) \ cflags-$(CONFIG_CPU_MIPS32_R2) += $(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
-Wa,-mips32r2 -Wa,--trap -Wa,-mips32r2 -Wa,--trap
cflags-$(CONFIG_CPU_MIPS64_R1) += $(call cc-option,-march=mips64,-mips2 -mtune=r4600) \ cflags-$(CONFIG_CPU_MIPS64_R1) += $(call cc-option,-march=mips64,-mips64 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64) \
-Wa,-mips64 -Wa,--trap -Wa,-mips64 -Wa,--trap
cflags-$(CONFIG_CPU_MIPS64_R2) += $(call cc-option,-march=mips64r2,-mips2 -mtune=r4600 ) \ cflags-$(CONFIG_CPU_MIPS64_R2) += $(call cc-option,-march=mips64r2,-mips64r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64) \
-Wa,-mips64r2 -Wa,--trap -Wa,-mips64r2 -Wa,--trap
cflags-$(CONFIG_CPU_R5000) += -march=r5000 -Wa,--trap cflags-$(CONFIG_CPU_R5000) += -march=r5000 -Wa,--trap
cflags-$(CONFIG_CPU_R5432) += $(call cc-options,-march=r5400,-march=r5000) \ cflags-$(CONFIG_CPU_R5432) += $(call cc-option,-march=r5400,-march=r5000) \
-Wa,--trap -Wa,--trap
cflags-$(CONFIG_CPU_NEVADA) += $(call cc-options,-march=rm5200,-march=r5000) \ cflags-$(CONFIG_CPU_NEVADA) += $(call cc-option,-march=rm5200,-march=r5000) \
-Wa,--trap -Wa,--trap
cflags-$(CONFIG_CPU_RM7000) += $(call cc-option,-march=rm7000,-march=r5000) \ cflags-$(CONFIG_CPU_RM7000) += $(call cc-option,-march=rm7000,-march=r5000) \
-Wa,--trap -Wa,--trap
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
# Makefile for the Alchemy Au1000 CPU, generic files. # Makefile for the Alchemy Au1000 CPU, generic files.
# #
obj-y += prom.o int-handler.o irq.o puts.o time.o reset.o \ obj-y += prom.o irq.o puts.o time.o reset.o \
au1xxx_irqmap.o clocks.o platform.o power.o setup.o \ au1xxx_irqmap.o clocks.o platform.o power.o setup.o \
sleeper.o cputable.o dma.o dbdma.o gpio.o sleeper.o cputable.o dma.o dbdma.o gpio.o
......
/*
* Copyright 2001 MontaVista Software Inc.
* Author: ppopov@mvista.com
*
* Interrupt dispatcher for Au1000 boards.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include <asm/asm.h>
#include <asm/mipsregs.h>
#include <asm/addrspace.h>
#include <asm/regdef.h>
#include <asm/stackframe.h>
.text
.set macro
.set noat
.align 5
NESTED(au1000_IRQ, PT_SIZE, sp)
SAVE_ALL
CLI # Important: mark KERNEL mode !
mfc0 t0,CP0_CAUSE # get pending interrupts
mfc0 t1,CP0_STATUS # get enabled interrupts
and t0,t1 # isolate allowed ones
andi t0,0xff00 # isolate pending bits
beqz t0, 3f # spurious interrupt
andi a0, t0, CAUSEF_IP7
beq a0, zero, 1f
move a0, sp
jal mips_timer_interrupt
j ret_from_irq
1:
andi a0, t0, CAUSEF_IP2 # Interrupt Controller 0, Request 0
beq a0, zero, 2f
move a0,sp
jal intc0_req0_irqdispatch
j ret_from_irq
2:
andi a0, t0, CAUSEF_IP3 # Interrupt Controller 0, Request 1
beq a0, zero, 3f
move a0,sp
jal intc0_req1_irqdispatch
j ret_from_irq
3:
andi a0, t0, CAUSEF_IP4 # Interrupt Controller 1, Request 0
beq a0, zero, 4f
move a0,sp
jal intc1_req0_irqdispatch
j ret_from_irq
4:
andi a0, t0, CAUSEF_IP5 # Interrupt Controller 1, Request 1
beq a0, zero, 5f
move a0, sp
jal intc1_req1_irqdispatch
j ret_from_irq
5:
move a0, sp
j spurious_interrupt
END(au1000_IRQ)
...@@ -66,7 +66,6 @@ ...@@ -66,7 +66,6 @@
#define EXT_INTC1_REQ1 5 /* IP 5 */ #define EXT_INTC1_REQ1 5 /* IP 5 */
#define MIPS_TIMER_IP 7 /* IP 7 */ #define MIPS_TIMER_IP 7 /* IP 7 */
extern asmlinkage void au1000_IRQ(void);
extern void set_debug_traps(void); extern void set_debug_traps(void);
extern irq_cpustat_t irq_stat [NR_CPUS]; extern irq_cpustat_t irq_stat [NR_CPUS];
...@@ -446,7 +445,6 @@ void __init arch_init_irq(void) ...@@ -446,7 +445,6 @@ void __init arch_init_irq(void)
extern int au1xxx_ic0_nr_irqs; extern int au1xxx_ic0_nr_irqs;
cp0_status = read_c0_status(); cp0_status = read_c0_status();
set_except_vector(0, au1000_IRQ);
/* Initialize interrupt controllers to a safe state. /* Initialize interrupt controllers to a safe state.
*/ */
...@@ -661,3 +659,21 @@ restore_au1xxx_intctl(void) ...@@ -661,3 +659,21 @@ restore_au1xxx_intctl(void)
au_writel(sleep_intctl_mask[0], IC0_MASKSET); au_sync(); au_writel(sleep_intctl_mask[0], IC0_MASKSET); au_sync();
} }
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
{
unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
if (pending & CAUSEF_IP7)
mips_timer_interrupt(regs);
else if (pending & CAUSEF_IP2)
intc0_req0_irqdispatch(regs);
else if (pending & CAUSEF_IP3)
intc0_req1_irqdispatch(regs);
else if (pending & CAUSEF_IP4)
intc1_req0_irqdispatch(regs);
else if (pending & CAUSEF_IP5)
intc1_req1_irqdispatch(regs);
else
spurious_interrupt(regs);
}
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# Makefile for the Cobalt micro systems family specific parts of the kernel # Makefile for the Cobalt micro systems family specific parts of the kernel
# #
obj-y := irq.o int-handler.o reset.o setup.o obj-y := irq.o reset.o setup.o
obj-$(CONFIG_EARLY_PRINTK) += console.o obj-$(CONFIG_EARLY_PRINTK) += console.o
......
...@@ -20,8 +20,6 @@ ...@@ -20,8 +20,6 @@
#include <asm/mach-cobalt/cobalt.h> #include <asm/mach-cobalt/cobalt.h>
extern void cobalt_handle_int(void);
/* /*
* We have two types of interrupts that we handle, ones that come in through * We have two types of interrupts that we handle, ones that come in through
* the CPU interrupt lines, and ones that come in on the via chip. The CPU * the CPU interrupt lines, and ones that come in on the via chip. The CPU
...@@ -79,7 +77,7 @@ static inline void via_pic_irq(struct pt_regs *regs) ...@@ -79,7 +77,7 @@ static inline void via_pic_irq(struct pt_regs *regs)
do_IRQ(irq, regs); do_IRQ(irq, regs);
} }
asmlinkage void cobalt_irq(struct pt_regs *regs) asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
{ {
unsigned pending; unsigned pending;
...@@ -122,8 +120,6 @@ void __init arch_init_irq(void) ...@@ -122,8 +120,6 @@ void __init arch_init_irq(void)
*/ */
GALILEO_OUTL(0, GT_INTRMASK_OFS); GALILEO_OUTL(0, GT_INTRMASK_OFS);
set_except_vector(0, cobalt_handle_int);
init_i8259_irqs(); /* 0 ... 15 */ init_i8259_irqs(); /* 0 ... 15 */
mips_cpu_irq_init(COBALT_CPU_IRQ); /* 16 ... 23 */ mips_cpu_irq_init(COBALT_CPU_IRQ); /* 16 ... 23 */
......
This diff is collapsed.
...@@ -3,6 +3,6 @@ ...@@ -3,6 +3,6 @@
# under Linux. # under Linux.
# #
obj-y += setup.o irq.o int-handler.o nile4_pic.o obj-y += setup.o irq.o nile4_pic.o
EXTRA_AFLAGS := $(CFLAGS) EXTRA_AFLAGS := $(CFLAGS)
/*
* arch/mips/ddb5074/int-handler.S -- NEC DDB Vrc-5074 interrupt handler
*
* Based on arch/mips/sgi/kernel/indyIRQ.S
*
* Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
*
* Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
* Sony Software Development Center Europe (SDCE), Brussels
*/
#include <asm/asm.h>
#include <asm/mipsregs.h>
#include <asm/regdef.h>
#include <asm/stackframe.h>
/* A lot of complication here is taken away because:
*
* 1) We handle one interrupt and return, sitting in a loop and moving across
* all the pending IRQ bits in the cause register is _NOT_ the answer, the
* common case is one pending IRQ so optimize in that direction.
*
* 2) We need not check against bits in the status register IRQ mask, that
* would make this routine slow as hell.
*
* 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
* between like BSD spl() brain-damage.
*
* Furthermore, the IRQs on the INDY look basically (barring software IRQs
* which we don't use at all) like:
*
* MIPS IRQ Source
* -------- ------
* 0 Software (ignored)
* 1 Software (ignored)
* 2 Local IRQ level zero
* 3 Local IRQ level one
* 4 8254 Timer zero
* 5 8254 Timer one
* 6 Bus Error
* 7 R4k timer (what we use)
*
* We handle the IRQ according to _our_ priority which is:
*
* Highest ---- R4k Timer
* Local IRQ zero
* Local IRQ one
* Bus Error
* 8254 Timer zero
* Lowest ---- 8254 Timer one
*
* then we just return, if multiple IRQs are pending then we will just take
* another exception, big deal.
*/
.text
.set noreorder
.set noat
.align 5
NESTED(ddbIRQ, PT_SIZE, sp)
SAVE_ALL
CLI
.set at
mfc0 s0, CP0_CAUSE # get irq mask
#if 1
mfc0 t2,CP0_STATUS # get enabled interrupts
and s0,t2 # isolate allowed ones
#endif
/* First we check for r4k counter/timer IRQ. */
andi a0, s0, CAUSEF_IP2 # delay slot, check local level zero
beq a0, zero, 1f
andi a0, s0, CAUSEF_IP3 # delay slot, check local level one
/* Wheee, local level zero interrupt. */
jal ddb_local0_irqdispatch
move a0, sp # delay slot
j ret_from_irq
nop # delay slot
1:
beq a0, zero, 1f
andi a0, s0, CAUSEF_IP6 # delay slot, check bus error
/* Wheee, local level one interrupt. */
move a0, sp
jal ddb_local1_irqdispatch
nop
j ret_from_irq
nop
1:
beq a0, zero, 1f
nop
/* Wheee, an asynchronous bus error... */
move a0, sp
jal ddb_buserror_irq
nop
j ret_from_irq
nop
1:
/* Here by mistake? This is possible, what can happen
* is that by the time we take the exception the IRQ
* pin goes low, so just leave if this is the case.
*/
andi a0, s0, (CAUSEF_IP4 | CAUSEF_IP5)
beq a0, zero, 1f
/* Must be one of the 8254 timers... */
move a0, sp
jal ddb_8254timer_irq
nop
1:
j ret_from_irq
nop
END(ddbIRQ)
...@@ -21,8 +21,6 @@ ...@@ -21,8 +21,6 @@
#include <asm/ddb5xxx/ddb5074.h> #include <asm/ddb5xxx/ddb5074.h>
extern asmlinkage void ddbIRQ(void);
static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL }; static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
#define M1543_PNP_CONFIG 0x03f0 /* PnP Config Port */ #define M1543_PNP_CONFIG 0x03f0 /* PnP Config Port */
...@@ -90,7 +88,7 @@ static void m1543_irq_setup(void) ...@@ -90,7 +88,7 @@ static void m1543_irq_setup(void)
} }
void ddb_local0_irqdispatch(struct pt_regs *regs) static void ddb_local0_irqdispatch(struct pt_regs *regs)
{ {
u32 mask; u32 mask;
int nile4_irq; int nile4_irq;
...@@ -118,29 +116,41 @@ void ddb_local0_irqdispatch(struct pt_regs *regs) ...@@ -118,29 +116,41 @@ void ddb_local0_irqdispatch(struct pt_regs *regs)
} }
} }
void ddb_local1_irqdispatch(void) static void ddb_local1_irqdispatch(void)
{ {
printk("ddb_local1_irqdispatch called\n"); printk("ddb_local1_irqdispatch called\n");
} }
void ddb_buserror_irq(void) static void ddb_buserror_irq(void)
{ {
printk("ddb_buserror_irq called\n"); printk("ddb_buserror_irq called\n");
} }
void ddb_8254timer_irq(void) static void ddb_8254timer_irq(void)
{ {
printk("ddb_8254timer_irq called\n"); printk("ddb_8254timer_irq called\n");
} }
asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
{
unsigned int pending = read_c0_cause() & read_c0_status();
if (pending & CAUSEF_IP2)
ddb_local0_irqdispatch(regs);
else if (pending & CAUSEF_IP3)
ddb_local1_irqdispatch();
else if (pending & CAUSEF_IP6)
ddb_buserror_irq();
else if (pending & (CAUSEF_IP4 | CAUSEF_IP5))
ddb_8254timer_irq();
}
void __init arch_init_irq(void) void __init arch_init_irq(void)
{ {
/* setup cascade interrupts */ /* setup cascade interrupts */
setup_irq(NILE4_IRQ_BASE + NILE4_INT_INTE, &irq_cascade); setup_irq(NILE4_IRQ_BASE + NILE4_INT_INTE, &irq_cascade);
setup_irq(CPU_IRQ_BASE + CPU_NILE4_CASCADE, &irq_cascade); setup_irq(CPU_IRQ_BASE + CPU_NILE4_CASCADE, &irq_cascade);
set_except_vector(0, ddbIRQ);
nile4_irq_setup(NILE4_IRQ_BASE); nile4_irq_setup(NILE4_IRQ_BASE);
m1543_irq_setup(); m1543_irq_setup();
init_i8259_irqs(); init_i8259_irqs();
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
# under Linux. # under Linux.
# #
obj-y += setup.o irq.o int-handler.o nile4_pic.o vrc5476_irq.o obj-y += setup.o irq.o nile4_pic.o vrc5476_irq.o
obj-$(CONFIG_KGDB) += dbg_io.o obj-$(CONFIG_KGDB) += dbg_io.o
EXTRA_AFLAGS := $(CFLAGS) EXTRA_AFLAGS := $(CFLAGS)
/*
* Copyright 2001 MontaVista Software Inc.
* Author: jsun@mvista.com or jsun@junsun.net
*
* First-level interrupt dispatcher for ddb5476
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include <asm/asm.h>
#include <asm/mipsregs.h>
#include <asm/addrspace.h>
#include <asm/regdef.h>
#include <asm/stackframe.h>
#include <asm/ddb5xxx/ddb5476.h>
/*
* first level interrupt dispatcher for ocelot board -
* We check for the timer first, then check PCI ints A and D.
* Then check for serial IRQ and fall through.
*/
.align 5
NESTED(ddb5476_handle_int, PT_SIZE, sp)
SAVE_ALL
CLI
.set at
.set noreorder
mfc0 t0, CP0_CAUSE
mfc0 t2, CP0_STATUS
and t0, t2
andi t1, t0, STATUSF_IP7 /* cpu timer */
bnez t1, ll_cpu_ip7
andi t1, t0, STATUSF_IP2 /* vrc5476 & i8259 */
bnez t1, ll_cpu_ip2
andi t1, t0, STATUSF_IP3
bnez t1, ll_cpu_ip3
andi t1, t0, STATUSF_IP4
bnez t1, ll_cpu_ip4
andi t1, t0, STATUSF_IP5
bnez t1, ll_cpu_ip5
andi t1, t0, STATUSF_IP6
bnez t1, ll_cpu_ip6
andi t1, t0, STATUSF_IP0 /* software int 0 */
bnez t1, ll_cpu_ip0
andi t1, t0, STATUSF_IP1 /* software int 1 */
bnez t1, ll_cpu_ip1
nop
.set reorder
/* wrong alarm or masked ... */
// j spurious_interrupt
move a0, sp
jal vrc5476_irq_dispatch
j ret_from_irq
nop
.align 5
ll_cpu_ip0:
li a0, CPU_IRQ_BASE + 0
move a1, sp
jal do_IRQ
j ret_from_irq
ll_cpu_ip1:
li a0, CPU_IRQ_BASE + 1
move a1, sp
jal do_IRQ
j ret_from_irq
ll_cpu_ip2: /* jump to second-level dispatching */
move a0, sp
jal vrc5476_irq_dispatch
j ret_from_irq
ll_cpu_ip3:
li a0, CPU_IRQ_BASE + 3
move a1, sp
jal do_IRQ
j ret_from_irq
ll_cpu_ip4:
li a0, CPU_IRQ_BASE + 4
move a1, sp
jal do_IRQ
j ret_from_irq
ll_cpu_ip5:
li a0, CPU_IRQ_BASE + 5
move a1, sp
jal do_IRQ
j ret_from_irq
ll_cpu_ip6:
li a0, CPU_IRQ_BASE + 6
move a1, sp
jal do_IRQ
j ret_from_irq
ll_cpu_ip7:
li a0, CPU_IRQ_BASE + 7
move a1, sp
jal do_IRQ
j ret_from_irq
END(ddb5476_handle_int)
...@@ -110,11 +110,36 @@ static void nile4_irq_setup(void) ...@@ -110,11 +110,36 @@ static void nile4_irq_setup(void)
static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL }; static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
static struct irqaction irq_error = { no_action, 0, CPU_MASK_NONE, "error", NULL, NULL }; static struct irqaction irq_error = { no_action, 0, CPU_MASK_NONE, "error", NULL, NULL };
extern asmlinkage void ddb5476_handle_int(void);
extern int setup_irq(unsigned int irq, struct irqaction *irqaction); extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
extern void mips_cpu_irq_init(u32 irq_base); extern void mips_cpu_irq_init(u32 irq_base);
extern void vrc5476_irq_init(u32 irq_base); extern void vrc5476_irq_init(u32 irq_base);
extern void vrc5476_irq_dispatch(struct pt_regs *regs);
asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
{
unsigned int pending = read_c0_cause() & read_c0_status();
if (pending & STATUSF_IP7)
do_IRQ(CPU_IRQ_BASE + 7, regs);
else if (pending & STATUSF_IP2)
vrc5476_irq_dispatch(regs);
else if (pending & STATUSF_IP3)
do_IRQ(CPU_IRQ_BASE + 3, regs);
else if (pending & STATUSF_IP4)
do_IRQ(CPU_IRQ_BASE + 4, regs);
else if (pending & STATUSF_IP5)
do_IRQ(CPU_IRQ_BASE + 5, regs);
else if (pending & STATUSF_IP6)
do_IRQ(CPU_IRQ_BASE + 6, regs);
else if (pending & STATUSF_IP0)
do_IRQ(CPU_IRQ_BASE, regs);
else if (pending & STATUSF_IP1)
do_IRQ(CPU_IRQ_BASE + 1, regs);
vrc5476_irq_dispatch(regs);
}
void __init arch_init_irq(void) void __init arch_init_irq(void)
{ {
/* hardware initialization */ /* hardware initialization */
...@@ -137,7 +162,4 @@ void __init arch_init_irq(void) ...@@ -137,7 +162,4 @@ void __init arch_init_irq(void)
setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_LBRT, &irq_error); setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_LBRT, &irq_error);
setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_PCIS, &irq_error); setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_PCIS, &irq_error);
setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_PCI, &irq_error); setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_PCI, &irq_error);
/* setup the grandpa intr vector */
set_except_vector(0, ddb5476_handle_int);
} }
...@@ -77,11 +77,9 @@ vrc5476_irq_init(u32 base) ...@@ -77,11 +77,9 @@ vrc5476_irq_init(u32 base)
} }
asmlinkage void void
vrc5476_irq_dispatch(struct pt_regs *regs) vrc5476_irq_dispatch(struct pt_regs *regs)
{ {
extern void spurious_interrupt(void);
u32 mask; u32 mask;
int nile4_irq; int nile4_irq;
...@@ -107,5 +105,5 @@ vrc5476_irq_dispatch(struct pt_regs *regs) ...@@ -107,5 +105,5 @@ vrc5476_irq_dispatch(struct pt_regs *regs)
return; return;
} }
} }
spurious_interrupt(); spurious_interrupt(regs);
} }
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# Makefile for NEC DDB-Vrc5477 board # Makefile for NEC DDB-Vrc5477 board
# #
obj-y += int-handler.o irq.o irq_5477.o setup.o lcd44780.o obj-y += irq.o irq_5477.o setup.o lcd44780.o
obj-$(CONFIG_RUNTIME_DEBUG) += debug.o obj-$(CONFIG_RUNTIME_DEBUG) += debug.o
obj-$(CONFIG_KGDB) += kgdb_io.o obj-$(CONFIG_KGDB) += kgdb_io.o
......
/*
* Copyright 2001 MontaVista Software Inc.
* Author: jsun@mvista.com or jsun@junsun.net
*
* First-level interrupt dispatcher for ddb5477
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include <asm/asm.h>
#include <asm/mipsregs.h>
#include <asm/addrspace.h>
#include <asm/regdef.h>
#include <asm/stackframe.h>
#include <asm/ddb5xxx/ddb5477.h>
/*
* first level interrupt dispatcher for ocelot board -
* We check for the timer first, then check PCI ints A and D.
* Then check for serial IRQ and fall through.
*/
.align 5
NESTED(ddb5477_handle_int, PT_SIZE, sp)
SAVE_ALL
CLI
.set at
.set noreorder
mfc0 t0, CP0_CAUSE
mfc0 t2, CP0_STATUS
and t0, t2
andi t1, t0, STATUSF_IP7 /* cpu timer */
bnez t1, ll_cputimer_irq
andi t1, t0, (STATUSF_IP2 | STATUSF_IP3 | STATUSF_IP4 | STATUSF_IP5 | STATUSF_IP6 )
bnez t1, ll_vrc5477_irq
andi t1, t0, STATUSF_IP0 /* software int 0 */
bnez t1, ll_cpu_ip0
andi t1, t0, STATUSF_IP1 /* software int 1 */
bnez t1, ll_cpu_ip1
nop
.set reorder
/* wrong alarm or masked ... */
j spurious_interrupt
nop
END(ddb5477_handle_int)
.align 5
ll_vrc5477_irq:
move a0, sp
jal vrc5477_irq_dispatch
j ret_from_irq
ll_cputimer_irq:
li a0, CPU_IRQ_BASE + 7
move a1, sp
jal do_IRQ
j ret_from_irq
ll_cpu_ip0:
li a0, CPU_IRQ_BASE + 0
move a1, sp
jal do_IRQ
j ret_from_irq
ll_cpu_ip1:
li a0, CPU_IRQ_BASE + 1
move a1, sp
jal do_IRQ
j ret_from_irq
...@@ -75,7 +75,6 @@ set_pci_int_attr(u32 pci, u32 intn, u32 active, u32 trigger) ...@@ -75,7 +75,6 @@ set_pci_int_attr(u32 pci, u32 intn, u32 active, u32 trigger)
extern void vrc5477_irq_init(u32 base); extern void vrc5477_irq_init(u32 base);
extern void mips_cpu_irq_init(u32 base); extern void mips_cpu_irq_init(u32 base);
extern asmlinkage void ddb5477_handle_int(void);
extern int setup_irq(unsigned int irq, struct irqaction *irqaction); extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL }; static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
...@@ -135,9 +134,6 @@ void __init arch_init_irq(void) ...@@ -135,9 +134,6 @@ void __init arch_init_irq(void)
/* setup cascade interrupts */ /* setup cascade interrupts */
setup_irq(VRC5477_IRQ_BASE + VRC5477_I8259_CASCADE, &irq_cascade); setup_irq(VRC5477_IRQ_BASE + VRC5477_I8259_CASCADE, &irq_cascade);
setup_irq(CPU_IRQ_BASE + CPU_VRC5477_CASCADE, &irq_cascade); setup_irq(CPU_IRQ_BASE + CPU_VRC5477_CASCADE, &irq_cascade);
/* hook up the first-level interrupt handler */
set_except_vector(0, ddb5477_handle_int);
} }
u8 i8259_interrupt_ack(void) u8 i8259_interrupt_ack(void)
...@@ -159,7 +155,7 @@ u8 i8259_interrupt_ack(void) ...@@ -159,7 +155,7 @@ u8 i8259_interrupt_ack(void)
* the first level int-handler will jump here if it is a vrc5477 irq * the first level int-handler will jump here if it is a vrc5477 irq
*/ */
#define NUM_5477_IRQS 32 #define NUM_5477_IRQS 32
asmlinkage void static void
vrc5477_irq_dispatch(struct pt_regs *regs) vrc5477_irq_dispatch(struct pt_regs *regs)
{ {
u32 intStatus; u32 intStatus;
...@@ -197,3 +193,21 @@ vrc5477_irq_dispatch(struct pt_regs *regs) ...@@ -197,3 +193,21 @@ vrc5477_irq_dispatch(struct pt_regs *regs)
} }
} }
} }
#define VR5477INTS (STATUSF_IP2|STATUSF_IP3|STATUSF_IP4|STATUSF_IP5|STATUSF_IP6)
asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
{
unsigned int pending = read_c0_cause() & read_c0_status();
if (pending & STATUSF_IP7)
do_IRQ(CPU_IRQ_BASE + 7, regs);
else if (pending & VR5477INTS)
vrc5477_irq_dispatch(regs);
else if (pending & STATUSF_IP0)
do_IRQ(CPU_IRQ_BASE, regs);
else if (pending & STATUSF_IP1)
do_IRQ(CPU_IRQ_BASE + 1, regs);
else
spurious_interrupt(regs);
}
/* /*
* arch/mips/dec/decstation.c * arch/mips/dec/decstation.c
*/ */
#include <asm/sections.h>
#define RELOC #define RELOC
#define INITRD #define INITRD
...@@ -24,7 +25,7 @@ ...@@ -24,7 +25,7 @@
#define INITRD_START (*(unsigned long *) (PARAM+0x218)) #define INITRD_START (*(unsigned long *) (PARAM+0x218))
#define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c)) #define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c))
extern int _ftext, _end; /* begin and end of kernel image */ extern int _ftext; /* begin and end of kernel image */
extern void kernel_entry(int, char **, unsigned long, int *); extern void kernel_entry(int, char **, unsigned long, int *);
void * memcpy(void * dest, const void *src, unsigned int count) void * memcpy(void * dest, const void *src, unsigned int count)
......
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
.text .text
.set noreorder .set noreorder
/* /*
* decstation_handle_int: Interrupt handler for DECstations * plat_irq_dispatch: Interrupt handler for DECstations
* *
* We follow the model in the Indy interrupt code by David Miller, where he * We follow the model in the Indy interrupt code by David Miller, where he
* says: a lot of complication here is taken away because: * says: a lot of complication here is taken away because:
...@@ -125,11 +125,7 @@ ...@@ -125,11 +125,7 @@
* just take another exception, big deal. * just take another exception, big deal.
*/ */
.align 5 .align 5
NESTED(decstation_handle_int, PT_SIZE, ra) NESTED(plat_irq_dispatch, PT_SIZE, ra)
.set noat
SAVE_ALL
CLI # TEST: interrupts should be off
.set at
.set noreorder .set noreorder
/* /*
...@@ -282,9 +278,11 @@ fpu: ...@@ -282,9 +278,11 @@ fpu:
#endif #endif
spurious: spurious:
j spurious_interrupt jal spurious_interrupt
nop nop
END(decstation_handle_int) j ret_from_irq
nop
END(plat_irq_dispatch)
/* /*
* Generic unimplemented interrupt routines -- cpu_mask_nr_tbl * Generic unimplemented interrupt routines -- cpu_mask_nr_tbl
......
...@@ -48,8 +48,6 @@ extern void dec_machine_halt(void); ...@@ -48,8 +48,6 @@ extern void dec_machine_halt(void);
extern void dec_machine_power_off(void); extern void dec_machine_power_off(void);
extern irqreturn_t dec_intr_halt(int irq, void *dev_id, struct pt_regs *regs); extern irqreturn_t dec_intr_halt(int irq, void *dev_id, struct pt_regs *regs);
extern asmlinkage void decstation_handle_int(void);
unsigned long dec_kn_slot_base, dec_kn_slot_size; unsigned long dec_kn_slot_base, dec_kn_slot_size;
EXPORT_SYMBOL(dec_kn_slot_base); EXPORT_SYMBOL(dec_kn_slot_base);
...@@ -744,7 +742,6 @@ void __init arch_init_irq(void) ...@@ -744,7 +742,6 @@ void __init arch_init_irq(void)
panic("Don't know how to set this up!"); panic("Don't know how to set this up!");
break; break;
} }
set_except_vector(0, decstation_handle_int);
/* Free the FPU interrupt if the exception is present. */ /* Free the FPU interrupt if the exception is present. */
if (!cpu_has_nofpuex) { if (!cpu_has_nofpuex) {
......
...@@ -6,4 +6,4 @@ ...@@ -6,4 +6,4 @@
# Makefile for the Galileo EV96100 board. # Makefile for the Galileo EV96100 board.
# #
obj-y += init.o irq.o puts.o reset.o time.o int-handler.o setup.o obj-y += init.o irq.o puts.o reset.o time.o setup.o
#include <asm/asm.h>
#include <asm/mipsregs.h>
#include <asm/regdef.h>
#include <asm/stackframe.h>
.set noat
.align 5
NESTED(ev96100IRQ, PT_SIZE, sp)
SAVE_ALL
CLI # Important: mark KERNEL mode !
mfc0 t0, CP0_CAUSE # get pending interrupts
mfc0 t1, CP0_STATUS # get enabled interrupts
and t0, t1 # isolate allowed ones
# FIX ME add R7000 extensions
andi t0,0xff00 # isolate pending bits
andi a0, t0, CAUSEF_IP7
beq a0, zero, 1f
move a0, sp
jal mips_timer_interrupt
j ret_from_irq
1: beqz t0, 3f # spurious interrupt
move a0, t0
move a1, sp
jal ev96100_cpu_irq
j ret_from_irq
3: j spurious_interrupt
END(ev96100IRQ)
...@@ -40,8 +40,6 @@ ...@@ -40,8 +40,6 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <asm/irq_cpu.h> #include <asm/irq_cpu.h>
extern asmlinkage void ev96100IRQ(void);
static inline unsigned int ffz8(unsigned int word) static inline unsigned int ffz8(unsigned int word)
{ {
unsigned long k; unsigned long k;
...@@ -54,13 +52,26 @@ static inline unsigned int ffz8(unsigned int word) ...@@ -54,13 +52,26 @@ static inline unsigned int ffz8(unsigned int word)
return k; return k;
} }
asmlinkage void ev96100_cpu_irq(unsigned int pendin) extern void mips_timer_interrupt(struct pt_regs *regs);
asmlinkage void ev96100_cpu_irq(unsigned int pending, struct pt_regs *regs)
{ {
do_IRQ(ffz8(pending >> 8), regs); do_IRQ(ffz8(pending >> 8), regs);
} }
asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
{
unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
if (pending & CAUSEF_IP7)
mips_timer_interrupt(regs);
else if (pending)
ev96100_cpu_irq(pending, regs);
else
spurious_interrupt(regs);
}
void __init arch_init_irq(void) void __init arch_init_irq(void)
{ {
set_except_vector(0, ev96100IRQ);
mips_cpu_irq_init(0); mips_cpu_irq_init(0);
} }
...@@ -6,6 +6,6 @@ ...@@ -6,6 +6,6 @@
# Makefile for the Galileo EV64120 board. # Makefile for the Galileo EV64120 board.
# #
obj-y += int-handler.o irq.o promcon.o reset.o serialGT.o setup.o obj-y += irq.o promcon.o reset.o serialGT.o setup.o
EXTRA_AFLAGS := $(CFLAGS) EXTRA_AFLAGS := $(CFLAGS)
/*
* int-handler.S
*
* Based on the cobalt handler.
*/
#include <asm/asm.h>
#include <asm/mipsregs.h>
#include <asm/addrspace.h>
#include <asm/regdef.h>
#include <asm/stackframe.h>
/*
* galileo_handle_int -
* We check for the timer first, then check PCI ints A and D.
* Then check for serial IRQ and fall through.
*/
.align 5
.set reorder
.set noat
NESTED(galileo_handle_int, PT_SIZE, sp)
SAVE_ALL
CLI
.set at
mfc0 t0,CP0_CAUSE
mfc0 t2,CP0_STATUS
and t0,t2
andi t1,t0,STATUSF_IP4 /* int2 hardware line (timer) */
bnez t1,ll_gt64120_irq
andi t1,t0,STATUSF_IP2 /* int0 hardware line */
bnez t1,ll_pci_intA
andi t1,t0,STATUSF_IP5 /* int3 hardware line */
bnez t1,ll_pci_intD
andi t1,t0,STATUSF_IP6 /* int4 hardware line */
bnez t1,ll_serial_irq
andi t1,t0,STATUSF_IP7 /* compare int */
bnez t1,ll_compare_irq
nop
/* wrong alarm or masked ... */
j spurious_interrupt
nop
END(galileo_handle_int)
.align 5
.set reorder
ll_gt64120_irq:
li a0,4
move a1,sp
jal do_IRQ
nop
j ret_from_irq
nop
.align 5
.set reorder
ll_compare_irq:
li a0,7
move a1,sp
jal do_IRQ
nop
j ret_from_irq
nop
.align 5
.set reorder
ll_pci_intA:
move a0,sp
jal pci_intA
nop
j ret_from_irq
nop
#if 0
.align 5
.set reorder
ll_pci_intB:
move a0,sp
jal pci_intB
nop
j ret_from_irq
nop
.align 5
.set reorder
ll_pci_intC:
move a0,sp
jal pci_intC
nop
j ret_from_irq
nop
#endif
.align 5
.set reorder
ll_pci_intD:
move a0,sp
jal pci_intD
nop
j ret_from_irq
nop
.align 5
.set reorder
ll_serial_irq:
li a0,6
move a1,sp
jal do_IRQ
nop
j ret_from_irq
nop
...@@ -46,14 +46,22 @@ ...@@ -46,14 +46,22 @@
#include <asm/system.h> #include <asm/system.h>
#include <asm/gt64120.h> #include <asm/gt64120.h>
asmlinkage inline void pci_intA(struct pt_regs *regs) asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
{ {
do_IRQ(GT_INTA, regs); unsigned int pending = read_c0_status() & read_c0_cause();
}
if (pending & STATUSF_IP4) /* int2 hardware line (timer) */
asmlinkage inline void pci_intD(struct pt_regs *regs) do_IRQ(4, regs);
{ else if (pending & STATUSF_IP2) /* int0 hardware line */
do_IRQ(GT_INTD, regs); do_IRQ(GT_INTA, regs);
else if (pending & STATUSF_IP5) /* int3 hardware line */
do_IRQ(GT_INTD, regs);
else if (pending & STATUSF_IP6) /* int4 hardware line */
do_IRQ(6, regs);
else if (pending & STATUSF_IP7) /* compare int */
do_IRQ(7, regs);
else
spurious_interrupt(regs);
} }
static void disable_ev64120_irq(unsigned int irq_nr) static void disable_ev64120_irq(unsigned int irq_nr)
...@@ -109,16 +117,11 @@ static struct hw_interrupt_type ev64120_irq_type = { ...@@ -109,16 +117,11 @@ static struct hw_interrupt_type ev64120_irq_type = {
void gt64120_irq_setup(void) void gt64120_irq_setup(void)
{ {
extern asmlinkage void galileo_handle_int(void);
/* /*
* Clear all of the interrupts while we change the able around a bit. * Clear all of the interrupts while we change the able around a bit.
*/ */
clear_c0_status(ST0_IM); clear_c0_status(ST0_IM);
/* Sets the exception_handler array. */
set_except_vector(0, galileo_handle_int);
local_irq_disable(); local_irq_disable();
/* /*
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# Makefile for Momentum's Ocelot board. # Makefile for Momentum's Ocelot board.
# #
obj-y += int-handler.o irq.o prom.o reset.o setup.o obj-y += irq.o prom.o reset.o setup.o
obj-$(CONFIG_KGDB) += dbg_io.o obj-$(CONFIG_KGDB) += dbg_io.o
......
/*
* Copyright 2001 MontaVista Software Inc.
* Author: jsun@mvista.com or jsun@junsun.net
*
* First-level interrupt dispatcher for ocelot board.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include <asm/asm.h>
#include <asm/mipsregs.h>
#include <asm/addrspace.h>
#include <asm/regdef.h>
#include <asm/stackframe.h>
/*
* first level interrupt dispatcher for ocelot board -
* We check for the timer first, then check PCI ints A and D.
* Then check for serial IRQ and fall through.
*/
.align 5
NESTED(ocelot_handle_int, PT_SIZE, sp)
SAVE_ALL
CLI
.set at
mfc0 t0, CP0_CAUSE
mfc0 t2, CP0_STATUS
and t0, t2
andi t1, t0, STATUSF_IP2 /* int0 hardware line */
bnez t1, ll_pri_enet_irq
andi t1, t0, STATUSF_IP3 /* int1 hardware line */
bnez t1, ll_sec_enet_irq
andi t1, t0, STATUSF_IP4 /* int2 hardware line */
bnez t1, ll_uart1_irq
andi t1, t0, STATUSF_IP5 /* int3 hardware line */
bnez t1, ll_cpci_irq
andi t1, t0, STATUSF_IP6 /* int4 hardware line */
bnez t1, ll_galileo_irq
andi t1, t0, STATUSF_IP7 /* cpu timer */
bnez t1, ll_cputimer_irq
/* now look at the extended interrupts */
mfc0 t0, CP0_CAUSE
cfc0 t1, CP0_S1_INTCONTROL
/* shift the mask 8 bits left to line up the bits */
sll t2, t1, 8
and t0, t2
srl t0, t0, 16
andi t1, t0, STATUSF_IP8 /* int6 hardware line */
bnez t1, ll_pmc1_irq
andi t1, t0, STATUSF_IP9 /* int7 hardware line */
bnez t1, ll_pmc2_irq
andi t1, t0, STATUSF_IP10 /* int8 hardware line */
bnez t1, ll_cpci_abcd_irq
andi t1, t0, STATUSF_IP11 /* int9 hardware line */
bnez t1, ll_uart2_irq
.set reorder
/* wrong alarm or masked ... */
j spurious_interrupt
nop
END(ocelot_handle_int)
.align 5
ll_pri_enet_irq:
li a0, 2
move a1, sp
jal do_IRQ
j ret_from_irq
ll_sec_enet_irq:
li a0, 3
move a1, sp
jal do_IRQ
j ret_from_irq
ll_uart1_irq:
li a0, 4
move a1, sp
jal do_IRQ
j ret_from_irq
ll_cpci_irq:
li a0, 5
move a1, sp
jal do_IRQ
j ret_from_irq
ll_galileo_irq:
li a0, 6
move a1, sp
jal do_IRQ
j ret_from_irq
ll_cputimer_irq:
li a0, 7
move a1, sp
jal do_IRQ
j ret_from_irq
ll_pmc1_irq:
li a0, 8
move a1, sp
jal do_IRQ
j ret_from_irq
ll_pmc2_irq:
li a0, 9
move a1, sp
jal do_IRQ
j ret_from_irq
ll_cpci_abcd_irq:
li a0, 10
move a1, sp
jal do_IRQ
j ret_from_irq
ll_uart2_irq:
li a0, 11
move a1, sp
jal do_IRQ
j ret_from_irq
...@@ -48,7 +48,38 @@ ...@@ -48,7 +48,38 @@
#include <asm/mipsregs.h> #include <asm/mipsregs.h>
#include <asm/system.h> #include <asm/system.h>
extern asmlinkage void ocelot_handle_int(void); asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
{
unsigned int pending = read_c0_status() & read_c0_cause();
if (pending & STATUSF_IP2) /* int0 hardware line */
do_IRQ(2, regs);
else if (pending & STATUSF_IP3) /* int1 hardware line */
do_IRQ(3, regs);
else if (pending & STATUSF_IP4) /* int2 hardware line */
do_IRQ(4, regs);
else if (pending & STATUSF_IP5) /* int3 hardware line */
do_IRQ(5, regs);
else if (pending & STATUSF_IP6) /* int4 hardware line */
do_IRQ(6, regs);
else if (pending & STATUSF_IP7) /* cpu timer */
do_IRQ(7, regs);
else {
/*
* Now look at the extended interrupts
*/
pending = (read_c0_cause() & (read_c0_intcontrol() << 8)) >> 16;
if (pending & STATUSF_IP8) /* int6 hardware line */
do_IRQ(8, regs);
else if (pending & STATUSF_IP9) /* int7 hardware line */
do_IRQ(9, regs);
else if (pending & STATUSF_IP10) /* int8 hardware line */
do_IRQ(10, regs);
else if (pending & STATUSF_IP11) /* int9 hardware line */
do_IRQ(11, regs);
}
}
void __init arch_init_irq(void) void __init arch_init_irq(void)
{ {
...@@ -59,9 +90,6 @@ void __init arch_init_irq(void) ...@@ -59,9 +90,6 @@ void __init arch_init_irq(void)
clear_c0_status(ST0_IM); clear_c0_status(ST0_IM);
local_irq_disable(); local_irq_disable();
/* Sets the first-level interrupt dispatcher. */
set_except_vector(0, ocelot_handle_int);
mips_cpu_irq_init(0); mips_cpu_irq_init(0);
rm7k_cpu_irq_init(8); rm7k_cpu_irq_init(8);
} }
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
# Makefile for the ITE 8172 (qed-4n-s01b) board, generic files. # Makefile for the ITE 8172 (qed-4n-s01b) board, generic files.
# #
obj-y += it8172_setup.o irq.o int-handler.o pmon_prom.o \ obj-y += it8172_setup.o irq.o pmon_prom.o \
time.o lpc.o puts.o reset.o time.o lpc.o puts.o reset.o
obj-$(CONFIG_IT8172_CIR)+= it8172_cir.o obj-$(CONFIG_IT8172_CIR)+= it8172_cir.o
......
#include <asm/asm.h>
#include <asm/mipsregs.h>
#include <asm/regdef.h>
#include <asm/stackframe.h>
.text
.set macro
.set noat
.align 5
NESTED(it8172_IRQ, PT_SIZE, sp)
SAVE_ALL
CLI # Important: mark KERNEL mode !
/* We're working with 'reorder' set at this point. */
/*
* Get pending interrupts
*/
mfc0 t0,CP0_CAUSE # get pending interrupts
mfc0 t1,CP0_STATUS # get enabled interrupts
and t0,t1 # isolate allowed ones
andi t0,0xff00 # isolate pending bits
beqz t0, 3f # spurious interrupt
andi a0, t0, CAUSEF_IP7
beq a0, zero, 1f
li a0, 127 # MIPS_CPU_TIMER_IRQ = (NR_IRQS-1)
move a1, sp
jal ll_timer_interrupt
j ret_from_irq
nop
1:
andi a0, t0, CAUSEF_IP2 # the only int we expect at this time
beq a0, zero, 3f
move a0,sp
jal it8172_hw0_irqdispatch
mfc0 t0,CP0_STATUS # disable interrupts
ori t0,1
xori t0,1
mtc0 t0,CP0_STATUS
nop
nop
nop
la a1, ret_from_irq
jr a1
nop
3:
move a0, sp
jal mips_spurious_interrupt
nop
la a1, ret_from_irq
jr a1
nop
END(it8172_IRQ)
...@@ -62,12 +62,8 @@ ...@@ -62,12 +62,8 @@
#define ALLINTS_NOTIMER (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4) #define ALLINTS_NOTIMER (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4)
void disable_it8172_irq(unsigned int irq_nr);
void enable_it8172_irq(unsigned int irq_nr);
extern void set_debug_traps(void); extern void set_debug_traps(void);
extern void mips_timer_interrupt(int irq, struct pt_regs *regs); extern void mips_timer_interrupt(int irq, struct pt_regs *regs);
extern asmlinkage void it8172_IRQ(void);
struct it8172_intc_regs volatile *it8172_hw0_icregs = struct it8172_intc_regs volatile *it8172_hw0_icregs =
(struct it8172_intc_regs volatile *)(KSEG1ADDR(IT8172_PCI_IO_BASE + IT_INTC_BASE)); (struct it8172_intc_regs volatile *)(KSEG1ADDR(IT8172_PCI_IO_BASE + IT_INTC_BASE));
...@@ -181,8 +177,6 @@ void __init arch_init_irq(void) ...@@ -181,8 +177,6 @@ void __init arch_init_irq(void)
int i; int i;
unsigned long flags; unsigned long flags;
set_except_vector(0, it8172_IRQ);
/* mask all interrupts */ /* mask all interrupts */
it8172_hw0_icregs->lb_mask = 0xffff; it8172_hw0_icregs->lb_mask = 0xffff;
it8172_hw0_icregs->lpc_mask = 0xffff; it8172_hw0_icregs->lpc_mask = 0xffff;
...@@ -282,6 +276,18 @@ void it8172_hw0_irqdispatch(struct pt_regs *regs) ...@@ -282,6 +276,18 @@ void it8172_hw0_irqdispatch(struct pt_regs *regs)
do_IRQ(irq, regs); do_IRQ(irq, regs);
} }
asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
{
unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
if (!pending)
mips_spurious_interrupt(regs);
else if (pending & CAUSEF_IP7)
ll_timer_interrupt(127, regs);
else if (pending & CAUSEF_IP2)
it8172_hw0_irqdispatch(regs);
}
void show_pending_irqs(void) void show_pending_irqs(void)
{ {
fputs("intstatus: "); fputs("intstatus: ");
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/mc146818rtc.h>
#include <asm/time.h> #include <asm/time.h>
#include <asm/mipsregs.h> #include <asm/mipsregs.h>
......
...@@ -34,13 +34,13 @@ ...@@ -34,13 +34,13 @@
#include <asm/bootinfo.h> #include <asm/bootinfo.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <asm/sections.h>
#include <asm/it8172/it8172.h> #include <asm/it8172/it8172.h>
#include <asm/it8172/it8172_dbg.h> #include <asm/it8172/it8172_dbg.h>
int prom_argc; int prom_argc;
char **prom_argv, **prom_envp; char **prom_argv, **prom_envp;
extern char _end;
extern void __init prom_init_cmdline(void); extern void __init prom_init_cmdline(void);
extern unsigned long __init prom_get_memsize(void); extern unsigned long __init prom_get_memsize(void);
extern void __init it8172_init_ram_resource(unsigned long memsize); extern void __init it8172_init_ram_resource(unsigned long memsize);
......
...@@ -34,13 +34,13 @@ ...@@ -34,13 +34,13 @@
#include <asm/bootinfo.h> #include <asm/bootinfo.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <asm/sections.h>
#include <asm/it8172/it8172.h> #include <asm/it8172/it8172.h>
#include <asm/it8172/it8172_dbg.h> #include <asm/it8172/it8172_dbg.h>
int prom_argc; int prom_argc;
char **prom_argv, **prom_envp; char **prom_argv, **prom_envp;
extern char _end;
extern void __init prom_init_cmdline(void); extern void __init prom_init_cmdline(void);
extern unsigned long __init prom_get_memsize(void); extern unsigned long __init prom_get_memsize(void);
extern void __init it8172_init_ram_resource(unsigned long memsize); extern void __init it8172_init_ram_resource(unsigned long memsize);
......
...@@ -2,6 +2,6 @@ ...@@ -2,6 +2,6 @@
# Makefile for the Jazz family specific parts of the kernel # Makefile for the Jazz family specific parts of the kernel
# #
obj-y := int-handler.o irq.o jazzdma.o reset.o setup.o obj-y := irq.o jazzdma.o reset.o setup.o
EXTRA_AFLAGS := $(CFLAGS) EXTRA_AFLAGS := $(CFLAGS)
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle and Andreas Busse
*
* Jazz family specific interrupt stuff
*
* To do: On Jazz machines we remap some non-ISA interrupts to ISA
* interrupts. These interrupts should use their own vectors.
* Squeeze the last cycles out of the handlers. Only a dead
* cycle is a good cycle.
*/
#include <asm/asm.h>
#include <asm/mipsregs.h>
#include <asm/jazz.h>
#include <asm/regdef.h>
#include <asm/stackframe.h>
/*
* jazz_handle_int: Interrupt handler for the ACER Pica-61 boards
*/
.set noreorder
NESTED(jazz_handle_int, PT_SIZE, ra)
.set noat
SAVE_ALL
CLI
.set at
/*
* Get pending interrupts
*/
mfc0 t0,CP0_CAUSE # get pending interrupts
mfc0 t1,CP0_STATUS # get enabled interrupts
and t0,t1 # isolate allowed ones
andi t0,0xff00 # isolate pending bits
beqz t0,3f
sll t0,16 # delay slot
/*
* Find irq with highest priority
* FIXME: This is slow - use binary search
*/
la t1,ll_vectors
1: bltz t0,2f # found pending irq
sll t0,1
b 1b
subu t1,PTRSIZE # delay slot
/*
* Do the low-level stuff
*/
2: lw t0,(t1)
jr t0
nop # delay slot
END(jazz_handle_int)
ll_sw0: li s1,~IE_SW0
mfc0 t0,CP0_CAUSE
and t0,s1
mtc0 t0,CP0_CAUSE
PANIC("Unimplemented sw0 handler")
ll_sw1: li s1,~IE_SW1
mfc0 t0,CP0_CAUSE
and t0,s1
mtc0 t0,CP0_CAUSE
PANIC("Unimplemented sw1 handler")
ll_local_dma: li s1,~IE_IRQ0
PANIC("Unimplemented local_dma handler")
ll_local_dev: lbu t0,JAZZ_IO_IRQ_SOURCE
#if PTRSIZE == 8 /* True 64 bit kernel */
dsll t0,1
#endif
.set reorder
LONG_L t0,local_vector(t0)
jr t0
.set noreorder
/*
* The braindead PICA hardware gives us no way to distinguish if we really
* received interrupt 7 from the (E)ISA bus or if we just received an
* interrupt with no findable cause. This sometimes happens with braindead
* cards. Oh well - for all the Jazz boxes slots are more or less just
* whistles and bells and we're aware of the problem.
*/
ll_isa_irq: lw a0, JAZZ_EISA_IRQ_ACK
jal do_IRQ
move a1,sp
j ret_from_irq
nop
/*
* Hmm... This is not just a plain PC clone so the question is
* which devices on Jazz machines can generate an (E)ISA NMI?
* (Writing to nonexistent memory?)
*/
ll_isa_nmi: li s1,~IE_IRQ3
PANIC("Unimplemented isa_nmi handler")
/*
* Timer IRQ - remapped to be more similar to an IBM compatible.
*
* The timer interrupt is handled specially to ensure that the jiffies
* variable is updated at all times. Specifically, the timer interrupt is
* just like the complete handlers except that it is invoked with interrupts
* disabled and should never re-enable them. If other interrupts were
* allowed to be processed while the timer interrupt is active, then the
* other interrupts would have to avoid using the jiffies variable for delay
* and interval timing operations to avoid hanging the system.
*/
ll_timer: lw zero,JAZZ_TIMER_REGISTER # timer irq cleared on read
li s1,~IE_IRQ4
li a0, JAZZ_TIMER_IRQ
jal do_IRQ
move a1,sp
mfc0 t0,CP0_STATUS # disable interrupts again
ori t0,1
xori t0,1
mtc0 t0,CP0_STATUS
j ret_from_irq
nop
/*
* CPU count/compare IRQ (unused)
*/
ll_count: j ret_from_irq
mtc0 zero,CP0_COMPARE
#if 0
/*
* Call the handler for the interrupt
* (Currently unused)
*/
call_real: /*
* temporarily disable interrupt
*/
mfc0 t2,CP0_STATUS
and t2,s1
mtc0 t2,CP0_STATUS
nor s1,zero,s1
jal do_IRQ
/*
* reenable interrupt
*/
mfc0 t2,CP0_STATUS
or t2,s1
mtc0 t2,CP0_STATUS
j ret_from_irq
#endif
.data
PTR ll_sw0 # SW0
PTR ll_sw1 # SW1
PTR ll_local_dma # Local DMA
PTR ll_local_dev # Local devices
PTR ll_isa_irq # ISA IRQ
PTR ll_isa_nmi # ISA NMI
PTR ll_timer # Timer
ll_vectors: PTR ll_count # Count/Compare IRQ
/*
* Interrupt handlers for local devices.
*/
.text
.set reorder
loc_no_irq: PANIC("Unimplemented loc_no_irq handler")
/*
* Parallel port IRQ
*/
loc_parallel: li s1,~JAZZ_IE_PARALLEL
li a0,JAZZ_PARALLEL_IRQ
b loc_call
/*
* Floppy IRQ
*/
loc_floppy: li s1,~JAZZ_IE_FLOPPY
li a0,JAZZ_FLOPPY_IRQ
b loc_call
/*
* Sound IRQ
*/
loc_sound: PANIC("Unimplemented loc_sound handler")
loc_video: PANIC("Unimplemented loc_video handler")
/*
* Ethernet interrupt handler
*/
loc_ethernet: li s1,~JAZZ_IE_ETHERNET
li a0,JAZZ_ETHERNET_IRQ
b loc_call
/*
* SCSI interrupt handler
*/
loc_scsi: li s1,~JAZZ_IE_SCSI
li a0,JAZZ_SCSI_IRQ
b loc_call
/*
* Keyboard interrupt handler
*/
loc_keyboard: li s1,~JAZZ_IE_KEYBOARD
li a0,JAZZ_KEYBOARD_IRQ
b loc_call
/*
* Mouse interrupt handler
*/
loc_mouse: li s1,~JAZZ_IE_MOUSE
li a0,JAZZ_MOUSE_IRQ
b loc_call
/*
* Serial port 1 IRQ
*/
loc_serial1: li s1,~JAZZ_IE_SERIAL1
li a0,JAZZ_SERIAL1_IRQ
b loc_call
/*
* Serial port 2 IRQ
*/
loc_serial2: li s1,~JAZZ_IE_SERIAL2
li a0,JAZZ_SERIAL2_IRQ
b loc_call
/*
* Call the interrupt handler for an interrupt generated by a
* local device.
*/
loc_call: /*
* Temporarily disable interrupt source
*/
lhu t2,JAZZ_IO_IRQ_ENABLE
and t2,s1
sh t2,JAZZ_IO_IRQ_ENABLE
nor s1,zero,s1
jal do_IRQ
/*
* Reenable interrupt
*/
lhu t2,JAZZ_IO_IRQ_ENABLE
or t2,s1
sh t2,JAZZ_IO_IRQ_ENABLE
j ret_from_irq
/*
* "Jump extender" to reach spurious_interrupt
*/
3: j spurious_interrupt
/*
* Vectors for interrupts generated by local devices
*/
.data
local_vector: PTR loc_no_irq
PTR loc_parallel
PTR loc_floppy
PTR loc_sound
PTR loc_video
PTR loc_ethernet
PTR loc_scsi
PTR loc_keyboard
PTR loc_mouse
PTR loc_serial1
PTR loc_serial2
...@@ -15,8 +15,6 @@ ...@@ -15,8 +15,6 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/jazz.h> #include <asm/jazz.h>
extern asmlinkage void jazz_handle_int(void);
static DEFINE_SPINLOCK(r4030_lock); static DEFINE_SPINLOCK(r4030_lock);
static void enable_r4030_irq(unsigned int irq) static void enable_r4030_irq(unsigned int irq)
...@@ -90,10 +88,82 @@ void __init init_r4030_ints(void) ...@@ -90,10 +88,82 @@ void __init init_r4030_ints(void)
*/ */
void __init arch_init_irq(void) void __init arch_init_irq(void)
{ {
set_except_vector(0, jazz_handle_int);
init_i8259_irqs(); /* Integrated i8259 */ init_i8259_irqs(); /* Integrated i8259 */
init_r4030_ints(); init_r4030_ints();
change_c0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1); change_c0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1);
} }
static void loc_call(unsigned int irq, struct pt_regs *regs, unsigned int mask)
{
r4030_write_reg16(JAZZ_IO_IRQ_ENABLE,
r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) & mask);
do_IRQ(irq, regs);
r4030_write_reg16(JAZZ_IO_IRQ_ENABLE,
r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) | mask);
}
static void ll_local_dev(struct pt_regs *regs)
{
switch (r4030_read_reg32(JAZZ_IO_IRQ_SOURCE)) {
case 0:
panic("Unimplemented loc_no_irq handler");
break;
case 4:
loc_call(JAZZ_PARALLEL_IRQ, regs, JAZZ_IE_PARALLEL);
break;
case 8:
loc_call(JAZZ_PARALLEL_IRQ, regs, JAZZ_IE_FLOPPY);
break;
case 12:
panic("Unimplemented loc_sound handler");
break;
case 16:
panic("Unimplemented loc_video handler");
break;
case 20:
loc_call(JAZZ_ETHERNET_IRQ, regs, JAZZ_IE_ETHERNET);
break;
case 24:
loc_call(JAZZ_SCSI_IRQ, regs, JAZZ_IE_SCSI);
break;
case 28:
loc_call(JAZZ_KEYBOARD_IRQ, regs, JAZZ_IE_KEYBOARD);
break;
case 32:
loc_call(JAZZ_MOUSE_IRQ, regs, JAZZ_IE_MOUSE);
break;
case 36:
loc_call(JAZZ_SERIAL1_IRQ, regs, JAZZ_IE_SERIAL1);
break;
case 40:
loc_call(JAZZ_SERIAL2_IRQ, regs, JAZZ_IE_SERIAL2);
break;
}
}
asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
{
unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
if (pending & IE_IRQ5)
write_c0_compare(0);
else if (pending & IE_IRQ4) {
r4030_read_reg32(JAZZ_TIMER_REGISTER);
do_IRQ(JAZZ_TIMER_IRQ, regs);
} else if (pending & IE_IRQ3)
panic("Unimplemented ISA NMI handler");
else if (pending & IE_IRQ2)
do_IRQ(r4030_read_reg32(JAZZ_EISA_IRQ_ACK), regs);
else if (pending & IE_IRQ1) {
ll_local_dev(regs);
} else if (unlikely(pending & IE_IRQ0))
panic("Unimplemented local_dma handler");
else if (pending & IE_SW1) {
clear_c0_cause(IE_SW1);
panic("Unimplemented sw1 handler");
} else if (pending & IE_SW0) {
clear_c0_cause(IE_SW0);
panic("Unimplemented sw0 handler");
}
}
...@@ -60,15 +60,15 @@ rtc_ds1742_get_time(void) ...@@ -60,15 +60,15 @@ rtc_ds1742_get_time(void)
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&rtc_lock, flags); spin_lock_irqsave(&rtc_lock, flags);
CMOS_WRITE(RTC_READ, RTC_CONTROL); rtc_write(RTC_READ, RTC_CONTROL);
second = BCD2BIN(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK); second = BCD2BIN(rtc_read(RTC_SECONDS) & RTC_SECONDS_MASK);
minute = BCD2BIN(CMOS_READ(RTC_MINUTES)); minute = BCD2BIN(rtc_read(RTC_MINUTES));
hour = BCD2BIN(CMOS_READ(RTC_HOURS)); hour = BCD2BIN(rtc_read(RTC_HOURS));
day = BCD2BIN(CMOS_READ(RTC_DATE)); day = BCD2BIN(rtc_read(RTC_DATE));
month = BCD2BIN(CMOS_READ(RTC_MONTH)); month = BCD2BIN(rtc_read(RTC_MONTH));
year = BCD2BIN(CMOS_READ(RTC_YEAR)); year = BCD2BIN(rtc_read(RTC_YEAR));
century = BCD2BIN(CMOS_READ(RTC_CENTURY) & RTC_CENTURY_MASK); century = BCD2BIN(rtc_read(RTC_CENTURY) & RTC_CENTURY_MASK);
CMOS_WRITE(0, RTC_CONTROL); rtc_write(0, RTC_CONTROL);
spin_unlock_irqrestore(&rtc_lock, flags); spin_unlock_irqrestore(&rtc_lock, flags);
year += century * 100; year += century * 100;
...@@ -87,16 +87,16 @@ rtc_ds1742_set_time(unsigned long t) ...@@ -87,16 +87,16 @@ rtc_ds1742_set_time(unsigned long t)
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&rtc_lock, flags); spin_lock_irqsave(&rtc_lock, flags);
CMOS_WRITE(RTC_READ, RTC_CONTROL); rtc_write(RTC_READ, RTC_CONTROL);
cmos_second = (u8)(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK); cmos_second = (u8)(rtc_read(RTC_SECONDS) & RTC_SECONDS_MASK);
cmos_minute = (u8)CMOS_READ(RTC_MINUTES); cmos_minute = (u8)rtc_read(RTC_MINUTES);
cmos_hour = (u8)CMOS_READ(RTC_HOURS); cmos_hour = (u8)rtc_read(RTC_HOURS);
cmos_day = (u8)CMOS_READ(RTC_DATE); cmos_day = (u8)rtc_read(RTC_DATE);
cmos_month = (u8)CMOS_READ(RTC_MONTH); cmos_month = (u8)rtc_read(RTC_MONTH);
cmos_year = (u8)CMOS_READ(RTC_YEAR); cmos_year = (u8)rtc_read(RTC_YEAR);
cmos_century = CMOS_READ(RTC_CENTURY) & RTC_CENTURY_MASK; cmos_century = rtc_read(RTC_CENTURY) & RTC_CENTURY_MASK;
CMOS_WRITE(RTC_WRITE, RTC_CONTROL); rtc_write(RTC_WRITE, RTC_CONTROL);
/* convert */ /* convert */
to_tm(t, &tm); to_tm(t, &tm);
...@@ -104,18 +104,18 @@ rtc_ds1742_set_time(unsigned long t) ...@@ -104,18 +104,18 @@ rtc_ds1742_set_time(unsigned long t)
/* check each field one by one */ /* check each field one by one */
year = BIN2BCD(tm.tm_year - EPOCH); year = BIN2BCD(tm.tm_year - EPOCH);
if (year != cmos_year) { if (year != cmos_year) {
CMOS_WRITE(year,RTC_YEAR); rtc_write(year,RTC_YEAR);
} }
month = BIN2BCD(tm.tm_mon); month = BIN2BCD(tm.tm_mon);
if (month != (cmos_month & 0x1f)) { if (month != (cmos_month & 0x1f)) {
CMOS_WRITE((month & 0x1f) | (cmos_month & ~0x1f),RTC_MONTH); rtc_write((month & 0x1f) | (cmos_month & ~0x1f),RTC_MONTH);
} }
day = BIN2BCD(tm.tm_mday); day = BIN2BCD(tm.tm_mday);
if (day != cmos_day) { if (day != cmos_day) {
CMOS_WRITE(day, RTC_DATE); rtc_write(day, RTC_DATE);
} }
if (cmos_hour & 0x40) { if (cmos_hour & 0x40) {
...@@ -130,20 +130,20 @@ rtc_ds1742_set_time(unsigned long t) ...@@ -130,20 +130,20 @@ rtc_ds1742_set_time(unsigned long t)
/* 24 hour format */ /* 24 hour format */
hour = BIN2BCD(tm.tm_hour) & 0x3f; hour = BIN2BCD(tm.tm_hour) & 0x3f;
} }
if (hour != cmos_hour) CMOS_WRITE(hour, RTC_HOURS); if (hour != cmos_hour) rtc_write(hour, RTC_HOURS);
minute = BIN2BCD(tm.tm_min); minute = BIN2BCD(tm.tm_min);
if (minute != cmos_minute) { if (minute != cmos_minute) {
CMOS_WRITE(minute, RTC_MINUTES); rtc_write(minute, RTC_MINUTES);
} }
second = BIN2BCD(tm.tm_sec); second = BIN2BCD(tm.tm_sec);
if (second != cmos_second) { if (second != cmos_second) {
CMOS_WRITE(second & RTC_SECONDS_MASK,RTC_SECONDS); rtc_write(second & RTC_SECONDS_MASK,RTC_SECONDS);
} }
/* RTC_CENTURY and RTC_CONTROL share same address... */ /* RTC_CENTURY and RTC_CONTROL share same address... */
CMOS_WRITE(cmos_century, RTC_CONTROL); rtc_write(cmos_century, RTC_CONTROL);
spin_unlock_irqrestore(&rtc_lock, flags); spin_unlock_irqrestore(&rtc_lock, flags);
return 0; return 0;
...@@ -163,9 +163,9 @@ rtc_ds1742_init(unsigned long base) ...@@ -163,9 +163,9 @@ rtc_ds1742_init(unsigned long base)
rtc_mips_set_time = rtc_ds1742_set_time; rtc_mips_set_time = rtc_ds1742_set_time;
/* clear oscillator stop bit */ /* clear oscillator stop bit */
CMOS_WRITE(RTC_READ, RTC_CONTROL); rtc_write(RTC_READ, RTC_CONTROL);
cmos_second = (u8)(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK); cmos_second = (u8)(rtc_read(RTC_SECONDS) & RTC_SECONDS_MASK);
CMOS_WRITE(RTC_WRITE, RTC_CONTROL); rtc_write(RTC_WRITE, RTC_CONTROL);
CMOS_WRITE(cmos_second, RTC_SECONDS); /* clear msb */ rtc_write(cmos_second, RTC_SECONDS); /* clear msb */
CMOS_WRITE(0, RTC_CONTROL); rtc_write(0, RTC_CONTROL);
} }
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# Makefile for TOSHIBA JMR-TX3927 board # Makefile for TOSHIBA JMR-TX3927 board
# #
obj-y += init.o int-handler.o irq.o setup.o obj-y += init.o irq.o setup.o
obj-$(CONFIG_RUNTIME_DEBUG) += debug.o obj-$(CONFIG_RUNTIME_DEBUG) += debug.o
obj-$(CONFIG_KGDB) += kgdb_io.o obj-$(CONFIG_KGDB) += kgdb_io.o
......
/*
* Copyright 2001 MontaVista Software Inc.
* Author: MontaVista Software, Inc.
* ahennessy@mvista.com
*
* Based on arch/mips/tsdb/kernel/int-handler.S
*
* Copyright (C) 2000-2001 Toshiba Corporation
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <asm/asm.h>
#include <asm/mipsregs.h>
#include <asm/regdef.h>
#include <asm/stackframe.h>
#include <asm/jmr3927/jmr3927.h>
/* A lot of complication here is taken away because:
*
* 1) We handle one interrupt and return, sitting in a loop
* and moving across all the pending IRQ bits in the cause
* register is _NOT_ the answer, the common case is one
* pending IRQ so optimize in that direction.
*
* 2) We need not check against bits in the status register
* IRQ mask, that would make this routine slow as hell.
*
* 3) Linux only thinks in terms of all IRQs on or all IRQs
* off, nothing in between like BSD spl() brain-damage.
*
*/
/* Flush write buffer (needed?)
* NOTE: TX39xx performs "non-blocking load", so explicitly use the target
* register of LBU to flush immediately.
*/
#define FLUSH_WB(tmp) \
la tmp, JMR3927_IOC_REV_ADDR; \
lbu tmp, (tmp); \
move tmp, zero;
.text
.set noreorder
.set noat
.align 5
NESTED(jmr3927_IRQ, PT_SIZE, sp)
SAVE_ALL
CLI
.set at
jal jmr3927_irc_irqdispatch
move a0, sp
FLUSH_WB(t0)
j ret_from_irq
nop
END(jmr3927_IRQ)
...@@ -77,8 +77,6 @@ static int jmr3927_gen_iack(void) ...@@ -77,8 +77,6 @@ static int jmr3927_gen_iack(void)
} }
#endif #endif
extern asmlinkage void jmr3927_IRQ(void);
#define irc_dlevel 0 #define irc_dlevel 0
#define irc_elevel 1 #define irc_elevel 1
...@@ -262,7 +260,7 @@ void jmr3927_spurious(struct pt_regs *regs) ...@@ -262,7 +260,7 @@ void jmr3927_spurious(struct pt_regs *regs)
regs->cp0_cause, regs->cp0_epc, regs->regs[31]); regs->cp0_cause, regs->cp0_epc, regs->regs[31]);
} }
void jmr3927_irc_irqdispatch(struct pt_regs *regs) asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
{ {
int irq; int irq;
...@@ -398,8 +396,6 @@ void __init arch_init_irq(void) ...@@ -398,8 +396,6 @@ void __init arch_init_irq(void)
jmr3927_irq_init(NR_ISA_IRQS); jmr3927_irq_init(NR_ISA_IRQS);
set_except_vector(0, jmr3927_IRQ);
/* setup irq space */ /* setup irq space */
add_tb_irq_space(&jmr3927_isac_irqspace); add_tb_irq_space(&jmr3927_isac_irqspace);
add_tb_irq_space(&jmr3927_ioc_irqspace); add_tb_irq_space(&jmr3927_ioc_irqspace);
......
...@@ -34,8 +34,11 @@ obj-$(CONFIG_CPU_R6000) += r6000_fpu.o r4k_switch.o ...@@ -34,8 +34,11 @@ obj-$(CONFIG_CPU_R6000) += r6000_fpu.o r4k_switch.o
obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_MIPS_MT_SMP) += smp_mt.o obj-$(CONFIG_MIPS_MT) += mips-mt.o
obj-$(CONFIG_MIPS_MT_SMTC) += smtc.o smtc-asm.o smtc-proc.o
obj-$(CONFIG_MIPS_MT_SMP) += smp-mt.o
obj-$(CONFIG_MIPS_APSP_KSPD) += kspd.o
obj-$(CONFIG_MIPS_VPE_LOADER) += vpe.o obj-$(CONFIG_MIPS_VPE_LOADER) += vpe.o
obj-$(CONFIG_MIPS_VPE_APSP_API) += rtlx.o obj-$(CONFIG_MIPS_VPE_APSP_API) += rtlx.o
......
...@@ -69,6 +69,9 @@ void output_ptreg_defines(void) ...@@ -69,6 +69,9 @@ void output_ptreg_defines(void)
offset("#define PT_BVADDR ", struct pt_regs, cp0_badvaddr); offset("#define PT_BVADDR ", struct pt_regs, cp0_badvaddr);
offset("#define PT_STATUS ", struct pt_regs, cp0_status); offset("#define PT_STATUS ", struct pt_regs, cp0_status);
offset("#define PT_CAUSE ", struct pt_regs, cp0_cause); offset("#define PT_CAUSE ", struct pt_regs, cp0_cause);
#ifdef CONFIG_MIPS_MT_SMTC
offset("#define PT_TCSTATUS ", struct pt_regs, cp0_tcstatus);
#endif /* CONFIG_MIPS_MT_SMTC */
size("#define PT_SIZE ", struct pt_regs); size("#define PT_SIZE ", struct pt_regs);
linefeed; linefeed;
} }
......
...@@ -17,6 +17,9 @@ ...@@ -17,6 +17,9 @@
#include <asm/isadep.h> #include <asm/isadep.h>
#include <asm/thread_info.h> #include <asm/thread_info.h>
#include <asm/war.h> #include <asm/war.h>
#ifdef CONFIG_MIPS_MT_SMTC
#include <asm/mipsmtregs.h>
#endif
#ifdef CONFIG_PREEMPT #ifdef CONFIG_PREEMPT
.macro preempt_stop .macro preempt_stop
...@@ -75,6 +78,37 @@ FEXPORT(syscall_exit) ...@@ -75,6 +78,37 @@ FEXPORT(syscall_exit)
bnez t0, syscall_exit_work bnez t0, syscall_exit_work
FEXPORT(restore_all) # restore full frame FEXPORT(restore_all) # restore full frame
#ifdef CONFIG_MIPS_MT_SMTC
/* Detect and execute deferred IPI "interrupts" */
move a0,sp
jal deferred_smtc_ipi
/* Re-arm any temporarily masked interrupts not explicitly "acked" */
mfc0 v0, CP0_TCSTATUS
ori v1, v0, TCSTATUS_IXMT
mtc0 v1, CP0_TCSTATUS
andi v0, TCSTATUS_IXMT
ehb
mfc0 t0, CP0_TCCONTEXT
DMT 9 # dmt t1
jal mips_ihb
mfc0 t2, CP0_STATUS
andi t3, t0, 0xff00
or t2, t2, t3
mtc0 t2, CP0_STATUS
ehb
andi t1, t1, VPECONTROL_TE
beqz t1, 1f
EMT
1:
mfc0 v1, CP0_TCSTATUS
/* We set IXMT above, XOR should cler it here */
xori v1, v1, TCSTATUS_IXMT
or v1, v0, v1
mtc0 v1, CP0_TCSTATUS
ehb
xor t0, t0, t3
mtc0 t0, CP0_TCCONTEXT
#endif /* CONFIG_MIPS_MT_SMTC */
.set noat .set noat
RESTORE_TEMP RESTORE_TEMP
RESTORE_AT RESTORE_AT
...@@ -120,28 +154,17 @@ syscall_exit_work: ...@@ -120,28 +154,17 @@ syscall_exit_work:
jal do_syscall_trace jal do_syscall_trace
b resume_userspace b resume_userspace
#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_MIPS_MT)
/* /*
* Common spurious interrupt handler. * MIPS32R2 Instruction Hazard Barrier - must be called
*
* For C code use the inline version named instruction_hazard().
*/ */
LEAF(spurious_interrupt) LEAF(mips_ihb)
/* .set mips32r2
* Someone tried to fool us by sending an interrupt but we jr.hb ra
* couldn't find a cause for it. nop
*/ END(mips_ihb)
PTR_LA t1, irq_err_count
#ifdef CONFIG_SMP #endif /* CONFIG_CPU_MIPSR2 or CONFIG_MIPS_MT */
1: ll t0, (t1)
addiu t0, 1
sc t0, (t1)
#if R10000_LLSC_WAR
beqzl t0, 1b
#else
beqz t0, 1b
#endif
#else
lw t0, (t1)
addiu t0, 1
sw t0, (t1)
#endif
j ret_from_irq
END(spurious_interrupt)
...@@ -283,11 +283,33 @@ ...@@ -283,11 +283,33 @@
*/ */
3: 3:
#ifdef CONFIG_MIPS_MT_SMTC
/* Read-modify write of Status must be atomic */
mfc0 t2, CP0_TCSTATUS
ori t1, t2, TCSTATUS_IXMT
mtc0 t1, CP0_TCSTATUS
andi t2, t2, TCSTATUS_IXMT
ehb
DMT 9 # dmt t1
jal mips_ihb
nop
#endif /* CONFIG_MIPS_MT_SMTC */
mfc0 t0, CP0_STATUS mfc0 t0, CP0_STATUS
ori t0, 0x1f ori t0, 0x1f
xori t0, 0x1f xori t0, 0x1f
mtc0 t0, CP0_STATUS mtc0 t0, CP0_STATUS
#ifdef CONFIG_MIPS_MT_SMTC
andi t1, t1, VPECONTROL_TE
beqz t1, 9f
nop
EMT # emt
9:
mfc0 t1, CP0_TCSTATUS
xori t1, t1, TCSTATUS_IXMT
or t1, t1, t2
mtc0 t1, CP0_TCSTATUS
ehb
#endif /* CONFIG_MIPS_MT_SMTC */
LONG_L v0, GDB_FR_STATUS(sp) LONG_L v0, GDB_FR_STATUS(sp)
LONG_L v1, GDB_FR_EPC(sp) LONG_L v1, GDB_FR_EPC(sp)
mtc0 v0, CP0_STATUS mtc0 v0, CP0_STATUS
......
...@@ -140,6 +140,7 @@ ...@@ -140,6 +140,7 @@
#include <asm/system.h> #include <asm/system.h>
#include <asm/gdb-stub.h> #include <asm/gdb-stub.h>
#include <asm/inst.h> #include <asm/inst.h>
#include <asm/smp.h>
/* /*
* external low-level support routines * external low-level support routines
...@@ -669,6 +670,64 @@ static void kgdb_wait(void *arg) ...@@ -669,6 +670,64 @@ static void kgdb_wait(void *arg)
local_irq_restore(flags); local_irq_restore(flags);
} }
/*
* GDB stub needs to call kgdb_wait on all processor with interrupts
* disabled, so it uses it's own special variant.
*/
static int kgdb_smp_call_kgdb_wait(void)
{
#ifdef CONFIG_SMP
struct call_data_struct data;
int i, cpus = num_online_cpus() - 1;
int cpu = smp_processor_id();
/*
* Can die spectacularly if this CPU isn't yet marked online
*/
BUG_ON(!cpu_online(cpu));
if (!cpus)
return 0;
if (spin_is_locked(&smp_call_lock)) {
/*
* Some other processor is trying to make us do something
* but we're not going to respond... give up
*/
return -1;
}
/*
* We will continue here, accepting the fact that
* the kernel may deadlock if another CPU attempts
* to call smp_call_function now...
*/
data.func = kgdb_wait;
data.info = NULL;
atomic_set(&data.started, 0);
data.wait = 0;
spin_lock(&smp_call_lock);
call_data = &data;
mb();
/* Send a message to all other CPUs and wait for them to respond */
for (i = 0; i < NR_CPUS; i++)
if (cpu_online(i) && i != cpu)
core_send_ipi(i, SMP_CALL_FUNCTION);
/* Wait for response */
/* FIXME: lock-up detection, backtrace on lock-up */
while (atomic_read(&data.started) != cpus)
barrier();
call_data = NULL;
spin_unlock(&smp_call_lock);
#endif
return 0;
}
/* /*
* This function does all command processing for interfacing to gdb. It * This function does all command processing for interfacing to gdb. It
...@@ -718,7 +777,7 @@ void handle_exception (struct gdb_regs *regs) ...@@ -718,7 +777,7 @@ void handle_exception (struct gdb_regs *regs)
/* /*
* force other cpus to enter kgdb * force other cpus to enter kgdb
*/ */
smp_call_function(kgdb_wait, NULL, 0, 0); kgdb_smp_call_kgdb_wait();
/* /*
* If we're in breakpoint() increment the PC * If we're in breakpoint() increment the PC
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <asm/asm.h> #include <asm/asm.h>
#include <asm/asmmacro.h>
#include <asm/cacheops.h> #include <asm/cacheops.h>
#include <asm/regdef.h> #include <asm/regdef.h>
#include <asm/fpregdef.h> #include <asm/fpregdef.h>
...@@ -122,6 +123,20 @@ handle_vcei: ...@@ -122,6 +123,20 @@ handle_vcei:
.set pop .set pop
END(except_vec3_r4000) END(except_vec3_r4000)
__FINIT
.align 5
NESTED(handle_int, PT_SIZE, sp)
SAVE_ALL
CLI
PTR_LA ra, ret_from_irq
move a0, sp
j plat_irq_dispatch
END(handle_int)
__INIT
/* /*
* Special interrupt vector for MIPS64 ISA & embedded MIPS processors. * Special interrupt vector for MIPS64 ISA & embedded MIPS processors.
* This is a dedicated interrupt exception vector which reduces the * This is a dedicated interrupt exception vector which reduces the
...@@ -157,6 +172,15 @@ NESTED(except_vec_vi, 0, sp) ...@@ -157,6 +172,15 @@ NESTED(except_vec_vi, 0, sp)
SAVE_AT SAVE_AT
.set push .set push
.set noreorder .set noreorder
#ifdef CONFIG_MIPS_MT_SMTC
/*
* To keep from blindly blocking *all* interrupts
* during service by SMTC kernel, we also want to
* pass the IM value to be cleared.
*/
EXPORT(except_vec_vi_mori)
ori a0, $0, 0
#endif /* CONFIG_MIPS_MT_SMTC */
EXPORT(except_vec_vi_lui) EXPORT(except_vec_vi_lui)
lui v0, 0 /* Patched */ lui v0, 0 /* Patched */
j except_vec_vi_handler j except_vec_vi_handler
...@@ -173,6 +197,25 @@ EXPORT(except_vec_vi_end) ...@@ -173,6 +197,25 @@ EXPORT(except_vec_vi_end)
NESTED(except_vec_vi_handler, 0, sp) NESTED(except_vec_vi_handler, 0, sp)
SAVE_TEMP SAVE_TEMP
SAVE_STATIC SAVE_STATIC
#ifdef CONFIG_MIPS_MT_SMTC
/*
* SMTC has an interesting problem that interrupts are level-triggered,
* and the CLI macro will clear EXL, potentially causing a duplicate
* interrupt service invocation. So we need to clear the associated
* IM bit of Status prior to doing CLI, and restore it after the
* service routine has been invoked - we must assume that the
* service routine will have cleared the state, and any active
* level represents a new or otherwised unserviced event...
*/
mfc0 t1, CP0_STATUS
and t0, a0, t1
mfc0 t2, CP0_TCCONTEXT
or t0, t0, t2
mtc0 t0, CP0_TCCONTEXT
xor t1, t1, t0
mtc0 t1, CP0_STATUS
ehb
#endif /* CONFIG_MIPS_MT_SMTC */
CLI CLI
move a0, sp move a0, sp
jalr v0 jalr v0
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/threads.h> #include <linux/threads.h>
#include <asm/asm.h> #include <asm/asm.h>
#include <asm/asmmacro.h>
#include <asm/regdef.h> #include <asm/regdef.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/mipsregs.h> #include <asm/mipsregs.h>
...@@ -82,12 +83,33 @@ ...@@ -82,12 +83,33 @@
*/ */
.macro setup_c0_status set clr .macro setup_c0_status set clr
.set push .set push
#ifdef CONFIG_MIPS_MT_SMTC
/*
* For SMTC, we need to set privilege and disable interrupts only for
* the current TC, using the TCStatus register.
*/
mfc0 t0, CP0_TCSTATUS
/* Fortunately CU 0 is in the same place in both registers */
/* Set TCU0, TMX, TKSU (for later inversion) and IXMT */
li t1, ST0_CU0 | 0x08001c00
or t0, t1
/* Clear TKSU, leave IXMT */
xori t0, 0x00001800
mtc0 t0, CP0_TCSTATUS
ehb
/* We need to leave the global IE bit set, but clear EXL...*/
mfc0 t0, CP0_STATUS
or t0, ST0_CU0 | ST0_EXL | ST0_ERL | \set | \clr
xor t0, ST0_EXL | ST0_ERL | \clr
mtc0 t0, CP0_STATUS
#else
mfc0 t0, CP0_STATUS mfc0 t0, CP0_STATUS
or t0, ST0_CU0|\set|0x1f|\clr or t0, ST0_CU0|\set|0x1f|\clr
xor t0, 0x1f|\clr xor t0, 0x1f|\clr
mtc0 t0, CP0_STATUS mtc0 t0, CP0_STATUS
.set noreorder .set noreorder
sll zero,3 # ehb sll zero,3 # ehb
#endif
.set pop .set pop
.endm .endm
...@@ -134,6 +156,24 @@ NESTED(kernel_entry, 16, sp) # kernel entry point ...@@ -134,6 +156,24 @@ NESTED(kernel_entry, 16, sp) # kernel entry point
ARC64_TWIDDLE_PC ARC64_TWIDDLE_PC
#ifdef CONFIG_MIPS_MT_SMTC
/*
* In SMTC kernel, "CLI" is thread-specific, in TCStatus.
* We still need to enable interrupts globally in Status,
* and clear EXL/ERL.
*
* TCContext is used to track interrupt levels under
* service in SMTC kernel. Clear for boot TC before
* allowing any interrupts.
*/
mtc0 zero, CP0_TCCONTEXT
mfc0 t0, CP0_STATUS
ori t0, t0, 0xff1f
xori t0, t0, 0x001e
mtc0 t0, CP0_STATUS
#endif /* CONFIG_MIPS_MT_SMTC */
PTR_LA t0, __bss_start # clear .bss PTR_LA t0, __bss_start # clear .bss
LONG_S zero, (t0) LONG_S zero, (t0)
PTR_LA t1, __bss_stop - LONGSIZE PTR_LA t1, __bss_stop - LONGSIZE
...@@ -166,8 +206,25 @@ NESTED(kernel_entry, 16, sp) # kernel entry point ...@@ -166,8 +206,25 @@ NESTED(kernel_entry, 16, sp) # kernel entry point
* function after setting up the stack and gp registers. * function after setting up the stack and gp registers.
*/ */
NESTED(smp_bootstrap, 16, sp) NESTED(smp_bootstrap, 16, sp)
#ifdef CONFIG_MIPS_MT_SMTC
/*
* Read-modify-writes of Status must be atomic, and this
* is one case where CLI is invoked without EXL being
* necessarily set. The CLI and setup_c0_status will
* in fact be redundant for all but the first TC of
* each VPE being booted.
*/
DMT 10 # dmt t2 /* t0, t1 are used by CLI and setup_c0_status() */
jal mips_ihb
#endif /* CONFIG_MIPS_MT_SMTC */
setup_c0_status_sec setup_c0_status_sec
smp_slave_setup smp_slave_setup
#ifdef CONFIG_MIPS_MT_SMTC
andi t2, t2, VPECONTROL_TE
beqz t2, 2f
EMT # emt
2:
#endif /* CONFIG_MIPS_MT_SMTC */
j start_secondary j start_secondary
END(smp_bootstrap) END(smp_bootstrap)
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
......
...@@ -187,6 +187,10 @@ void mask_and_ack_8259A(unsigned int irq) ...@@ -187,6 +187,10 @@ void mask_and_ack_8259A(unsigned int irq)
outb(cached_21,0x21); outb(cached_21,0x21);
outb(0x60+irq,0x20); /* 'Specific EOI' to master */ outb(0x60+irq,0x20); /* 'Specific EOI' to master */
} }
#ifdef CONFIG_MIPS_MT_SMTC
if (irq_hwmask[irq] & ST0_IM)
set_c0_status(irq_hwmask[irq] & ST0_IM);
#endif /* CONFIG_MIPS_MT_SMTC */
spin_unlock_irqrestore(&i8259A_lock, flags); spin_unlock_irqrestore(&i8259A_lock, flags);
return; return;
......
...@@ -76,6 +76,11 @@ static void level_mask_and_ack_msc_irq(unsigned int irq) ...@@ -76,6 +76,11 @@ static void level_mask_and_ack_msc_irq(unsigned int irq)
mask_msc_irq(irq); mask_msc_irq(irq);
if (!cpu_has_veic) if (!cpu_has_veic)
MSCIC_WRITE(MSC01_IC_EOI, 0); MSCIC_WRITE(MSC01_IC_EOI, 0);
#ifdef CONFIG_MIPS_MT_SMTC
/* This actually needs to be a call into platform code */
if (irq_hwmask[irq] & ST0_IM)
set_c0_status(irq_hwmask[irq] & ST0_IM);
#endif /* CONFIG_MIPS_MT_SMTC */
} }
/* /*
...@@ -92,6 +97,10 @@ static void edge_mask_and_ack_msc_irq(unsigned int irq) ...@@ -92,6 +97,10 @@ static void edge_mask_and_ack_msc_irq(unsigned int irq)
MSCIC_WRITE(MSC01_IC_SUP+irq*8, r | ~MSC01_IC_SUP_EDGE_BIT); MSCIC_WRITE(MSC01_IC_SUP+irq*8, r | ~MSC01_IC_SUP_EDGE_BIT);
MSCIC_WRITE(MSC01_IC_SUP+irq*8, r); MSCIC_WRITE(MSC01_IC_SUP+irq*8, r);
} }
#ifdef CONFIG_MIPS_MT_SMTC
if (irq_hwmask[irq] & ST0_IM)
set_c0_status(irq_hwmask[irq] & ST0_IM);
#endif /* CONFIG_MIPS_MT_SMTC */
} }
/* /*
......
...@@ -38,6 +38,15 @@ void ack_bad_irq(unsigned int irq) ...@@ -38,6 +38,15 @@ void ack_bad_irq(unsigned int irq)
atomic_t irq_err_count; atomic_t irq_err_count;
#ifdef CONFIG_MIPS_MT_SMTC
/*
* SMTC Kernel needs to manipulate low-level CPU interrupt mask
* in do_IRQ. These are passed in setup_irq_smtc() and stored
* in this table.
*/
unsigned long irq_hwmask[NR_IRQS];
#endif /* CONFIG_MIPS_MT_SMTC */
#undef do_IRQ #undef do_IRQ
/* /*
...@@ -49,6 +58,7 @@ asmlinkage unsigned int do_IRQ(unsigned int irq, struct pt_regs *regs) ...@@ -49,6 +58,7 @@ asmlinkage unsigned int do_IRQ(unsigned int irq, struct pt_regs *regs)
{ {
irq_enter(); irq_enter();
__DO_IRQ_SMTC_HOOK();
__do_IRQ(irq, regs); __do_IRQ(irq, regs);
irq_exit(); irq_exit();
...@@ -101,6 +111,11 @@ int show_interrupts(struct seq_file *p, void *v) ...@@ -101,6 +111,11 @@ int show_interrupts(struct seq_file *p, void *v)
return 0; return 0;
} }
asmlinkage void spurious_interrupt(struct pt_regs *regs)
{
atomic_inc(&irq_err_count);
}
#ifdef CONFIG_KGDB #ifdef CONFIG_KGDB
extern void breakpoint(void); extern void breakpoint(void);
extern void set_debug_traps(void); extern void set_debug_traps(void);
...@@ -124,6 +139,9 @@ void __init init_IRQ(void) ...@@ -124,6 +139,9 @@ void __init init_IRQ(void)
irq_desc[i].depth = 1; irq_desc[i].depth = 1;
irq_desc[i].handler = &no_irq_type; irq_desc[i].handler = &no_irq_type;
spin_lock_init(&irq_desc[i].lock); spin_lock_init(&irq_desc[i].lock);
#ifdef CONFIG_MIPS_MT_SMTC
irq_hwmask[i] = 0;
#endif /* CONFIG_MIPS_MT_SMTC */
} }
arch_init_irq(); arch_init_irq();
......
/*
* Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved.
*
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/unistd.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/syscalls.h>
#include <linux/workqueue.h>
#include <linux/errno.h>
#include <linux/list.h>
#include <asm/vpe.h>
#include <asm/rtlx.h>
#include <asm/kspd.h>
static struct workqueue_struct *workqueue = NULL;
static struct work_struct work;
extern unsigned long cpu_khz;
struct mtsp_syscall {
int cmd;
unsigned char abi;
unsigned char size;
};
struct mtsp_syscall_ret {
int retval;
int errno;
};
struct mtsp_syscall_generic {
int arg0;
int arg1;
int arg2;
int arg3;
int arg4;
int arg5;
int arg6;
};
static struct list_head kspd_notifylist;
static int sp_stopping = 0;
/* these should match with those in the SDE kit */
#define MTSP_SYSCALL_BASE 0
#define MTSP_SYSCALL_EXIT (MTSP_SYSCALL_BASE + 0)
#define MTSP_SYSCALL_OPEN (MTSP_SYSCALL_BASE + 1)
#define MTSP_SYSCALL_READ (MTSP_SYSCALL_BASE + 2)
#define MTSP_SYSCALL_WRITE (MTSP_SYSCALL_BASE + 3)
#define MTSP_SYSCALL_CLOSE (MTSP_SYSCALL_BASE + 4)
#define MTSP_SYSCALL_LSEEK32 (MTSP_SYSCALL_BASE + 5)
#define MTSP_SYSCALL_ISATTY (MTSP_SYSCALL_BASE + 6)
#define MTSP_SYSCALL_GETTIME (MTSP_SYSCALL_BASE + 7)
#define MTSP_SYSCALL_PIPEFREQ (MTSP_SYSCALL_BASE + 8)
#define MTSP_SYSCALL_GETTOD (MTSP_SYSCALL_BASE + 9)
#define MTSP_O_RDONLY 0x0000
#define MTSP_O_WRONLY 0x0001
#define MTSP_O_RDWR 0x0002
#define MTSP_O_NONBLOCK 0x0004
#define MTSP_O_APPEND 0x0008
#define MTSP_O_SHLOCK 0x0010
#define MTSP_O_EXLOCK 0x0020
#define MTSP_O_ASYNC 0x0040
#define MTSP_O_FSYNC O_SYNC
#define MTSP_O_NOFOLLOW 0x0100
#define MTSP_O_SYNC 0x0080
#define MTSP_O_CREAT 0x0200
#define MTSP_O_TRUNC 0x0400
#define MTSP_O_EXCL 0x0800
#define MTSP_O_BINARY 0x8000
#define SP_VPE 1
struct apsp_table {
int sp;
int ap;
};
/* we might want to do the mode flags too */
struct apsp_table open_flags_table[] = {
{ MTSP_O_RDWR, O_RDWR },
{ MTSP_O_WRONLY, O_WRONLY },
{ MTSP_O_CREAT, O_CREAT },
{ MTSP_O_TRUNC, O_TRUNC },
{ MTSP_O_NONBLOCK, O_NONBLOCK },
{ MTSP_O_APPEND, O_APPEND },
{ MTSP_O_NOFOLLOW, O_NOFOLLOW }
};
struct apsp_table syscall_command_table[] = {
{ MTSP_SYSCALL_OPEN, __NR_open },
{ MTSP_SYSCALL_CLOSE, __NR_close },
{ MTSP_SYSCALL_READ, __NR_read },
{ MTSP_SYSCALL_WRITE, __NR_write },
{ MTSP_SYSCALL_LSEEK32, __NR_lseek }
};
static int sp_syscall(int num, int arg0, int arg1, int arg2, int arg3)
{
register long int _num __asm__ ("$2") = num;
register long int _arg0 __asm__ ("$4") = arg0;
register long int _arg1 __asm__ ("$5") = arg1;
register long int _arg2 __asm__ ("$6") = arg2;
register long int _arg3 __asm__ ("$7") = arg3;
mm_segment_t old_fs;
old_fs = get_fs();
set_fs(KERNEL_DS);
__asm__ __volatile__ (
" syscall \n"
: "=r" (_num), "=r" (_arg3)
: "r" (_num), "r" (_arg0), "r" (_arg1), "r" (_arg2), "r" (_arg3));
set_fs(old_fs);
/* $a3 is error flag */
if (_arg3)
return -_num;
return _num;
}
static int translate_syscall_command(int cmd)
{
int i;
int ret = -1;
for (i = 0; i < ARRAY_SIZE(syscall_command_table); i++) {
if ((cmd == syscall_command_table[i].sp))
return syscall_command_table[i].ap;
}
return ret;
}
static unsigned int translate_open_flags(int flags)
{
int i;
unsigned int ret = 0;
for (i = 0; i < (sizeof(open_flags_table) / sizeof(struct apsp_table));
i++) {
if( (flags & open_flags_table[i].sp) ) {
ret |= open_flags_table[i].ap;
}
}
return ret;
}
static void sp_setfsuidgid( uid_t uid, gid_t gid)
{
current->fsuid = uid;
current->fsgid = gid;
key_fsuid_changed(current);
key_fsgid_changed(current);
}
/*
* Expects a request to be on the sysio channel. Reads it. Decides whether
* its a linux syscall and runs it, or whatever. Puts the return code back
* into the request and sends the whole thing back.
*/
void sp_work_handle_request(void)
{
struct mtsp_syscall sc;
struct mtsp_syscall_generic generic;
struct mtsp_syscall_ret ret;
struct kspd_notifications *n;
struct timeval tv;
struct timezone tz;
int cmd;
char *vcwd;
mm_segment_t old_fs;
int size;
ret.retval = -1;
if (!rtlx_read(RTLX_CHANNEL_SYSIO, &sc, sizeof(struct mtsp_syscall), 0)) {
printk(KERN_ERR "Expected request but nothing to read\n");
return;
}
size = sc.size;
if (size) {
if (!rtlx_read(RTLX_CHANNEL_SYSIO, &generic, size, 0)) {
printk(KERN_ERR "Expected request but nothing to read\n");
return;
}
}
/* Run the syscall at the priviledge of the user who loaded the
SP program */
if (vpe_getuid(SP_VPE))
sp_setfsuidgid( vpe_getuid(SP_VPE), vpe_getgid(SP_VPE));
switch (sc.cmd) {
/* needs the flags argument translating from SDE kit to
linux */
case MTSP_SYSCALL_PIPEFREQ:
ret.retval = cpu_khz * 1000;
ret.errno = 0;
break;
case MTSP_SYSCALL_GETTOD:
memset(&tz, 0, sizeof(tz));
if ((ret.retval = sp_syscall(__NR_gettimeofday, (int)&tv,
(int)&tz, 0,0)) == 0)
ret.retval = tv.tv_sec;
ret.errno = errno;
break;
case MTSP_SYSCALL_EXIT:
list_for_each_entry(n, &kspd_notifylist, list)
n->kspd_sp_exit(SP_VPE);
sp_stopping = 1;
printk(KERN_DEBUG "KSPD got exit syscall from SP exitcode %d\n",
generic.arg0);
break;
case MTSP_SYSCALL_OPEN:
generic.arg1 = translate_open_flags(generic.arg1);
vcwd = vpe_getcwd(SP_VPE);
/* change to the cwd of the process that loaded the SP program */
old_fs = get_fs();
set_fs(KERNEL_DS);
sys_chdir(vcwd);
set_fs(old_fs);
sc.cmd = __NR_open;
/* fall through */
default:
if ((sc.cmd >= __NR_Linux) &&
(sc.cmd <= (__NR_Linux + __NR_Linux_syscalls)) )
cmd = sc.cmd;
else
cmd = translate_syscall_command(sc.cmd);
if (cmd >= 0) {
ret.retval = sp_syscall(cmd, generic.arg0, generic.arg1,
generic.arg2, generic.arg3);
ret.errno = errno;
} else
printk(KERN_WARNING
"KSPD: Unknown SP syscall number %d\n", sc.cmd);
break;
} /* switch */
if (vpe_getuid(SP_VPE))
sp_setfsuidgid( 0, 0);
if ((rtlx_write(RTLX_CHANNEL_SYSIO, &ret, sizeof(struct mtsp_syscall_ret), 0))
< sizeof(struct mtsp_syscall_ret))
printk("KSPD: sp_work_handle_request failed to send to SP\n");
}
static void sp_cleanup(void)
{
struct files_struct *files = current->files;
int i, j;
struct fdtable *fdt;
j = 0;
/*
* It is safe to dereference the fd table without RCU or
* ->file_lock
*/
fdt = files_fdtable(files);
for (;;) {
unsigned long set;
i = j * __NFDBITS;
if (i >= fdt->max_fdset || i >= fdt->max_fds)
break;
set = fdt->open_fds->fds_bits[j++];
while (set) {
if (set & 1) {
struct file * file = xchg(&fdt->fd[i], NULL);
if (file)
filp_close(file, files);
}
i++;
set >>= 1;
}
}
}
static int channel_open = 0;
/* the work handler */
static void sp_work(void *data)
{
if (!channel_open) {
if( rtlx_open(RTLX_CHANNEL_SYSIO, 1) != 0) {
printk("KSPD: unable to open sp channel\n");
sp_stopping = 1;
} else {
channel_open++;
printk(KERN_DEBUG "KSPD: SP channel opened\n");
}
} else {
/* wait for some data, allow it to sleep */
rtlx_read_poll(RTLX_CHANNEL_SYSIO, 1);
/* Check we haven't been woken because we are stopping */
if (!sp_stopping)
sp_work_handle_request();
}
if (!sp_stopping)
queue_work(workqueue, &work);
else
sp_cleanup();
}
static void startwork(int vpe)
{
sp_stopping = channel_open = 0;
if (workqueue == NULL) {
if ((workqueue = create_singlethread_workqueue("kspd")) == NULL) {
printk(KERN_ERR "unable to start kspd\n");
return;
}
INIT_WORK(&work, sp_work, NULL);
queue_work(workqueue, &work);
} else
queue_work(workqueue, &work);
}
static void stopwork(int vpe)
{
sp_stopping = 1;
printk(KERN_DEBUG "KSPD: SP stopping\n");
}
void kspd_notify(struct kspd_notifications *notify)
{
list_add(&notify->list, &kspd_notifylist);
}
static struct vpe_notifications notify;
static int kspd_module_init(void)
{
INIT_LIST_HEAD(&kspd_notifylist);
notify.start = startwork;
notify.stop = stopwork;
vpe_notify(SP_VPE, &notify);
return 0;
}
static void kspd_module_exit(void)
{
}
module_init(kspd_module_init);
module_exit(kspd_module_exit);
MODULE_DESCRIPTION("MIPS KSPD");
MODULE_AUTHOR("Elizabeth Oldham, MIPS Technologies, Inc.");
MODULE_LICENSE("GPL");
...@@ -1182,6 +1182,16 @@ asmlinkage ssize_t sys32_readahead(int fd, u32 pad0, u64 a2, u64 a3, ...@@ -1182,6 +1182,16 @@ asmlinkage ssize_t sys32_readahead(int fd, u32 pad0, u64 a2, u64 a3,
return sys_readahead(fd, merge_64(a2, a3), count); return sys_readahead(fd, merge_64(a2, a3), count);
} }
asmlinkage long sys32_sync_file_range(int fd, int __pad,
unsigned long a2, unsigned long a3,
unsigned long a4, unsigned long a5,
int flags)
{
return sys_sync_file_range(fd,
merge_64(a2, a3), merge_64(a4, a5),
flags);
}
/* Argument list sizes for sys_socketcall */ /* Argument list sizes for sys_socketcall */
#define AL(x) ((x) * sizeof(unsigned int)) #define AL(x) ((x) * sizeof(unsigned int))
static unsigned char socketcall_nargs[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3), static unsigned char socketcall_nargs[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
......
This diff is collapsed.
...@@ -28,21 +28,9 @@ extern long __strnlen_user_asm(const char *s); ...@@ -28,21 +28,9 @@ extern long __strnlen_user_asm(const char *s);
/* /*
* String functions * String functions
*/ */
EXPORT_SYMBOL(memchr);
EXPORT_SYMBOL(memcmp);
EXPORT_SYMBOL(memset); EXPORT_SYMBOL(memset);
EXPORT_SYMBOL(memcpy); EXPORT_SYMBOL(memcpy);
EXPORT_SYMBOL(memmove); EXPORT_SYMBOL(memmove);
EXPORT_SYMBOL(strcat);
EXPORT_SYMBOL(strchr);
#ifdef CONFIG_64BIT
EXPORT_SYMBOL(strncmp);
#endif
EXPORT_SYMBOL(strlen);
EXPORT_SYMBOL(strncat);
EXPORT_SYMBOL(strnlen);
EXPORT_SYMBOL(strrchr);
EXPORT_SYMBOL(strstr);
EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL(kernel_thread);
...@@ -61,6 +49,3 @@ EXPORT_SYMBOL(__strnlen_user_asm); ...@@ -61,6 +49,3 @@ EXPORT_SYMBOL(__strnlen_user_asm);
EXPORT_SYMBOL(csum_partial); EXPORT_SYMBOL(csum_partial);
EXPORT_SYMBOL(invalid_pte_table); EXPORT_SYMBOL(invalid_pte_table);
#ifdef CONFIG_GENERIC_IRQ_PROBE
EXPORT_SYMBOL(probe_irq_mask);
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -460,3 +460,5 @@ sys_call_table: ...@@ -460,3 +460,5 @@ sys_call_table:
PTR sys_pselect6 /* 5260 */ PTR sys_pselect6 /* 5260 */
PTR sys_ppoll PTR sys_ppoll
PTR sys_unshare PTR sys_unshare
PTR sys_splice
PTR sys_sync_file_range
...@@ -386,3 +386,5 @@ EXPORT(sysn32_call_table) ...@@ -386,3 +386,5 @@ EXPORT(sysn32_call_table)
PTR sys_pselect6 PTR sys_pselect6
PTR sys_ppoll /* 6265 */ PTR sys_ppoll /* 6265 */
PTR sys_unshare PTR sys_unshare
PTR sys_splice
PTR sys_sync_file_range
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment