summary refs log tree commit diff
path: root/arch
diff options
context:
space:
mode:
authorJeff Garzik <jeff@garzik.org>2006-03-20 04:38:03 -0500
committerJeff Garzik <jeff@garzik.org>2006-03-20 04:38:03 -0500
commitd378aca6ec708bfb24df5c47801b1f2399efc481 (patch)
tree7535f96bf34314df071698d2e06054b8d5223ebb /arch
parentabc71c46dc0a12ab7fddc18cfe4f4aa26808c79b (diff)
parent7705a8792b0fc82fd7d4dd923724606bbfd9fb20 (diff)
downloadlinux-d378aca6ec708bfb24df5c47801b1f2399efc481.tar.gz
Merge branch 'master'
Diffstat (limited to 'arch')
-rw-r--r--arch/i386/kernel/smpboot.c10
-rw-r--r--arch/mips/Makefile3
-rw-r--r--arch/mips/arc/misc.c19
-rw-r--r--arch/mips/au1000/common/reset.c10
-rw-r--r--arch/mips/kernel/time.c6
-rw-r--r--arch/mips/mm/c-r4k.c13
-rw-r--r--arch/mips/mm/c-tx39.c1
-rw-r--r--arch/mips/sibyte/sb1250/time.c77
-rw-r--r--arch/mips/sibyte/swarm/setup.c7
9 files changed, 97 insertions, 49 deletions
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index eba7f53f8b4a..7007e1783797 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -1029,6 +1029,16 @@ int __devinit smp_prepare_cpu(int cpu)
 	int	apicid, ret;
 
 	lock_cpu_hotplug();
+
+	/*
+	 * On x86, CPU0 is never offlined.  Trying to bring up an
+	 * already-booted CPU will hang.  So check for that case.
+	 */
+	if (cpu_online(cpu)) {
+		ret = -EINVAL;
+		goto exit;
+	}
+
 	apicid = x86_cpu_to_apicid[cpu];
 	if (apicid == BAD_APICID) {
 		ret = -ENODEV;
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index fe9da16f3a40..3d8dac681c63 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -108,7 +108,8 @@ MODFLAGS			+= -mlong-calls
 cflags-$(CONFIG_CPU_BIG_ENDIAN)		+= $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' && echo -EB)
 cflags-$(CONFIG_CPU_LITTLE_ENDIAN)	+= $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' || echo -EL)
 
-cflags-$(CONFIG_SB1XXX_CORELIS)	+= -mno-sched-prolog -fno-omit-frame-pointer
+cflags-$(CONFIG_SB1XXX_CORELIS)	+= $(call cc-option,-mno-sched-prolog) \
+				   -fno-omit-frame-pointer
 
 #
 # Use: $(call set_gccflags,<cpu0>,<isa0>,<cpu1>,<isa1>,<isa2>)
diff --git a/arch/mips/arc/misc.c b/arch/mips/arc/misc.c
index 84867de22028..b2e10b9e9452 100644
--- a/arch/mips/arc/misc.c
+++ b/arch/mips/arc/misc.c
@@ -9,7 +9,6 @@
  * Copyright (C) 1999 Ralf Baechle (ralf@gnu.org)
  * Copyright (C) 1999 Silicon Graphics, Inc.
  */
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 
@@ -20,17 +19,11 @@
 #include <asm/bootinfo.h>
 #include <asm/system.h>
 
-extern void *sgiwd93_host;
-extern void reset_wd33c93(void *instance);
-
 VOID
 ArcHalt(VOID)
 {
 	bc_disable();
 	local_irq_disable();
-#ifdef CONFIG_SCSI_SGIWD93
-	reset_wd33c93(sgiwd93_host);
-#endif
 	ARC_CALL0(halt);
 never:	goto never;
 }
@@ -40,9 +33,6 @@ ArcPowerDown(VOID)
 {
 	bc_disable();
 	local_irq_disable();
-#ifdef CONFIG_SCSI_SGIWD93
-	reset_wd33c93(sgiwd93_host);
-#endif
 	ARC_CALL0(pdown);
 never:	goto never;
 }
@@ -53,9 +43,6 @@ ArcRestart(VOID)
 {
 	bc_disable();
 	local_irq_disable();
-#ifdef CONFIG_SCSI_SGIWD93
-	reset_wd33c93(sgiwd93_host);
-#endif
 	ARC_CALL0(restart);
 never:	goto never;
 }
@@ -65,9 +52,6 @@ ArcReboot(VOID)
 {
 	bc_disable();
 	local_irq_disable();
-#ifdef CONFIG_SCSI_SGIWD93
-	reset_wd33c93(sgiwd93_host);
-#endif
 	ARC_CALL0(reboot);
 never:	goto never;
 }
@@ -77,9 +61,6 @@ ArcEnterInteractiveMode(VOID)
 {
 	bc_disable();
 	local_irq_disable();
-#ifdef CONFIG_SCSI_SGIWD93
-	reset_wd33c93(sgiwd93_host);
-#endif
 	ARC_CALL0(imode);
 never:	goto never;
 }
diff --git a/arch/mips/au1000/common/reset.c b/arch/mips/au1000/common/reset.c
index 4ffccedf5967..c93af224c1b3 100644
--- a/arch/mips/au1000/common/reset.c
+++ b/arch/mips/au1000/common/reset.c
@@ -164,17 +164,20 @@ void au1000_restart(char *command)
 
 void au1000_halt(void)
 {
-#if defined(CONFIG_MIPS_PB1550)
+#if defined(CONFIG_MIPS_PB1550) || defined(CONFIG_MIPS_DB1550)
 	/* power off system */
-	printk("\n** Powering off Pb1550\n");
+	printk("\n** Powering off...\n");
 	au_writew(au_readw(0xAF00001C) | (3<<14), 0xAF00001C);
 	au_sync();
 	while(1); /* should not get here */
-#endif
+#else
 	printk(KERN_NOTICE "\n** You can safely turn off the power\n");
 #ifdef CONFIG_MIPS_MIRAGE
 	au_writel((1 << 26) | (1 << 10), GPIO2_OUTPUT);
 #endif
+#ifdef CONFIG_MIPS_DB1200
+	au_writew(au_readw(0xB980001C) | (1<<14), 0xB980001C);
+#endif
 #ifdef CONFIG_PM
 	au_sleep();
 
@@ -187,6 +190,7 @@ void au1000_halt(void)
 	                "wait\n\t"
 			".set\tmips0");
 #endif
+#endif /* defined(CONFIG_MIPS_PB1550) || defined(CONFIG_MIPS_DB1550) */
 }
 
 void au1000_power_off(void)
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index 42c94c771afb..51273b7297a7 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -424,6 +424,8 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 	unsigned long j;
 	unsigned int count;
 
+	write_seqlock(&xtime_lock);
+
 	count = mips_hpt_read();
 	mips_timer_ack();
 
@@ -441,7 +443,6 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 	 * CMOS clock accordingly every ~11 minutes. rtc_set_time() has to be
 	 * called as close as possible to 500 ms before the new second starts.
 	 */
-	write_seqlock(&xtime_lock);
 	if (ntp_synced() &&
 	    xtime.tv_sec > last_rtc_update + 660 &&
 	    (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
@@ -453,7 +454,6 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 			last_rtc_update = xtime.tv_sec - 600;
 		}
 	}
-	write_sequnlock(&xtime_lock);
 
 	/*
 	 * If jiffies has overflown in this timer_interrupt, we must
@@ -496,6 +496,8 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 		}
 	}
 
+	write_sequnlock(&xtime_lock);
+
 	/*
 	 * In UP mode, we call local_timer_interrupt() to do profiling
 	 * and process accouting.
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index 0668e9bfce41..9572ed44f0d5 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -375,6 +375,7 @@ static void r4k_flush_cache_mm(struct mm_struct *mm)
 struct flush_cache_page_args {
 	struct vm_area_struct *vma;
 	unsigned long addr;
+	unsigned long pfn;
 };
 
 static inline void local_r4k_flush_cache_page(void *args)
@@ -382,6 +383,7 @@ static inline void local_r4k_flush_cache_page(void *args)
 	struct flush_cache_page_args *fcp_args = args;
 	struct vm_area_struct *vma = fcp_args->vma;
 	unsigned long addr = fcp_args->addr;
+	unsigned long paddr = fcp_args->pfn << PAGE_SHIFT;
 	int exec = vma->vm_flags & VM_EXEC;
 	struct mm_struct *mm = vma->vm_mm;
 	pgd_t *pgdp;
@@ -431,11 +433,12 @@ static inline void local_r4k_flush_cache_page(void *args)
 	 * Do indexed flush, too much work to get the (possible) TLB refills
 	 * to work correctly.
 	 */
-	addr = INDEX_BASE + (addr & (dcache_size - 1));
 	if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) {
-		r4k_blast_dcache_page_indexed(addr);
-		if (exec && !cpu_icache_snoops_remote_store)
-			r4k_blast_scache_page_indexed(addr);
+		r4k_blast_dcache_page_indexed(cpu_has_pindexed_dcache ?
+					      paddr : addr);
+		if (exec && !cpu_icache_snoops_remote_store) {
+			r4k_blast_scache_page_indexed(paddr);
+		}
 	}
 	if (exec) {
 		if (cpu_has_vtag_icache) {
@@ -455,6 +458,7 @@ static void r4k_flush_cache_page(struct vm_area_struct *vma,
 
 	args.vma = vma;
 	args.addr = addr;
+	args.pfn = pfn;
 
 	on_each_cpu(local_r4k_flush_cache_page, &args, 1, 1);
 }
@@ -956,6 +960,7 @@ static void __init probe_pcache(void)
 	switch (c->cputype) {
 	case CPU_20KC:
 	case CPU_25KF:
+		c->dcache.flags |= MIPS_CACHE_PINDEX;
 	case CPU_R10000:
 	case CPU_R12000:
 	case CPU_SB1:
diff --git a/arch/mips/mm/c-tx39.c b/arch/mips/mm/c-tx39.c
index 7c572bea4a98..fe232e3988e3 100644
--- a/arch/mips/mm/c-tx39.c
+++ b/arch/mips/mm/c-tx39.c
@@ -210,7 +210,6 @@ static void tx39_flush_cache_page(struct vm_area_struct *vma, unsigned long page
 	 * Do indexed flush, too much work to get the (possible) TLB refills
 	 * to work correctly.
 	 */
-	page = (KSEG0 + (page & (dcache_size - 1)));
 	if (cpu_has_dc_aliases || exec)
 		tx39_blast_dcache_page_indexed(page);
 	if (exec)
diff --git a/arch/mips/sibyte/sb1250/time.c b/arch/mips/sibyte/sb1250/time.c
index 511c89d65f38..1588f6debd90 100644
--- a/arch/mips/sibyte/sb1250/time.c
+++ b/arch/mips/sibyte/sb1250/time.c
@@ -47,23 +47,51 @@
 #define IMR_IP3_VAL	K_INT_MAP_I1
 #define IMR_IP4_VAL	K_INT_MAP_I2
 
+#define SB1250_HPT_NUM		3
+#define SB1250_HPT_VALUE	M_SCD_TIMER_CNT /* max value */
+#define SB1250_HPT_SHIFT	((sizeof(unsigned int)*8)-V_SCD_TIMER_WIDTH)
+
+
 extern int sb1250_steal_irq(int irq);
 
+static unsigned int sb1250_hpt_read(void);
+static void sb1250_hpt_init(unsigned int);
+
+static unsigned int hpt_offset;
+
+void __init sb1250_hpt_setup(void)
+{
+	int cpu = smp_processor_id();
+
+	if (!cpu) {
+		/* Setup hpt using timer #3 but do not enable irq for it */
+		__raw_writeq(0, IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CFG)));
+		__raw_writeq(SB1250_HPT_VALUE,
+			     IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_INIT)));
+		__raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
+			     IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CFG)));
+
+		/*
+		 * we need to fill 32 bits, so just use the upper 23 bits and pretend
+		 * the timer is going 512Mhz instead of 1Mhz
+		 */
+		mips_hpt_frequency = V_SCD_TIMER_FREQ << SB1250_HPT_SHIFT;
+		mips_hpt_init = sb1250_hpt_init;
+		mips_hpt_read = sb1250_hpt_read;
+	}
+}
+
+
 void sb1250_time_init(void)
 {
 	int cpu = smp_processor_id();
 	int irq = K_INT_TIMER_0+cpu;
 
-	/* Only have 4 general purpose timers */
-	if (cpu > 3) {
+	/* Only have 4 general purpose timers, and we use last one as hpt */
+	if (cpu > 2) {
 		BUG();
 	}
 
-	if (!cpu) {
-		/* Use our own gettimeoffset() routine */
-		do_gettimeoffset = sb1250_gettimeoffset;
-	}
-
 	sb1250_mask_irq(cpu, irq);
 
 	/* Map the timer interrupt to ip[4] of this cpu */
@@ -75,10 +103,10 @@ void sb1250_time_init(void)
 	/* Disable the timer and set up the count */
 	__raw_writeq(0, IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
 #ifdef CONFIG_SIMULATION
-	__raw_writeq(50000 / HZ,
+	__raw_writeq((50000 / HZ) - 1,
 		     IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)));
 #else
-	__raw_writeq(1000000 / HZ,
+	__raw_writeq((V_SCD_TIMER_FREQ / HZ) - 1,
 		     IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)));
 #endif
 
@@ -103,7 +131,7 @@ void sb1250_timer_interrupt(struct pt_regs *regs)
 	int cpu = smp_processor_id();
 	int irq = K_INT_TIMER_0 + cpu;
 
-	/* Reset the timer */
+	/* ACK interrupt */
 	____raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
 		       IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
 
@@ -122,15 +150,26 @@ void sb1250_timer_interrupt(struct pt_regs *regs)
 }
 
 /*
- * We use our own do_gettimeoffset() instead of the generic one,
- * because the generic one does not work for SMP case.
- * In addition, since we use general timer 0 for system time,
- * we can get accurate intra-jiffy offset without calibration.
+ * The HPT is free running from SB1250_HPT_VALUE down to 0 then starts over
+ * again. There's no easy way to set to a specific value so store init value
+ * in hpt_offset and subtract each time.
+ *
+ * Note: Timer isn't full 32bits so shift it into the upper part making
+ *       it appear to run at a higher frequency.
  */
-unsigned long sb1250_gettimeoffset(void)
+static unsigned int sb1250_hpt_read(void)
 {
-	unsigned long count =
-		__raw_readq(IOADDR(A_SCD_TIMER_REGISTER(0, R_SCD_TIMER_CNT)));
+	unsigned int count;
 
-	return 1000000/HZ - count;
- }
+	count = G_SCD_TIMER_CNT(__raw_readq(IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CNT))));
+
+	count = (SB1250_HPT_VALUE - count) << SB1250_HPT_SHIFT;
+
+	return count - hpt_offset;
+}
+
+static void sb1250_hpt_init(unsigned int count)
+{
+	hpt_offset = count;
+	return;
+}
diff --git a/arch/mips/sibyte/swarm/setup.c b/arch/mips/sibyte/swarm/setup.c
index b614ca0ddb69..b661d2425a36 100644
--- a/arch/mips/sibyte/swarm/setup.c
+++ b/arch/mips/sibyte/swarm/setup.c
@@ -70,6 +70,12 @@ const char *get_system_type(void)
 	return "SiByte " SIBYTE_BOARD_NAME;
 }
 
+void __init swarm_time_init(void)
+{
+	/* Setup HPT */
+	sb1250_hpt_setup();
+}
+
 void __init swarm_timer_setup(struct irqaction *irq)
 {
         /*
@@ -109,6 +115,7 @@ void __init plat_setup(void)
 
 	panic_timeout = 5;  /* For debug.  */
 
+	board_time_init = swarm_time_init;
 	board_timer_setup = swarm_timer_setup;
 	board_be_handler = swarm_be_handler;