Subject: Origin patches, take 2

From: Ralf Baechle <[email-masked]>
Date: Mon, 18 Nov 2002 14:42:12 +0100

Take two on the Origin patches.  This patch pulls the broken IOC3 patches
which somebody from SGI sneaked to Linus making the IO3 ethernet driver
close to unusable ...

This is a fairly dirty patchkit to revive the port.  I'm posting it here
because these patches are quite quick'n'dirty and various people have
been flooding my mailbox during the past time with requests for Origin
kernels.

The serial console is still seriously missbehaving; fixing that is the
last big to do item before the port is fully usable again.

  Ralf

diff -u -r1.99.2.32 traps.c
--- arch/mips/kernel/traps.c 4 Nov 2002 19:39:56 -0000
+++ arch/mips/kernel/traps.c 18 Nov 2002 11:43:14 -0000
@@ -909,6 +909,12 @@
 
 	cpu_data[cpu].asid_cache = ASID_FIRST_VERSION;
 	set_context(cpu << 23);
+
+	atomic_inc(&init_mm.mm_count);
+	current->active_mm = &init_mm;
+	if (current->mm)
+		BUG();
+	enter_lazy_tlb(&init_mm, current, cpu);
 }
 
 void __init trap_init(void)
diff -u -r1.1.2.3 ip27-console.c
--- arch/mips/sgi-ip27/ip27-console.c 7 Nov 2002 01:47:45 -0000
+++ arch/mips/sgi-ip27/ip27-console.c 18 Nov 2002 11:43:15 -0000
@@ -9,6 +9,7 @@
 #include <linux/console.h>
 #include <linux/kdev_t.h>
 #include <linux/major.h>
+#include <asm/page.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/sn0/hub.h>
 #include <asm/sn/klconfig.h>
@@ -45,11 +46,11 @@
 }
 
 static struct console ip27_prom_console = {
-    .name	= "prom",
-    .write	= ip27prom_console_write,
-    .device	= ip27prom_console_dev,
-    .flags	= CON_PRINTBUFFER,
-    .index	= -1,
+	.name	= "prom",
+	.write	= ip27prom_console_write,
+	.device	= ip27prom_console_dev,
+	.flags	= CON_PRINTBUFFER,
+	.index	= -1,
 };
 
 __init void ip27_setup_console(void)
diff -u -r1.1.2.3 ip27-init.c
--- arch/mips/sgi-ip27/ip27-init.c 28 Sep 2002 22:28:38 -0000
+++ arch/mips/sgi-ip27/ip27-init.c 18 Nov 2002 11:43:16 -0000
@@ -424,6 +424,8 @@
 
 void __init start_secondary(void)
 {
+	extern atomic_t smp_commenced;
+
 	CPUMASK_CLRB(boot_barrier, getcpuid());	/* needs atomicity */
 	per_cpu_init();
 	per_cpu_trap_init();
@@ -435,7 +437,20 @@
 	local_flush_tlb_all();
 	flush_cache_l1();
 	flush_cache_l2();
-	start_secondary();
+
+	smp_callin();
+	while (!atomic_read(&smp_commenced));
+	return cpu_idle();
+}
+
+static int __init fork_by_hand(void)
+{
+	struct pt_regs regs;
+	/*
+	 * don't care about the epc and regs settings since
+	 * we'll never reschedule the forked task.
+	 */
+	return do_fork(CLONE_VM|CLONE_PID, 0, &regs, 0);
 }
 
 __init void allowboot(void)
@@ -457,6 +472,8 @@
 	boot_barrier = boot_cpumask;
 	/* Launch slaves. */
 	for (cpu = 0; cpu < maxcpus; cpu++) {
+		struct task_struct *idle;
+
 		if (cpu == mycpuid) {
 			alloc_cpupda(cpu, num_cpus);
 			num_cpus++;
@@ -466,59 +483,66 @@
 		}
 
 		/* Skip holes in CPU space */
-		if (CPUMASK_TSTB(boot_cpumask, cpu)) {
-			struct task_struct *p;
+		if (!CPUMASK_TSTB(boot_cpumask, cpu))
+			continue;
 
-			/*
-			 * The following code is purely to make sure
-			 * Linux can schedule processes on this slave.
-			 */
-			kernel_thread(0, NULL, CLONE_PID);
-			p = init_task.prev_task;
-			sprintf(p->comm, "%s%d", "Idle", num_cpus);
-			init_tasks[num_cpus] = p;
-			alloc_cpupda(cpu, num_cpus);
-			del_from_runqueue(p);
-			p->processor = num_cpus;
-			p->cpus_runnable = 1 << num_cpus; /* we schedule the first task manually */
-			unhash_process(p);
-			/* Attach to the address space of init_task. */
-			atomic_inc(&init_mm.mm_count);
-			p->active_mm = &init_mm;
-
-			/*
-		 	 * Launch a slave into smp_bootstrap().
-		 	 * It doesn't take an argument, and we
-			 * set sp to the kernel stack of the newly
-			 * created idle process, gp to the proc struct
-			 * (so that current-> works).
-		 	 */
-			LAUNCH_SLAVE(cputonasid(num_cpus),cputoslice(num_cpus),
-				(launch_proc_t)MAPPED_KERN_RW_TO_K0(smp_bootstrap),
-				0, (void *)((unsigned long)p +
-				KERNEL_STACK_SIZE - 32), (void *)p);
-
-			/*
-			 * Now optimistically set the mapping arrays. We
-			 * need to wait here, verify the cpu booted up, then
-			 * fire up the next cpu.
-			 */
-			__cpu_number_map[cpu] = num_cpus;
-			__cpu_logical_map[num_cpus] = cpu;
-			CPUMASK_SETB(cpu_online_map, cpu);
-			num_cpus++;
-			/*
-			 * Wait this cpu to start up and initialize its hub,
-			 * and discover the io devices it will control.
-			 *
-			 * XXX: We really want to fire up launch all the CPUs
-			 * at once.  We have to preserve the order of the
-			 * devices on the bridges first though.
-			 */
-			while(atomic_read(&numstarted) != num_cpus);
-		}
+		/*
+		 * We can't use kernel_thread since we must avoid to
+		 * reschedule the child.
+		 */
+		if (fork_by_hand() < 0)
+			panic("failed fork for CPU %d", num_cpus);
+
+		/*
+		 * We remove it from the pidhash and the runqueue
+		 * once we got the process:
+		 */
+		idle = init_task.prev_task;
+		if (!idle)
+			panic("No idle process for CPU %d", num_cpus);
+
+		idle->processor = num_cpus;
+		idle->cpus_runnable = 1 << cpu; /* we schedule the first task manually */
+
+		alloc_cpupda(cpu, num_cpus);
+
+		idle->thread.reg31 = (unsigned long) start_secondary;
+
+		del_from_runqueue(idle);
+		unhash_process(idle);
+		init_tasks[num_cpus] = idle;
+
+		/*
+	 	 * Launch a slave into smp_bootstrap().
+	 	 * It doesn't take an argument, and we
+		 * set sp to the kernel stack of the newly
+		 * created idle process, gp to the proc struct
+		 * (so that current-> works).
+	 	 */
+		LAUNCH_SLAVE(cputonasid(num_cpus),cputoslice(num_cpus),
+			(launch_proc_t)MAPPED_KERN_RW_TO_K0(smp_bootstrap),
+			0, (void *)((unsigned long)idle +
+			KERNEL_STACK_SIZE - 32), (void *)idle);
+
+		/*
+		 * Now optimistically set the mapping arrays. We
+		 * need to wait here, verify the cpu booted up, then
+		 * fire up the next cpu.
+		 */
+		__cpu_number_map[cpu] = num_cpus;
+		__cpu_logical_map[num_cpus] = cpu;
+		CPUMASK_SETB(cpu_online_map, cpu);
+		num_cpus++;
+		/*
+		 * Wait this cpu to start up and initialize its hub,
+		 * and discover the io devices it will control.
+		 *
+		 * XXX: We really want to fire up launch all the CPUs
+		 * at once.  We have to preserve the order of the
+		 * devices on the bridges first though.
+		 */
+		while(atomic_read(&numstarted) != num_cpus);
 	}
-
 
 #ifdef LATER
 	Wait logic goes here.
diff -u -r1.1.2.3 ip27-rtc.c
--- arch/mips/sgi-ip27/ip27-rtc.c 7 Nov 2002 01:47:45 -0000
+++ arch/mips/sgi-ip27/ip27-rtc.c 18 Nov 2002 11:43:17 -0000
@@ -61,7 +61,6 @@
 #define RTC_TIMER_ON		0x02	/* missed irq timer active	*/
 
 static unsigned char rtc_status;	/* bitmapped status byte.	*/
-static spinlock_t rtc_status_lock = SPIN_LOCK_UNLOCKED;
 static unsigned long rtc_freq;	/* Current periodic IRQ rate	*/
 static struct m48t35_rtc *rtc;
 
@@ -125,10 +124,7 @@
 		if ((yrs -= epoch) > 255)    /* They are unsigned */
 			return -EINVAL;
 
-		save_flags(flags);
-		cli();
 		if (yrs > 169) {
-			restore_flags(flags);
 			return -EINVAL;
 		}
 		if (yrs >= 100)
@@ -141,6 +137,7 @@
 		BIN_TO_BCD(mon);
 		BIN_TO_BCD(yrs);
 
+		spin_lock_irq(&rtc_lock);
 		rtc->control &= ~M48T35_RTC_SET;
 		rtc->year = yrs;
 		rtc->month = mon;
@@ -149,8 +146,8 @@
 		rtc->min = min;
 		rtc->sec = sec;
 		rtc->control &= ~M48T35_RTC_SET;
+		spin_unlock_irq(&rtc_lock);
 
-		restore_flags(flags);
 		return 0;
 	}
 	default:
@@ -167,15 +164,15 @@
 
 static int rtc_open(struct inode *inode, struct file *file)
 {
-	spin_lock(rtc_status_lock);
+	spin_lock_irq(rtc_lock);
 
 	if (rtc_status & RTC_IS_OPEN) {
-		spin_unlock(rtc_status_lock);
+		spin_unlock_irq(rtc_status_lock);
 		return -EBUSY;
 	}
 
 	rtc_status |= RTC_IS_OPEN;
-	spin_unlock(rtc_status_lock);
+	spin_unlock_irq(rtc_lock);
 
 	return 0;
 }
@@ -187,9 +184,9 @@
 	 * in use, and clear the data.
 	 */
 
-	spin_lock(rtc_status_lock);
+	spin_lock_irq(rtc_lock);
 	rtc_status &= ~RTC_IS_OPEN;
-	spin_unlock(rtc_status_lock);
+	spin_unlock_irq(rtc_lock);
 
 	return 0;
 }
@@ -226,9 +223,6 @@
 		return -ENODEV;
 	create_proc_read_entry ("rtc", 0, NULL, rtc_read_proc, NULL);
 
-	save_flags(flags);
-	cli();
-	restore_flags(flags);
 	rtc_freq = 1024;
 	return 0;
 }
@@ -304,8 +298,7 @@
 	 * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated
 	 * by the RTC when initially set to a non-zero value.
 	 */
-	save_flags(flags);
-	cli();
+	spin_lock_irq(&rtc_lock);
         rtc->control |= M48T35_RTC_READ;
 	rtc_tm->tm_sec = rtc->sec;
 	rtc_tm->tm_min = rtc->min;
@@ -314,7 +307,7 @@
 	rtc_tm->tm_mon = rtc->month;
 	rtc_tm->tm_year = rtc->year;
 	rtc->control &= ~M48T35_RTC_READ;
-	restore_flags(flags);
+	spin_unlock_irq(&rtc_lock);
 
 	BCD_TO_BIN(rtc_tm->tm_sec);
 	BCD_TO_BIN(rtc_tm->tm_min);
diff -u -r1.1.2.3 ip27-setup.c
--- arch/mips/sgi-ip27/ip27-setup.c 21 Sep 2002 21:15:23 -0000
+++ arch/mips/sgi-ip27/ip27-setup.c 18 Nov 2002 11:43:17 -0000
@@ -311,6 +311,6 @@
 	ioc3_eth_init();
 	per_cpu_init();
 
-	mips_io_port_base = IO_BASE;
+	set_io_port_base(IO_BASE);
 	board_time_init = ip27_time_init;
 }
diff -u -r1.1.2.2 ip27-timer.c
--- arch/mips/sgi-ip27/ip27-timer.c 5 Aug 2002 23:53:35 -0000
+++ arch/mips/sgi-ip27/ip27-timer.c 18 Nov 2002 11:43:21 -0000
@@ -1,5 +1,5 @@
 /*
- * Copytight (C) 1999, 2000 Ralf Baechle ([email-masked])
+ * Copytight (C) 1999, 2000, 2002 Ralf Baechle ([email-masked])
  * Copytight (C) 1999, 2000 Silicon Graphics, Inc.
  */
 #include <linux/config.h>
@@ -55,6 +55,7 @@
 	rtc = (struct m48t35_rtc *)(KL_CONFIG_CH_CONS_INFO(nid)->memory_base +
 							IOC3_BYTEBUS_DEV0);
 
+	spin_lock(&rtc_lock);
 	rtc->control |= M48T35_RTC_READ;
 	cmos_minutes = rtc->min;
 	BCD_TO_BIN(cmos_minutes);
@@ -84,15 +85,18 @@
 		       cmos_minutes, real_minutes);
 		retval = -1;
 	}
+	spin_unlock(&rtc_lock);
 
 	return retval;
 }
 
+#define IP27_TIMER_IRQ	9			/* XXX Assign number */
+
 void rt_timer_interrupt(struct pt_regs *regs)
 {
 	int cpu = smp_processor_id();
 	int cpuA = ((cputoslice(cpu)) == 0);
-	int irq = 9;				/* XXX Assign number */
+	int irq = IP27_TIMER_IRQ;
 
 	irq_enter(cpu, irq);
 	write_lock(&xtime_lock);
@@ -157,7 +161,7 @@
 
 static __init unsigned long get_m48t35_time(void)
 {
-        unsigned int year, month, date, hour, min, sec;
+	unsigned int year, month, date, hour, min, sec;
 	struct m48t35_rtc *rtc;
 	nasid_t nid;
 
@@ -165,6 +169,7 @@
 	rtc = (struct m48t35_rtc *)(KL_CONFIG_CH_CONS_INFO(nid)->memory_base +
 							IOC3_BYTEBUS_DEV0);
 
+	spin_lock(&rtc_lock);
 	rtc->control |= M48T35_RTC_READ;
 	sec = rtc->sec;
 	min = rtc->min;
@@ -173,17 +178,27 @@
 	month = rtc->month;
 	year = rtc->year;
 	rtc->control &= ~M48T35_RTC_READ;
+	spin_unlock(&rtc_lock);
+
+	BCD_TO_BIN(sec);
+	BCD_TO_BIN(min);
+	BCD_TO_BIN(hour);
+	BCD_TO_BIN(date);
+	BCD_TO_BIN(month);
+	BCD_TO_BIN(year);
+
+	year += 1970;
 
-        BCD_TO_BIN(sec);
-        BCD_TO_BIN(min);
-        BCD_TO_BIN(hour);
-        BCD_TO_BIN(date);
-        BCD_TO_BIN(month);
-        BCD_TO_BIN(year);
+	return mktime(year, month, date, hour, min, sec);
+}
 
-        year += 1970;
+static void ip27_timer_setup(struct irqaction *irq)
+{
+	/* over-write the handler, we use our own way */
+	irq->handler = no_action;
 
-        return mktime(year, month, date, hour, min, sec);
+	/* setup irqaction */
+//	setup_irq(IP27_TIMER_IRQ, irq);		/* XXX Can't do this yet.  */
 }
 
 void __init ip27_time_init(void)
@@ -192,6 +207,9 @@
 	xtime.tv_usec = 0;
 
 	do_gettimeoffset = ip27_do_gettimeoffset;
+
+	// board_time_init = ip27_time_init;
+	board_timer_setup = ip27_timer_setup;
 }
 
 void __init cpu_time_init(void)
diff -u -r1.2.2.5 smp.c
--- arch/mips/sibyte/sb1250/smp.c 28 Sep 2002 22:28:38 -0000
+++ arch/mips/sibyte/sb1250/smp.c 18 Nov 2002 11:43:21 -0000
@@ -129,9 +129,6 @@
 		p->processor = i;
 		p->cpus_runnable = 1 << i; /* we schedule the first task manually */
 
-		/* Attach to the address space of init_task. */
-		atomic_inc(&init_mm.mm_count);
-		p->active_mm = &init_mm;
 		init_tasks[i] = p;
 
 		del_from_runqueue(p);
diff -u -r1.22.2.19 Makefile
--- arch/mips64/Makefile 12 Nov 2002 02:14:50 -0000
+++ arch/mips64/Makefile 18 Nov 2002 11:43:21 -0000
@@ -215,7 +215,7 @@
 # ELF files from 32-bit files by conversion.
 #
 ifdef CONFIG_BOOT_ELF64
-GCCFLAGS += -Wa,-32 $(shell if $(CC) $(1) -c -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi)
+GCCFLAGS += -Wa,-32 $(shell if $(CC) -Wa,-mgp64 -c -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "-Wa,-mgp64"; fi)
 LINKFLAGS += -T arch/mips64/ld.script.elf32
 #AS += -64
 #LD += -m elf64bmip
@@ -238,9 +238,9 @@
 MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
 
 ifdef CONFIG_CPU_LITTLE_ENDIAN
-64bit-bfd = elf64-littlemips
+64bit-bfd = elf64-tradlittlemips
 else
-64bit-bfd = elf64-bigmips
+64bit-bfd = elf64-tradbigmips
 endif
 
 vmlinux: arch/mips64/ld.script.elf32
@@ -249,10 +249,10 @@
 
 ifdef CONFIG_MAPPED_KERNEL
 vmlinux.64: vmlinux
-	$(OBJCOPY) -O $(64bit-bfd) --change-addresses=0xbfffffff40000000 $< $@
+	$(OBJCOPY) -O $(64bit-bfd) --remove-section=.reginfo --change-addresses=0xbfffffff40000000 $< $@
 else
 vmlinux.64: vmlinux
-	$(OBJCOPY) -O $(64bit-bfd) --change-addresses=0xa7ffffff80000000 $< $@
+	$(OBJCOPY) -O $(64bit-bfd) --remove-section=.reginfo --change-addresses=0xa800000080000000 $< $@
 endif
 
 zImage: vmlinux
diff -u -r1.73.2.22 defconfig
--- arch/mips64/defconfig 8 Nov 2002 01:39:44 -0000
+++ arch/mips64/defconfig 18 Nov 2002 11:43:21 -0000
@@ -49,8 +49,8 @@
 # CONFIG_SGI_IP22 is not set
 CONFIG_SGI_IP27=y
 # CONFIG_SGI_SN0_N_MODE is not set
-CONFIG_DISCONTIGMEM=y
-CONFIG_NUMA=y
+# CONFIG_DISCONTIGMEM is not set
+# CONFIG_NUMA is not set
 # CONFIG_MAPPED_KERNEL is not set
 # CONFIG_REPLICATE_KTEXT is not set
 # CONFIG_REPLICATE_EXHANDLERS is not set
@@ -473,8 +473,8 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BEFS_DEBUG is not set
 # CONFIG_BFS_FS is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
+CONFIG_EXT3_FS=y
+CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 # CONFIG_FAT_FS is not set
 # CONFIG_MSDOS_FS is not set
diff -u -r1.67.2.22 defconfig-ip27
--- arch/mips64/defconfig-ip27 8 Nov 2002 01:39:44 -0000
+++ arch/mips64/defconfig-ip27 18 Nov 2002 11:43:21 -0000
@@ -49,8 +49,8 @@
 # CONFIG_SGI_IP22 is not set
 CONFIG_SGI_IP27=y
 # CONFIG_SGI_SN0_N_MODE is not set
-CONFIG_DISCONTIGMEM=y
-CONFIG_NUMA=y
+# CONFIG_DISCONTIGMEM is not set
+# CONFIG_NUMA is not set
 # CONFIG_MAPPED_KERNEL is not set
 # CONFIG_REPLICATE_KTEXT is not set
 # CONFIG_REPLICATE_EXHANDLERS is not set
@@ -473,8 +473,8 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BEFS_DEBUG is not set
 # CONFIG_BFS_FS is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
+CONFIG_EXT3_FS=y
+CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 # CONFIG_FAT_FS is not set
 # CONFIG_MSDOS_FS is not set
diff -u -r1.11.2.12 Makefile
--- arch/mips64/kernel/Makefile 7 Nov 2002 18:01:32 -0000
+++ arch/mips64/kernel/Makefile 18 Nov 2002 11:43:21 -0000
@@ -12,7 +12,7 @@
 
 O_TARGET := kernel.o
 
-export-objs	= irq.o mips64_ksyms.o pci-dma.o setup.o smp.o
+export-objs	= irq.o mips64_ksyms.o pci-dma.o setup.o smp.o time.o
 
 obj-y		:= branch.o cpu-probe.o entry.o irq.o proc.o process.o \
 		   ptrace.o r4k_cache.o r4k_fpu.o r4k_genex.o r4k_switch.o \
diff -u -r1.31.2.21 setup.c
--- arch/mips64/kernel/setup.c 25 Oct 2002 23:01:17 -0000
+++ arch/mips64/kernel/setup.c 18 Nov 2002 11:43:21 -0000
@@ -278,6 +278,7 @@
 	start_pfn = PFN_UP(CPHYSADDR(&_end));
 #endif	/* CONFIG_BLK_DEV_INITRD */
 
+#ifndef CONFIG_SGI_IP27
 	/* Find the highest page frame number we have available.  */
 	max_pfn = 0;
 	for (i = 0; i < boot_mem_map.nr_map; i++) {
@@ -342,6 +343,7 @@
 
 	/* Reserve the bootmap memory.  */
 	reserve_bootmem(PFN_PHYS(start_pfn), bootmap_size);
+#endif
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	/* Board specific code should have set up initrd_start and initrd_end */
diff -u -r1.1.2.6 time.c
--- arch/mips64/kernel/time.c 31 Oct 2002 19:50:14 -0000
+++ arch/mips64/kernel/time.c 18 Nov 2002 11:43:28 -0000
@@ -21,6 +21,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
+#include <linux/module.h>
 
 #include <asm/bootinfo.h>
 #include <asm/cpu.h>
@@ -38,6 +39,8 @@
 extern rwlock_t xtime_lock;
 extern volatile unsigned long wall_jiffies;
 
+spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
+
 /*
  * whether we emulate local_timer_interrupts for SMP machines.
  */
@@ -580,3 +583,5 @@
 	 */
 	tm->tm_wday = (gday + 4) % 7; /* 1970/1/1 was Thursday */
 }
+
+EXPORT_SYMBOL(rtc_lock);
diff -u -r1.30.2.35 traps.c
--- arch/mips64/kernel/traps.c 4 Nov 2002 19:39:56 -0000
+++ arch/mips64/kernel/traps.c 18 Nov 2002 11:43:28 -0000
@@ -686,6 +686,12 @@
 	cpu_data[cpu].asid_cache = ASID_FIRST_VERSION;
 	set_context(((long)(&pgd_current[cpu])) << 23);
 	set_wired(0);
+
+	atomic_inc(&init_mm.mm_count);
+	current->active_mm = &init_mm;
+	if (current->mm)
+		BUG();
+	enter_lazy_tlb(&init_mm, current, cpu);
 }
 
 void __init trap_init(void)
diff -u -r1.56.2.6 ioc3-eth.c
--- drivers/net/ioc3-eth.c 7 Nov 2002 01:47:46 -0000
+++ drivers/net/ioc3-eth.c 18 Nov 2002 11:43:39 -0000
@@ -26,7 +26,6 @@
  *    which workarounds are required for them?  Do we ever have Lucent's?
  *  o For the 2.5 branch kill the mii-tool ioctls.
  */
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/kernel.h>
@@ -34,7 +33,6 @@
 #include <linux/errno.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/crc32.h>
 
 #ifdef CONFIG_SERIAL
 #include <linux/serial.h>
@@ -342,15 +340,14 @@
 }
 
 /*
- * Read the NIC (Number-In-a-Can) device used to store the MAC address on
- * SN0 / SN00 nodeboards and PCI cards.
+ * Read the NIC (Number-In-a-Can) device.
  */
-static void ioc3_get_eaddr_nic(struct ioc3_private *ip)
+static void ioc3_get_eaddr(struct ioc3_private *ip)
 {
 	struct ioc3 *ioc3 = ip->regs;
 	u8 nic[14];
-	int tries = 2; /* There may be some problem with the battery?  */
 	int i;
+	int tries = 2; /* There may be some problem with the battery?  */
 
 	ioc3_w(gpcr_s, (1 << 21));
 
@@ -373,123 +370,16 @@
 	for (i = 13; i >= 0; i--)
 		nic[i] = nic_read_byte(ioc3);
 
-	for (i = 2; i < 8; i++)
-		ip->dev->dev_addr[i - 2] = nic[i];
-}
-
-#if defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_SGI_SN2)
-/*
- * Get the ether-address on SN1 nodes
- */
-static void ioc3_get_eaddr_sn(struct ioc3_private *ip)
-{
-	int ibrick_mac_addr_get(nasid_t, char *);
-	struct ioc3 *ioc3 = ip->regs;
-	nasid_t nasid_of_ioc3;
-	char io7eaddr[20];
-	long mac;
-	int err_val;
-
-	/*
-	 * err_val = ibrick_mac_addr_get(get_nasid(), io7eaddr );
-	 * 
-	 * BAD!!  The above call uses get_nasid() and assumes that
-	 * the ioc3 pointed to by struct ioc3 is hooked up to the
-	 * cbrick that we're running on.  The proper way to make this call
-	 * is to figure out which nasid the ioc3 is connected to
-	 * and use that to call ibrick_mac_addr_get.  Below is
-	 * a hack to do just that.
-	 */
-
-	/*
-	 * Get the nasid of the ioc3 from the ioc3's base addr.
-	 * FIXME: the 8 at the end assumes we're in memory mode, 
-	 * not node mode (for that, we'd change it to a 9).
-	 * Is there a call to extract this info from a physical
-	 * addr somewhere in an sn header file already?  If so,
-	 * we should probably use that, or restructure this routine
-	 * to use pci_dev and generic numa nodeid getting stuff.
-	 */
-	nasid_of_ioc3 = (((unsigned long)ioc3 >> 33) & ~(-1 << 8));
-	err_val = ibrick_mac_addr_get(nasid_of_ioc3, io7eaddr );
-
-
-	if (err_val) {
-		/* Couldn't read the eeprom; try OSLoadOptions. */
-		printk("WARNING: ibrick_mac_addr_get failed: %d\n", err_val);
-
-		/* this is where we hardwire the mac address
- 		 * 1st ibrick had 08:00:69:11:34:75
- 		 * 2nd ibrick had 08:00:69:11:35:35
- 		 *
- 		 * Eagan Machines:
- 		 *      mankato1 08:00:69:11:BE:95
- 		 *      warroad  08:00:69:11:bd:60
- 		 *      duron    08:00:69:11:34:60
- 		 *
- 		 * an easy way to get the mac address is to hook
- 		 * up an ip35, then from L1 do 'cti serial'
- 		 * and then look for MAC line XXX THIS DOESN"T QUITE WORK!!
- 		 */
-		printk("ioc3_get_eaddr: setting ethernet address to:\n -----> ");
-		ip->dev->dev_addr[0] = 0x8;
-		ip->dev->dev_addr[1] = 0x0;
-		ip->dev->dev_addr[2] = 0x69;
-		ip->dev->dev_addr[3] = 0x11;
-		ip->dev->dev_addr[4] = 0x34;
-		ip->dev->dev_addr[5] = 0x60;
-	}
-	else {
-		long simple_strtol(const char *,char **,unsigned int);
-
-		mac = simple_strtol(io7eaddr, (char **)0, 16);
-		ip->dev->dev_addr[0] = (mac >> 40) & 0xff;
-		ip->dev->dev_addr[1] = (mac >> 32) & 0xff;
-		ip->dev->dev_addr[2] = (mac >> 24) & 0xff;
-		ip->dev->dev_addr[3] = (mac >> 16) & 0xff;
-		ip->dev->dev_addr[4] = (mac >> 8) & 0xff;
-		ip->dev->dev_addr[5] = mac & 0xff;
-	}
-}
-#endif
-
-/*
- * Ok, this is hosed by design.  It's necessary to know what machine the
- * NIC is in in order to know how to read the NIC address.  We also have
- * to know if it's a PCI card or a NIC in on the node board ...
- */
-static void ioc3_get_eaddr(struct ioc3_private *ip)
-{
-	void (*do_get_eaddr)(struct ioc3_private *ip) = NULL;
-	int i;
-
-	/*
-	 * We should also use this code for PCI cards, no matter what host
-	 * machine but how to know that we're a PCI card?
-	 */
-#ifdef CONFIG_SGI_IP27
-	do_get_eaddr = ioc3_get_eaddr_nic;
-#endif
-#if defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_SGI_SN2)
-	do_get_eaddr = ioc3_get_eaddr_sn;
-#endif
-
-	if (!do_get_eaddr) {
-		printk(KERN_ERR "Don't know how to read MAC address of this "
-		       "IOC3 NIC\n");
-		return;
-	}
-
 	printk("Ethernet address is ");
-	for (i = 0; i < 6; i++) {
-		printk("%02x", ip->dev->dev_addr[i]);
+	for (i = 2; i < 8; i++) {
+		ip->dev->dev_addr[i - 2] = nic[i];
+		printk("%02x", nic[i]);
 		if (i < 7)
 			printk(":");
 	}
 	printk(".\n");
 }
 
-
 /*
  * Caller must hold the ioc3_lock ever for MII readers.  This is also
  * used to protect the transmitter side but it's low contention.
@@ -544,10 +434,10 @@
 
 	skb = ip->rx_skbs[rx_entry];
 	rxb = (struct ioc3_erxbuf *) (skb->data - RX_OFFSET);
-	w0 = be32_to_cpu(rxb->w0);
+	w0 = rxb->w0;
 
 	while (w0 & ERXBUF_V) {
-		err = be32_to_cpu(rxb->err);		/* It's valid ...  */
+		err = rxb->err;				/* It's valid ...  */
 		if (err & ERXBUF_GOODPKT) {
 			len = ((w0 >> ERXBUF_BYTECNT_SHIFT) & 0x7ff) - 4;
 			skb_trim(skb, len);
@@ -588,8 +478,8 @@
 			ip->stats.rx_frame_errors++;
 next:
 		ip->rx_skbs[n_entry] = new_skb;
-		rxr[n_entry] = cpu_to_be32((0xa5UL << 56) |
-		                         ((unsigned long) rxb & TO_PHYS_MASK));
+		rxr[n_entry] = (0xa5UL << 56) |
+		                ((unsigned long) rxb & TO_PHYS_MASK);
 		rxb->w0 = 0;				/* Clear valid flag */
 		n_entry = (n_entry + 1) & 511;		/* Update erpir */
 
@@ -597,7 +487,7 @@
 		rx_entry = (rx_entry + 1) & 511;
 		skb = ip->rx_skbs[rx_entry];
 		rxb = (struct ioc3_erxbuf *) (skb->data - RX_OFFSET);
-		w0 = be32_to_cpu(rxb->w0);
+		w0 = rxb->w0;
 	}
 	ioc3->erpir = (n_entry << 3) | ERPIR_ARM;
 	ip->rx_pi = n_entry;
@@ -1299,8 +1189,8 @@
 			/* Because we reserve afterwards. */
 			skb_put(skb, (1664 + RX_OFFSET));
 			rxb = (struct ioc3_erxbuf *) skb->data;
-			rxr[i] = cpu_to_be64((0xa5UL << 56) |
-			                ((unsigned long) rxb & TO_PHYS_MASK));
+			rxr[i] = (0xa5UL << 56)
+				| ((unsigned long) rxb & TO_PHYS_MASK);
 			skb_reserve(skb, RX_OFFSET);
 		}
 		ip->rx_ci = 0;
@@ -1622,10 +1512,10 @@
 MODULE_DEVICE_TABLE(pci, ioc3_pci_tbl);
 
 static struct pci_driver ioc3_driver = {
-	.name		= "ioc3-eth",
-	.id_table	= ioc3_pci_tbl,
-	.probe		= ioc3_probe,
-	.remove		= __devexit_p(ioc3_remove_one),
+	name:		"ioc3-eth",
+	id_table:	ioc3_pci_tbl,
+	probe:		ioc3_probe,
+	remove:		__devexit_p(ioc3_remove_one),
 };
 
 static int __init ioc3_init_module(void)
@@ -1664,8 +1554,8 @@
 			memset(desc->data + len, 0, ETH_ZLEN - len);
 			len = ETH_ZLEN;
 		}
-		desc->cmd    = cpu_to_be32(len | ETXD_INTWHENDONE | ETXD_D0V);
-		desc->bufcnt = cpu_to_be32(len);
+		desc->cmd    = len | ETXD_INTWHENDONE | ETXD_D0V;
+		desc->bufcnt = len;
 	} else if ((data ^ (data + len)) & 0x4000) {
 		unsigned long b2, s1, s2;
 
@@ -1673,20 +1563,16 @@
 		s1 = b2 - data;
 		s2 = data + len - b2;
 
-		desc->cmd    = cpu_to_be32(len | ETXD_INTWHENDONE |
-		                           ETXD_B1V | ETXD_B2V);
-		desc->bufcnt = cpu_to_be32((s1 << ETXD_B1CNT_SHIFT)
-		                           | (s2 << ETXD_B2CNT_SHIFT));
-		desc->p1     = cpu_to_be64((0xa5UL << 56) |
-                                           (data & TO_PHYS_MASK));
-		desc->p2     = cpu_to_be64((0xa5UL << 56) |
-		                           (data & TO_PHYS_MASK));
+		desc->cmd    = len | ETXD_INTWHENDONE | ETXD_B1V | ETXD_B2V;
+		desc->bufcnt = (s1 << ETXD_B1CNT_SHIFT) |
+		               (s2 << ETXD_B2CNT_SHIFT);
+		desc->p1     = (0xa5UL << 56) | (data & TO_PHYS_MASK);
+		desc->p2     = (0xa5UL << 56) | (data & TO_PHYS_MASK);
 	} else {
 		/* Normal sized packet that doesn't cross a page boundary. */
-		desc->cmd    = cpu_to_be32(len | ETXD_INTWHENDONE | ETXD_B1V);
-		desc->bufcnt = cpu_to_be32(len << ETXD_B1CNT_SHIFT);
-		desc->p1     = cpu_to_be64((0xa5UL << 56) |
-		                           (data & TO_PHYS_MASK));
+		desc->cmd    = len | ETXD_INTWHENDONE | ETXD_B1V;
+		desc->bufcnt = len << ETXD_B1CNT_SHIFT;
+		desc->p1     = (0xa5UL << 56) | (data & TO_PHYS_MASK);
 	}
 
 	BARRIER();
@@ -1725,16 +1611,27 @@
  * Given a multicast ethernet address, this routine calculates the
  * address's bit index in the logical address filter mask
  */
+#define CRC_MASK        0xedb88320
 
 static inline unsigned int
 ioc3_hash(const unsigned char *addr)
 {
 	unsigned int temp = 0;
 	unsigned char byte;
-	u32 crc;
-	int bits;
+	unsigned int crc;
+	int bits, len;
 
-	crc = ether_crc_le(ETH_ALEN, addr);
+	len = ETH_ALEN;
+	for (crc = ~0; --len >= 0; addr++) {
+		byte = *addr;
+		for (bits = 8; --bits >= 0; ) {
+			if ((byte ^ crc) & 1)
+				crc = (crc >> 1) ^ CRC_MASK;
+			else
+				crc >>= 1;
+			byte >>= 1;
+		}
+	}
 
 	crc &= 0x3f;    /* bit reverse lowest 6 bits for hash index */
 	for (bits = 6; --bits >= 0; ) {
@@ -1920,7 +1817,6 @@
 
 MODULE_AUTHOR("Ralf Baechle <[email-masked]>");
 MODULE_DESCRIPTION("SGI IOC3 Ethernet driver");
-MODULE_LICENSE("GPL");
 
 module_init(ioc3_init_module);
 module_exit(ioc3_cleanup_module);
diff -u -r1.25.2.14 io.h
--- include/asm-mips64/io.h 28 Sep 2002 22:28:38 -0000
+++ include/asm-mips64/io.h 18 Nov 2002 11:44:01 -0000
@@ -330,7 +330,7 @@
 
 #define outw(val,port)							\
 do {									\
-	*(volatile u16 *)(mips_io_port_base + (port)) = __ioswab16(val);\
+	*(volatile u16 *)(mips_io_port_base + (port ^ 2)) = __ioswab16(val);\
 } while(0)
 
 #define outl(val,port)							\
@@ -346,7 +346,7 @@
 
 #define outw_p(val,port)						\
 do {									\
-	*(volatile u16 *)(mips_io_port_base + (port)) = __ioswab16(val);\
+	*(volatile u16 *)(mips_io_port_base + (port ^ 2)) = __ioswab16(val);\
 	SLOW_DOWN_IO;							\
 } while(0)
 
@@ -363,7 +363,7 @@
 
 static inline unsigned short inw(unsigned long port)
 {
-	return __ioswab16(*(volatile u16 *)(mips_io_port_base + port));
+	return __ioswab16(*(volatile u16 *)(mips_io_port_base + (port ^ 2)));
 }
 
 static inline unsigned int inl(unsigned long port)
@@ -385,7 +385,7 @@
 {
 	u16 __val;
 
-	__val = *(volatile u16 *)(mips_io_port_base + port);
+	__val = *(volatile u16 *)(mips_io_port_base + (port ^ 2));
 	SLOW_DOWN_IO;
 
 	return __ioswab16(__val);
diff -u -r1.1 m48t35.h
--- include/asm-mips64/m48t35.h 18 Feb 2000 09:54:39 -0000
+++ include/asm-mips64/m48t35.h 18 Nov 2002 11:44:01 -0000
@@ -1,32 +1,30 @@
 /*
  *  Registers for the SGS-Thomson M48T35 Timekeeper RAM chip
  */
-
 #ifndef _ASM_M48T35_H
 #define _ASM_M48T35_H
 
+#include <linux/spinlock.h>
+
+extern spinlock_t rtc_lock;
+
 struct m48t35_rtc {
-        volatile u8         pad[0x7ff8];    /* starts at 0x7ff8 */
-        volatile u8         control;
-        volatile u8         sec;
-        volatile u8         min;
-        volatile u8         hour;
-        volatile u8         day;
-        volatile u8         date;
-        volatile u8         month;
-        volatile u8         year;
+	volatile u8	pad[0x7ff8];    /* starts at 0x7ff8 */
+	volatile u8	control;
+	volatile u8	sec;
+	volatile u8	min;
+	volatile u8	hour;
+	volatile u8	day;
+	volatile u8	date;
+	volatile u8	month;
+	volatile u8	year;
 };
 
-#define M48T35_RTC_SET      0x80
-#define M48T35_RTC_STOPPED  0x80
-#define M48T35_RTC_READ     0x40
-
-#ifndef BCD_TO_BIN
-#define BCD_TO_BIN(x)   ((x)=((x)&15) + ((x)>>4)*10)
-#endif
-
-#ifndef BIN_TO_BCD
-#define BIN_TO_BCD(x)   ((x)=(((x)/10)<<4) + (x)%10)
-#endif
+#define M48T35_RTC_SET		0x80
+#define M48T35_RTC_STOPPED	0x80
+#define M48T35_RTC_READ		0x40
+
+#define BCD_TO_BIN(x)		((x)=((x)&15) + ((x)>>4)*10)
+#define BIN_TO_BCD(x)		((x)=(((x)/10)<<4) + (x)%10)
 
-#endif
+#endif /* _ASM_M48T35_H */
diff -u -r1.10.2.14 page.h
--- include/asm-mips64/page.h 30 Sep 2002 17:00:03 -0000
+++ include/asm-mips64/page.h 18 Nov 2002 11:44:02 -0000
@@ -115,7 +115,7 @@
 #endif
 #if defined(CONFIG_SGI_IP27)
 #define PAGE_OFFSET	0xa800000000000000UL
-#define UNCAC_BASE	0x9000000000000000UL
+#define UNCAC_BASE	0x9600000000000000UL
 #endif
 #if defined(CONFIG_SIBYTE_SB1250)
 #define PAGE_OFFSET	0xa800000000000000UL
diff -u -r1.2.2.1 addrs.h
--- include/asm-mips64/sn/sn0/addrs.h 27 Jun 2002 14:21:24 -0000
+++ include/asm-mips64/sn/sn0/addrs.h 18 Nov 2002 11:44:06 -0000
@@ -45,11 +45,11 @@
 #define HSPEC_BASE		0x9000000000000000
 #define IO_BASE			0x9200000000000000
 #define MSPEC_BASE		0x9400000000000000
-#define UNCAC_BASE		0x9600000000000000
+#define __UNCAC_BASE		0x9600000000000000
 
 #define TO_PHYS(x)		(	      ((x) & TO_PHYS_MASK))
 #define TO_CAC(x)		(CAC_BASE   | ((x) & TO_PHYS_MASK))
-#define TO_UNCAC(x)		(UNCAC_BASE | ((x) & TO_PHYS_MASK))
+#define TO_UNCAC(x)		(__UNCAC_BASE | ((x) & TO_PHYS_MASK))
 #define TO_MSPEC(x)		(MSPEC_BASE | ((x) & TO_PHYS_MASK))
 #define TO_HSPEC(x)		(HSPEC_BASE | ((x) & TO_PHYS_MASK))

---

From: "??" <[email-masked]>
Date: Tue, 19 Nov 2002 20:09:07 +0800

dear all,

anyone successfully using usb hotplug function with linux mips kernel?

http://marc.theaimsgroup.com/?l=linux-hotplug-devel&m=102954820511328&w=2

best regards,

---

From: Ralf Baechle <[email-masked]>
Date: Tue, 19 Nov 2002 13:29:22 +0100

Hello double questionmark ;-)

> http://marc.theaimsgroup.com/?l=linux-hotplug-devel&m=102954820511328&w=2

There is nothing in the USB code that should be MIPS specific.  Despite
what Tom suspects everything is fine.  32-bit kernel symbols always start
with 0xffffffff and the value of usbdevfs_cleanup is an artefact of the
function having been discarded by the linker.

  Ralf

---

From: Jun Sun <[email-masked]>
Date: Tue, 19 Nov 2002 09:54:44 -0800

> function having been discarded by the linker.

Additional info:

USB has been working on MIPS for well over a year now.  There was a problem
early on due to non-coherent MIPS cache, but it was solved back then.

We have been using USB on global span IVR successfully.  Maybe there are
still some patches missing in linux-mips tree.  I will take a look later.

Jun

---

From: Pete Popov <[email-masked]>
Date: 19 Nov 2002 10:03:47 -0800

On Tue, 2002-11-19 at 09:54, Jun Sun wrote:
> We have been using USB on global span IVR successfully.  

... among many other mips boards.

> Maybe there are still some patches missing in linux-mips tree.  I will 
> take a look later.

Pete

---

From: Yoichi Yuasa <[email-masked]>
Date: Wed, 20 Nov 2002 11:49:30 +0900

Hi,

On 19 Nov 2002 10:03:47 -0800

> > Maybe there are still some patches missing in linux-mips tree.  I will 

I don't have a problem with current CVS tree(linux_2_4 tag) and a small patch.

I tested by the following system.
Hot plug is fine.

NEC VR4122(Eagle)
USB OCHI Controller
SanDisk SDDR-31
128MB CF

I attached a small patch.

Yoichi

--- linux.orig/drivers/usb/hub.c	Thu Sep 12 13:09:25 2002
+++ linux/drivers/usb/hub.c	Wed Nov 20 11:43:34 2002
@@ -698,12 +698,6 @@
 		return;
 	}
 
-	if (usb_hub_port_debounce(hub, port)) {
-		err("connect-debounce failed, port %d disabled", port+1);
-		usb_hub_port_disable(hub, port);
-		return;
-	}
-
 	down(&usb_address0_sem);
 
 	tempstr = kmalloc(1024, GFP_KERNEL);

---

From: "??" <[email-masked]>
Date: Wed, 20 Nov 2002 11:25:13 +0800

dear jun,
do you have the patch to fix "non-coherent MIPS cache"?
thanks in advanced!:)

and thanks you all who reply to this so quickly:)
btw, i don't mean usb not function with linux mips kernel
i mean using the "hotplug"-usb
support(http://linux-hotplug.sourceforge.net/?selected=usb) with linux mips
kernel

for example, after we plug in usb cable with a mips board,
the mips kernel try to execute "/sbin/hotplug" shell script,
then kernel wait_for_complete() for "/sbin/hotplug" with spin_lock_irq(),
the do_execve() of "/sbin/hotplug" return 0(successfully),
however, wait_for_complete() never return,
then kernel is reseted by hardware watchdog(timeout 3 secs)

we already trace this problem over a month,
but still can't figure out is it a userland
problem(cross-compiler/shell(bash))
or a problem with linux mips kernel

best regards,

---

From: "??" <[email-masked]>
Date: Wed, 20 Nov 2002 11:50:51 +0800

dear Yoichi,

thanks for your reply & patch
we are using kernel 2.4.18, after reading your patch,

we found there is no following section:
- if (usb_hub_port_debounce(hub, port)) {
-  err("connect-debounce failed, port %d disabled", port+1);
-  usb_hub_port_disable(hub, port);
-  return;
- }

but a following section: (mentioned redhat bug #23670)
>        /* Some low speed devices have problems with the quick delay, so */
>        /*  be a bit pessimistic with those devices. RHbug #23670 */
>       if (portstatus & USB_PORT_STAT_LOW_SPEED) {
>                wait_ms(400);
>                delay = HUB_LONG_RESET_TIME;
>        }

can we safely remove the above section?

best regards,

----- Original Message -----
From: "Yoichi Yuasa" <[email-masked]>
To: <[email-masked]>
Cc: <[email-masked]>; <[email-masked]>; <[email-masked]>;
<[email-masked]>
Sent: Wednesday, November 20, 2002 10:49 AM
Subject: Re: usb hotplug function with linux mips kernel

---

From: Ralf Baechle <[email-masked]>
Date: Thu, 21 Nov 2002 16:37:39 +0100

> +++ linux/drivers/usb/hub.c	Wed Nov 20 11:43:34 2002

Looks like a total hack, don't expect me to apply this ...

  Ralf