summaryrefslogtreecommitdiffstats
path: root/arch/mips
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/au1000/common/gpio.c6
-rw-r--r--arch/mips/kernel/cpu-probe.c16
-rw-r--r--arch/mips/kernel/genex.S37
-rw-r--r--arch/mips/kernel/kgdb.c3
-rw-r--r--arch/mips/kernel/process.c2
-rw-r--r--arch/mips/kernel/traps.c22
-rw-r--r--arch/mips/kernel/vmlinux.lds.S1
-rw-r--r--arch/mips/lib/csum_partial.S21
-rw-r--r--arch/mips/pci/Makefile1
-rw-r--r--arch/mips/pci/pci-bcm47xx.c60
-rw-r--r--arch/mips/pci/pci-ip27.c40
-rw-r--r--arch/mips/sgi-ip22/ip22-platform.c2
-rw-r--r--arch/mips/vr41xx/common/irq.c6
13 files changed, 177 insertions, 40 deletions
diff --git a/arch/mips/au1000/common/gpio.c b/arch/mips/au1000/common/gpio.c
index b485d94ce8a..e660ddd611c 100644
--- a/arch/mips/au1000/common/gpio.c
+++ b/arch/mips/au1000/common/gpio.c
@@ -48,7 +48,7 @@ static void au1xxx_gpio2_write(unsigned gpio, int value)
{
gpio -= AU1XXX_GPIO_BASE;
- gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << gpio) | (value << gpio);
+ gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << gpio) | ((!!value) << gpio);
}
static int au1xxx_gpio2_direction_input(unsigned gpio)
@@ -61,7 +61,8 @@ static int au1xxx_gpio2_direction_input(unsigned gpio)
static int au1xxx_gpio2_direction_output(unsigned gpio, int value)
{
gpio -= AU1XXX_GPIO_BASE;
- gpio2->dir = (0x01 << gpio) | (value << gpio);
+ gpio2->dir |= 0x01 << gpio;
+ gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << gpio) | ((!!value) << gpio);
return 0;
}
@@ -90,6 +91,7 @@ static int au1xxx_gpio1_direction_input(unsigned gpio)
static int au1xxx_gpio1_direction_output(unsigned gpio, int value)
{
gpio1->trioutclr = (0x01 & gpio);
+ au1xxx_gpio1_write(gpio, value);
return 0;
}
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 335a6ae3d59..11c92dc5379 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -45,18 +45,7 @@ static void r39xx_wait(void)
local_irq_enable();
}
-/*
- * There is a race when WAIT instruction executed with interrupt
- * enabled.
- * But it is implementation-dependent wheter the pipelie restarts when
- * a non-enabled interrupt is requested.
- */
-static void r4k_wait(void)
-{
- __asm__(" .set mips3 \n"
- " wait \n"
- " .set mips0 \n");
-}
+extern void r4k_wait(void);
/*
* This variant is preferable as it allows testing need_resched and going to
@@ -128,7 +117,7 @@ static int __init wait_disable(char *s)
__setup("nowait", wait_disable);
-static inline void check_wait(void)
+void __init check_wait(void)
{
struct cpuinfo_mips *c = &current_cpu_data;
@@ -242,7 +231,6 @@ static inline void check_errata(void)
void __init check_bugs32(void)
{
- check_wait();
check_errata();
}
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index c6ada98ee04..f886dd7f708 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -20,6 +20,7 @@
#include <asm/stackframe.h>
#include <asm/war.h>
#include <asm/page.h>
+#include <asm/thread_info.h>
#define PANIC_PIC(msg) \
.set push; \
@@ -126,7 +127,42 @@ handle_vcei:
__FINIT
+ .align 5 /* 32 byte rollback region */
+LEAF(r4k_wait)
+ .set push
+ .set noreorder
+ /* start of rollback region */
+ LONG_L t0, TI_FLAGS($28)
+ nop
+ andi t0, _TIF_NEED_RESCHED
+ bnez t0, 1f
+ nop
+ nop
+ nop
+ .set mips3
+ wait
+ /* end of rollback region (the region size must be power of two) */
+ .set pop
+1:
+ jr ra
+ END(r4k_wait)
+
+ .macro BUILD_ROLLBACK_PROLOGUE handler
+ FEXPORT(rollback_\handler)
+ .set push
+ .set noat
+ MFC0 k0, CP0_EPC
+ PTR_LA k1, r4k_wait
+ ori k0, 0x1f /* 32 byte rollback region */
+ xori k0, 0x1f
+ bne k0, k1, 9f
+ MTC0 k0, CP0_EPC
+9:
+ .set pop
+ .endm
+
.align 5
+BUILD_ROLLBACK_PROLOGUE handle_int
NESTED(handle_int, PT_SIZE, sp)
#ifdef CONFIG_TRACE_IRQFLAGS
/*
@@ -201,6 +237,7 @@ NESTED(except_vec_ejtag_debug, 0, sp)
* This prototype is copied to ebase + n*IntCtl.VS and patched
* to invoke the handler
*/
+BUILD_ROLLBACK_PROLOGUE except_vec_vi
NESTED(except_vec_vi, 0, sp)
SAVE_SOME
SAVE_AT
diff --git a/arch/mips/kernel/kgdb.c b/arch/mips/kernel/kgdb.c
index 8f6d58ede33..6e152c80cd4 100644
--- a/arch/mips/kernel/kgdb.c
+++ b/arch/mips/kernel/kgdb.c
@@ -236,8 +236,7 @@ int kgdb_arch_handle_exception(int vector, int signo, int err_code,
atomic_set(&kgdb_cpu_doing_single_step, -1);
if (remcom_in_buffer[0] == 's')
- if (kgdb_contthread)
- atomic_set(&kgdb_cpu_doing_single_step, cpu);
+ atomic_set(&kgdb_cpu_doing_single_step, cpu);
return 0;
}
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index b16facd9ea8..ce7684335a4 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -148,6 +148,8 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
clear_tsk_thread_flag(p, TIF_USEDFPU);
#ifdef CONFIG_MIPS_MT_FPAFF
+ clear_tsk_thread_flag(p, TIF_FPUBOUND);
+
/*
* FPU affinity support is cleaner if we track the
* user-visible CPU affinity from the very beginning.
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 6bee29097a5..5fd0cd020af 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -46,6 +46,9 @@
#include <asm/types.h>
#include <asm/stacktrace.h>
+extern void check_wait(void);
+extern asmlinkage void r4k_wait(void);
+extern asmlinkage void rollback_handle_int(void);
extern asmlinkage void handle_int(void);
extern asmlinkage void handle_tlbm(void);
extern asmlinkage void handle_tlbl(void);
@@ -1251,6 +1254,9 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
extern char except_vec_vi, except_vec_vi_lui;
extern char except_vec_vi_ori, except_vec_vi_end;
+ extern char rollback_except_vec_vi;
+ char *vec_start = (cpu_wait == r4k_wait) ?
+ &rollback_except_vec_vi : &except_vec_vi;
#ifdef CONFIG_MIPS_MT_SMTC
/*
* We need to provide the SMTC vectored interrupt handler
@@ -1258,11 +1264,11 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
* Status.IM bit to be masked before going there.
*/
extern char except_vec_vi_mori;
- const int mori_offset = &except_vec_vi_mori - &except_vec_vi;
+ const int mori_offset = &except_vec_vi_mori - vec_start;
#endif /* CONFIG_MIPS_MT_SMTC */
- const int handler_len = &except_vec_vi_end - &except_vec_vi;
- const int lui_offset = &except_vec_vi_lui - &except_vec_vi;
- const int ori_offset = &except_vec_vi_ori - &except_vec_vi;
+ const int handler_len = &except_vec_vi_end - vec_start;
+ const int lui_offset = &except_vec_vi_lui - vec_start;
+ const int ori_offset = &except_vec_vi_ori - vec_start;
if (handler_len > VECTORSPACING) {
/*
@@ -1272,7 +1278,7 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
panic("VECTORSPACING too small");
}
- memcpy(b, &except_vec_vi, handler_len);
+ memcpy(b, vec_start, handler_len);
#ifdef CONFIG_MIPS_MT_SMTC
BUG_ON(n > 7); /* Vector index %d exceeds SMTC maximum. */
@@ -1554,6 +1560,10 @@ void __init trap_init(void)
extern char except_vec3_generic, except_vec3_r4000;
extern char except_vec4;
unsigned long i;
+ int rollback;
+
+ check_wait();
+ rollback = (cpu_wait == r4k_wait);
#if defined(CONFIG_KGDB)
if (kgdb_early_setup)
@@ -1618,7 +1628,7 @@ void __init trap_init(void)
if (board_be_init)
board_be_init();
- set_except_vector(0, handle_int);
+ set_except_vector(0, rollback ? rollback_handle_int : handle_int);
set_except_vector(1, handle_tlbm);
set_except_vector(2, handle_tlbl);
set_except_vector(3, handle_tlbs);
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index b5470ceb418..afb119f3568 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -36,6 +36,7 @@ SECTIONS
SCHED_TEXT
LOCK_TEXT
KPROBES_TEXT
+ *(.text.*)
*(.fixup)
*(.gnu.warning)
} :text = 0
diff --git a/arch/mips/lib/csum_partial.S b/arch/mips/lib/csum_partial.S
index 8d7784122c1..edac9892c51 100644
--- a/arch/mips/lib/csum_partial.S
+++ b/arch/mips/lib/csum_partial.S
@@ -39,12 +39,14 @@
#ifdef USE_DOUBLE
#define LOAD ld
+#define LOAD32 lwu
#define ADD daddu
#define NBYTES 8
#else
#define LOAD lw
+#define LOAD32 lw
#define ADD addu
#define NBYTES 4
@@ -60,6 +62,14 @@
ADD sum, v1; \
.set pop
+#define ADDC32(sum,reg) \
+ .set push; \
+ .set noat; \
+ addu sum, reg; \
+ sltu v1, sum, reg; \
+ addu sum, v1; \
+ .set pop
+
#define CSUM_BIGCHUNK1(src, offset, sum, _t0, _t1, _t2, _t3) \
LOAD _t0, (offset + UNIT(0))(src); \
LOAD _t1, (offset + UNIT(1))(src); \
@@ -132,7 +142,7 @@ LEAF(csum_partial)
beqz t8, .Lqword_align
andi t8, src, 0x8
- lw t0, 0x00(src)
+ LOAD32 t0, 0x00(src)
LONG_SUBU a1, a1, 0x4
ADDC(sum, t0)
PTR_ADDU src, src, 0x4
@@ -211,7 +221,7 @@ LEAF(csum_partial)
LONG_SRL t8, t8, 0x2
.Lend_words:
- lw t0, (src)
+ LOAD32 t0, (src)
LONG_SUBU t8, t8, 0x1
ADDC(sum, t0)
.set reorder /* DADDI_WAR */
@@ -230,6 +240,9 @@ LEAF(csum_partial)
/* Still a full word to go */
ulw t1, (src)
PTR_ADDIU src, 4
+#ifdef USE_DOUBLE
+ dsll t1, t1, 32 /* clear lower 32bit */
+#endif
ADDC(sum, t1)
1: move t1, zero
@@ -280,7 +293,7 @@ LEAF(csum_partial)
1:
.set reorder
/* Add the passed partial csum. */
- ADDC(sum, a2)
+ ADDC32(sum, a2)
jr ra
.set noreorder
END(csum_partial)
@@ -681,7 +694,7 @@ EXC( sb t0, NBYTES-2(dst), .Ls_exc)
.set pop
1:
.set reorder
- ADDC(sum, psum)
+ ADDC32(sum, psum)
jr ra
.set noreorder
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
index 15e01aec37f..c8c32f417b6 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_SOC_TX3927) += ops-tx3927.o
obj-$(CONFIG_PCI_VR41XX) += ops-vr41xx.o pci-vr41xx.o
obj-$(CONFIG_MARKEINS) += ops-emma2rh.o pci-emma2rh.o fixup-emma2rh.o
obj-$(CONFIG_PCI_TX4927) += ops-tx4927.o
+obj-$(CONFIG_BCM47XX) += pci-bcm47xx.o
#
# These are still pretty much in the old state, watch, go blind.
diff --git a/arch/mips/pci/pci-bcm47xx.c b/arch/mips/pci/pci-bcm47xx.c
new file mode 100644
index 00000000000..bea9b6cdfdb
--- /dev/null
+++ b/arch/mips/pci/pci-bcm47xx.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2008 Aurelien Jarno <aurelien@aurel32.net>
+ *
+ * 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 <linux/types.h>
+#include <linux/pci.h>
+#include <linux/ssb/ssb.h>
+
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+ return 0;
+}
+
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ int res;
+ u8 slot, pin;
+
+ res = ssb_pcibios_plat_dev_init(dev);
+ if (res < 0) {
+ printk(KERN_ALERT "PCI: Failed to init device %s\n",
+ pci_name(dev));
+ return res;
+ }
+
+ pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+ slot = PCI_SLOT(dev->devfn);
+ res = ssb_pcibios_map_irq(dev, slot, pin);
+
+ /* IRQ-0 and IRQ-1 are software interrupts. */
+ if (res < 2) {
+ printk(KERN_ALERT "PCI: Failed to map IRQ of device %s\n",
+ pci_name(dev));
+ return res;
+ }
+
+ dev->irq = res;
+ return 0;
+}
+
diff --git a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c
index bd78368c82b..f97ab146101 100644
--- a/arch/mips/pci/pci-ip27.c
+++ b/arch/mips/pci/pci-ip27.c
@@ -143,25 +143,47 @@ int __cpuinit bridge_probe(nasid_t nasid, int widget_id, int masterwid)
*/
int __devinit pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
+ return 0;
+}
+
+/* Most MIPS systems have straight-forward swizzling needs. */
+static inline u8 bridge_swizzle(u8 pin, u8 slot)
+{
+ return (((pin - 1) + slot) % 4) + 1;
+}
+
+static inline struct pci_dev *bridge_root_dev(struct pci_dev *dev)
+{
+ while (dev->bus->parent) {
+ /* Move up the chain of bridges. */
+ dev = dev->bus->self;
+ }
+
+ return dev;
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus);
- int irq = bc->pci_int[slot];
+ struct pci_dev *rdev = bridge_root_dev(dev);
+ int slot = PCI_SLOT(rdev->devfn);
+ int irq;
+ irq = bc->pci_int[slot];
if (irq == -1) {
- irq = bc->pci_int[slot] = request_bridge_irq(bc);
+ irq = request_bridge_irq(bc);
if (irq < 0)
- panic("Can't allocate interrupt for PCI device %s\n",
- pci_name(dev));
+ return irq;
+
+ bc->pci_int[slot] = irq;
}
irq_to_bridge[irq] = bc;
irq_to_slot[irq] = slot;
- return irq;
-}
+ dev->irq = irq;
-/* Do platform specific device initialization at pci_enable_device() time */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
return 0;
}
diff --git a/arch/mips/sgi-ip22/ip22-platform.c b/arch/mips/sgi-ip22/ip22-platform.c
index 60141235ec4..52486c4d2b0 100644
--- a/arch/mips/sgi-ip22/ip22-platform.c
+++ b/arch/mips/sgi-ip22/ip22-platform.c
@@ -150,7 +150,7 @@ static int __init sgiseeq_devinit(void)
return res;
/* Second HPC is missing? */
- if (!ip22_is_fullhouse() ||
+ if (ip22_is_fullhouse() ||
get_dbe(tmp, (unsigned int *)&hpc3c1->pbdma[1]))
return 0;
diff --git a/arch/mips/vr41xx/common/irq.c b/arch/mips/vr41xx/common/irq.c
index cba36a247e3..92dd1a0ca35 100644
--- a/arch/mips/vr41xx/common/irq.c
+++ b/arch/mips/vr41xx/common/irq.c
@@ -72,6 +72,7 @@ static void irq_dispatch(unsigned int irq)
cascade = irq_cascade + irq;
if (cascade->get_irq != NULL) {
unsigned int source_irq = irq;
+ int ret;
desc = irq_desc + source_irq;
if (desc->chip->mask_ack)
desc->chip->mask_ack(source_irq);
@@ -79,8 +80,9 @@ static void irq_dispatch(unsigned int irq)
desc->chip->mask(source_irq);
desc->chip->ack(source_irq);
}
- irq = cascade->get_irq(irq);
- if (irq < 0)
+ ret = cascade->get_irq(irq);
+ irq = ret;
+ if (ret < 0)
atomic_inc(&irq_err_count);
else
irq_dispatch(irq);