From: Andy P. <at...@us...> - 2002-04-10 18:32:34
|
Update of /cvsroot/linux-vax/kernel-2.4/arch/mips64/sgi-ip27 In directory usw-pr-cvs1:/tmp/cvs-serv18937/mips64/sgi-ip27 Modified Files: Makefile ip27-berr.c ip27-console.c ip27-init.c ip27-irq-glue.S ip27-irq.c ip27-klconfig.c ip27-klnuma.c ip27-memory.c ip27-pci-dma.c ip27-pci.c ip27-setup.c ip27-timer.c Log Message: synch 2.4.15 commit 38 Index: Makefile =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/mips64/sgi-ip27/Makefile,v retrieving revision 1.1.1.2 retrieving revision 1.2 diff -u -r1.1.1.2 -r1.2 --- Makefile 25 Feb 2001 23:15:22 -0000 1.1.1.2 +++ Makefile 10 Apr 2002 14:43:22 -0000 1.2 @@ -7,7 +7,7 @@ .S.o: $(CC) $(CFLAGS) -c $< -o $*.o -O_TARGET = ip27.a +O_TARGET = ip27.o obj-y := ip27-berr.o ip27-console.o ip27-irq.o ip27-init.o ip27-irq-glue.o \ ip27-klconfig.o ip27-klnuma.o ip27-memory.o ip27-nmi.o ip27-pci.o \ Index: ip27-berr.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/mips64/sgi-ip27/ip27-berr.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- ip27-berr.c 14 Jan 2001 19:54:37 -0000 1.1.1.1 +++ ip27-berr.c 10 Apr 2002 14:43:22 -0000 1.2 @@ -8,6 +8,9 @@ */ #include <linux/init.h> #include <linux/kernel.h> +#include <linux/module.h> + +#include <asm/module.h> #include <asm/sn/addrs.h> #include <asm/sn/arch.h> #include <asm/sn/sn0/hub.h> @@ -43,16 +46,43 @@ return 0; } +extern spinlock_t modlist_lock; + static inline unsigned long search_dbe_table(unsigned long addr) { unsigned long ret; +#ifndef CONFIG_MODULES /* There is only the kernel to search. */ ret = search_one_table(__start___dbe_table, __stop___dbe_table-1, addr); - if (ret) return ret; - - return 0; + return ret; +#else + unsigned long flags; + + /* The kernel is the last "module" -- no need to treat it special. */ + struct module *mp; + struct archdata *ap; + + spin_lock_irqsave(&modlist_lock, flags); + for (mp = module_list; mp != NULL; mp = mp->next) { + if (!mod_member_present(mp, archdata_end) || + !mod_archdata_member_present(mp, struct archdata, + dbe_table_end)) + continue; + ap = (struct archdata *)(mod->archdata_start); + + if (ap->dbe_table_start == NULL || + !(mp->flags & (MOD_RUNNING | MOD_INITIALIZING))) + continue; + ret = search_one_table(ap->dbe_table_start, + ap->dbe_table_end - 1, addr); + if (ret) + break; + } + spin_unlock_irqrestore(&modlist_lock, flags); + return ret; +#endif } void do_ibe(struct pt_regs *regs) @@ -64,9 +94,43 @@ while(1); } +static void dump_hub_information(unsigned long errst0, unsigned long errst1) +{ + static char *err_type[2][8] = { + { NULL, "Uncached Partial Read PRERR", "DERR", "Read Timeout", + NULL, NULL, NULL, NULL }, + { "WERR", "Uncached Partial Write", "PWERR", "Write Timeout", + NULL, NULL, NULL, NULL } + }; + int wrb = errst1 & PI_ERR_ST1_WRBRRB_MASK; + + if (!(errst0 & PI_ERR_ST0_VALID_MASK)) { + printk("Hub does not contain valid error information\n"); + return; + } + + + printk("Hub has valid error information:\n"); + if (errst0 & PI_ERR_ST0_OVERRUN_MASK) + printk("Overrun is set. Error stack may contain additional " + "information.\n"); + printk("Hub error address is %08lx\n", + (errst0 & PI_ERR_ST0_ADDR_MASK) >> (PI_ERR_ST0_ADDR_SHFT - 3)); + printk("Incoming message command 0x%lx\n", + (errst0 & PI_ERR_ST0_CMD_MASK) >> PI_ERR_ST0_CMD_SHFT); + printk("Supplemental field of incoming message is 0x%lx\n", + (errst0 & PI_ERR_ST0_SUPPL_MASK) >> PI_ERR_ST0_SUPPL_SHFT); + printk("T5 Rn (for RRB only) is 0x%lx\n", + (errst0 & PI_ERR_ST0_REQNUM_MASK) >> PI_ERR_ST0_REQNUM_SHFT); + printk("Error type is %s\n", err_type[wrb] + [(errst0 & PI_ERR_ST0_TYPE_MASK) >> PI_ERR_ST0_TYPE_SHFT] + ? : "invalid"); +} + void do_dbe(struct pt_regs *regs) { - unsigned long fixup; + unsigned long fixup, errst0, errst1; + int cpu = LOCAL_HUB_L(PI_CPU_NUM); fixup = search_dbe_table(regs->cp0_epc); if (fixup) { @@ -77,7 +141,12 @@ return; } - printk("Got dbe at 0x%lx\n", regs->cp0_epc); + printk("Slice %c got dbe at 0x%lx\n", 'A' + cpu, regs->cp0_epc); + printk("Hub information:\n"); + printk("ERR_INT_PEND = 0x%06lx\n", LOCAL_HUB_L(PI_ERR_INT_PEND)); + errst0 = LOCAL_HUB_L(cpu ? PI_ERR_STATUS0_B : PI_ERR_STATUS0_A); + errst1 = LOCAL_HUB_L(cpu ? PI_ERR_STATUS1_B : PI_ERR_STATUS1_A); + dump_hub_information(errst0, errst1); show_regs(regs); dump_tlb_all(); while(1); @@ -95,7 +164,7 @@ set_except_vector(7, handle_dbe); LOCAL_HUB_S(PI_ERR_INT_PEND, - cpu ? PI_ERR_CLEAR_ALL_A : PI_ERR_CLEAR_ALL_B); + cpu ? PI_ERR_CLEAR_ALL_B : PI_ERR_CLEAR_ALL_A); LOCAL_HUB_S(PI_ERR_INT_MASK_A + cpuoff, 0); LOCAL_HUB_S(PI_ERR_STACK_ADDR_A + cpuoff, 0); LOCAL_HUB_S(PI_ERR_STACK_SIZE, 0); /* Disable error stack */ Index: ip27-console.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/mips64/sgi-ip27/ip27-console.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- ip27-console.c 14 Jan 2001 19:54:49 -0000 1.1.1.1 +++ ip27-console.c 10 Apr 2002 14:43:22 -0000 1.2 @@ -2,6 +2,8 @@ * 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) 2001 Ralf Baechle */ #include <linux/init.h> #include <linux/console.h> @@ -11,7 +13,6 @@ #include <asm/sn/sn0/hub.h> #include <asm/sn/klconfig.h> #include <asm/sn/ioc3.h> -#include <asm/sgialib.h> #include <asm/sn/sn_private.h> void prom_putchar(char c) Index: ip27-init.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/mips64/sgi-ip27/ip27-init.c,v retrieving revision 1.1.1.2 retrieving revision 1.2 diff -u -r1.1.1.2 -r1.2 --- ip27-init.c 25 Feb 2001 23:15:22 -0000 1.1.1.2 +++ ip27-init.c 10 Apr 2002 14:43:22 -0000 1.2 @@ -1,3 +1,12 @@ +/* + * 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) 2000 - 2001 by Kanoj Sarcar (ka...@sg...) + * Copyright (C) 2000 - 2001 by Silicon Graphics, Inc. + */ + #include <linux/config.h> #include <linux/kernel.h> #include <linux/init.h> @@ -23,14 +32,14 @@ #include <asm/sn/sn_private.h> #include <asm/sn/sn0/ip27.h> #include <asm/sn/mapped_kernel.h> +#include <asm/sn/sn0/addrs.h> +#include <asm/sn/gda.h> #define CPU_NONE (cpuid_t)-1 -#define CPUMASK_CLRALL(p) (p) = 0 -#define CPUMASK_SETB(p, bit) (p) |= 1 << (bit) -#define CPUMASK_CLRB(p, bit) (p) &= ~(1ULL << (bit)) -#define CPUMASK_TSTB(p, bit) ((p) & (1ULL << (bit))) - +/* + * The following should work till 64 nodes, ie 128p SN0s. + */ #define CNODEMASK_CLRALL(p) (p) = 0 #define CNODEMASK_TSTB(p, bit) ((p) & (1ULL << (bit))) #define CNODEMASK_SETB(p, bit) ((p) |= 1ULL << (bit)) @@ -42,11 +51,13 @@ static spinlock_t hub_mask_lock = SPIN_LOCK_UNLOCKED; static cnodemask_t hub_init_mask; static atomic_t numstarted = ATOMIC_INIT(1); +static int router_distance; nasid_t master_nasid = INVALID_NASID; cnodeid_t nasid_to_compact_node[MAX_NASIDS]; nasid_t compact_to_nasid_node[MAX_COMPACT_NODES]; cnodeid_t cpuid_to_compact_node[MAXCPUS]; +char node_distances[MAX_COMPACT_NODES][MAX_COMPACT_NODES]; hubreg_t get_region(cnodeid_t cnode) { @@ -89,9 +100,13 @@ return brd->brd_nasid; } +/* Tweak this for maximum number of CPUs to activate */ +static int max_cpus = NR_CPUS; + int do_cpumask(cnodeid_t cnode, nasid_t nasid, cpumask_t *boot_cpumask, int *highest) { + static int tot_cpus_found = 0; lboard_t *brd; klcpu_t *acpu; int cpus_found = 0; @@ -109,9 +124,11 @@ if (cpuid > *highest) *highest = cpuid; /* Only let it join in if it's marked enabled */ - if (acpu->cpu_info.flags & KLINFO_ENABLE) { + if ((acpu->cpu_info.flags & KLINFO_ENABLE) && + (tot_cpus_found != max_cpus)) { CPUMASK_SETB(*boot_cpumask, cpuid); cpus_found++; + tot_cpus_found++; } acpu = (klcpu_t *)find_component(brd, (klinfo_t *)acpu, KLSTRUCT_CPU); @@ -172,6 +189,9 @@ void mlreset (void) { int i; + void init_topology_matrix(void); + void dump_topology(void); + master_nasid = get_nasid(); fine_mode = is_fine_dirmode(); @@ -184,6 +204,9 @@ maxcpus = cpu_node_probe(&boot_cpumask, &numnodes); printk("Discovered %d cpus on %d nodes\n", maxcpus, numnodes); + init_topology_matrix(); + dump_topology(); + gen_region_mask(®ion_mask, numnodes); CNODEMASK_CLRALL(hub_init_mask); @@ -474,7 +497,7 @@ alloc_cpupda(cpu, num_cpus); del_from_runqueue(p); p->processor = num_cpus; - p->has_cpu = 1; /* we schedule the first task manually */ + 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); @@ -534,3 +557,284 @@ #else /* CONFIG_SMP */ void cboot(void) {} #endif /* CONFIG_SMP */ + + +#define rou_rflag rou_flags + +void +router_recurse(klrou_t *router_a, klrou_t *router_b, int depth) +{ + klrou_t *router; + lboard_t *brd; + int port; + + if (router_a->rou_rflag == 1) + return; + + if (depth >= router_distance) + return; + + router_a->rou_rflag = 1; + + for (port = 1; port <= MAX_ROUTER_PORTS; port++) { + if (router_a->rou_port[port].port_nasid == INVALID_NASID) + continue; + + brd = (lboard_t *)NODE_OFFSET_TO_K0( + router_a->rou_port[port].port_nasid, + router_a->rou_port[port].port_offset); + + if (brd->brd_type == KLTYPE_ROUTER) { + router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd), brd->brd_compts[0]); + if (router == router_b) { + if (depth < router_distance) + router_distance = depth; + } + else + router_recurse(router, router_b, depth + 1); + } + } + + router_a->rou_rflag = 0; +} + +int +node_distance(nasid_t nasid_a, nasid_t nasid_b) +{ + nasid_t nasid; + cnodeid_t cnode; + lboard_t *brd, *dest_brd; + int port; + klrou_t *router, *router_a = NULL, *router_b = NULL; + + /* Figure out which routers nodes in question are connected to */ + for (cnode = 0; cnode < numnodes; cnode++) { + nasid = COMPACT_TO_NASID_NODEID(cnode); + + if (nasid == -1) continue; + + brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid), + KLTYPE_ROUTER); + + if (!brd) + continue; + + do { + if (brd->brd_flags & DUPLICATE_BOARD) + continue; + + router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd), brd->brd_compts[0]); + router->rou_rflag = 0; + + for (port = 1; port <= MAX_ROUTER_PORTS; port++) { + if (router->rou_port[port].port_nasid == INVALID_NASID) + continue; + + dest_brd = (lboard_t *)NODE_OFFSET_TO_K0( + router->rou_port[port].port_nasid, + router->rou_port[port].port_offset); + + if (dest_brd->brd_type == KLTYPE_IP27) { + if (dest_brd->brd_nasid == nasid_a) + router_a = router; + if (dest_brd->brd_nasid == nasid_b) + router_b = router; + } + } + + } while ( (brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER)) ); + } + + if (router_a == NULL) { + printk("node_distance: router_a NULL\n"); + return -1; + } + if (router_b == NULL) { + printk("node_distance: router_b NULL\n"); + return -1; + } + + if (nasid_a == nasid_b) + return 0; + + if (router_a == router_b) + return 1; + + router_distance = 100; + router_recurse(router_a, router_b, 2); + + return router_distance; +} + +void +init_topology_matrix(void) +{ + nasid_t nasid, nasid2; + cnodeid_t row, col; + + for (row = 0; row < MAX_COMPACT_NODES; row++) + for (col = 0; col < MAX_COMPACT_NODES; col++) + node_distances[row][col] = -1; + + for (row = 0; row < numnodes; row++) { + nasid = COMPACT_TO_NASID_NODEID(row); + for (col = 0; col < numnodes; col++) { + nasid2 = COMPACT_TO_NASID_NODEID(col); + node_distances[row][col] = node_distance(nasid, nasid2); + } + } +} + +void +dump_topology(void) +{ + nasid_t nasid; + cnodeid_t cnode; + lboard_t *brd, *dest_brd; + int port; + int router_num = 0; + klrou_t *router; + cnodeid_t row, col; + + printk("************** Topology ********************\n"); + + printk(" "); + for (col = 0; col < numnodes; col++) + printk("%02d ", col); + printk("\n"); + for (row = 0; row < numnodes; row++) { + printk("%02d ", row); + for (col = 0; col < numnodes; col++) + printk("%2d ", node_distances[row][col]); + printk("\n"); + } + + for (cnode = 0; cnode < numnodes; cnode++) { + nasid = COMPACT_TO_NASID_NODEID(cnode); + + if (nasid == -1) continue; + + brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid), + KLTYPE_ROUTER); + + if (!brd) + continue; + + do { + if (brd->brd_flags & DUPLICATE_BOARD) + continue; + printk("Router %d:", router_num); + router_num++; + + router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd), brd->brd_compts[0]); + + for (port = 1; port <= MAX_ROUTER_PORTS; port++) { + if (router->rou_port[port].port_nasid == INVALID_NASID) + continue; + + dest_brd = (lboard_t *)NODE_OFFSET_TO_K0( + router->rou_port[port].port_nasid, + router->rou_port[port].port_offset); + + if (dest_brd->brd_type == KLTYPE_IP27) + printk(" %d", dest_brd->brd_nasid); + if (dest_brd->brd_type == KLTYPE_ROUTER) + printk(" r"); + } + printk("\n"); + + } while ( (brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER)) ); + } +} + +#if 0 +#define brd_widgetnum brd_slot +#define NODE_OFFSET_TO_KLINFO(n,off) ((klinfo_t*) TO_NODE_CAC(n,off)) +void +dump_klcfg(void) +{ + cnodeid_t cnode; + int i; + nasid_t nasid; + lboard_t *lbptr; + gda_t *gdap; + + gdap = (gda_t *)GDA_ADDR(get_nasid()); + if (gdap->g_magic != GDA_MAGIC) { + printk("dumpklcfg_cmd: Invalid GDA MAGIC\n"); + return; + } + + for (cnode = 0; cnode < MAX_COMPACT_NODES; cnode ++) { + nasid = gdap->g_nasidtable[cnode]; + + if (nasid == INVALID_NASID) + continue; + + printk("\nDumpping klconfig Nasid %d:\n", nasid); + + lbptr = KL_CONFIG_INFO(nasid); + + while (lbptr) { + printk(" %s, Nasid %d, Module %d, widget 0x%x, partition %d, NIC 0x%x lboard 0x%lx", + "board name here", /* BOARD_NAME(lbptr->brd_type), */ + lbptr->brd_nasid, lbptr->brd_module, + lbptr->brd_widgetnum, + lbptr->brd_partition, + (lbptr->brd_nic), lbptr); + if (lbptr->brd_flags & DUPLICATE_BOARD) + printk(" -D"); + printk("\n"); + for (i = 0; i < lbptr->brd_numcompts; i++) { + klinfo_t *kli; + kli = NODE_OFFSET_TO_KLINFO(NASID_GET(lbptr), lbptr->brd_compts[i]); + printk(" type %2d, flags 0x%04x, diagval %3d, physid %4d, virtid %2d: %s\n", + kli->struct_type, + kli->flags, + kli->diagval, + kli->physid, + kli->virtid, + "comp. name here"); + /* COMPONENT_NAME(kli->struct_type)); */ + } + lbptr = KLCF_NEXT(lbptr); + } + } + printk("\n"); + + /* Useful to print router maps also */ + + for (cnode = 0; cnode < MAX_COMPACT_NODES; cnode ++) { + klrou_t *kr; + int i; + + nasid = gdap->g_nasidtable[cnode]; + if (nasid == INVALID_NASID) + continue; + lbptr = KL_CONFIG_INFO(nasid); + + while (lbptr) { + + lbptr = find_lboard_class(lbptr, KLCLASS_ROUTER); + if(!lbptr) + break; + if (!KL_CONFIG_DUPLICATE_BOARD(lbptr)) { + printk("%llx -> \n", lbptr->brd_nic); + kr = (klrou_t *)find_first_component(lbptr, + KLSTRUCT_ROU); + for (i = 1; i <= MAX_ROUTER_PORTS; i++) { + printk("[%d, %llx]; ", + kr->rou_port[i].port_nasid, + kr->rou_port[i].port_offset); + } + printk("\n"); + } + lbptr = KLCF_NEXT(lbptr); + } + printk("\n"); + } + + dump_topology(); +} +#endif + Index: ip27-irq-glue.S =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/mips64/sgi-ip27/ip27-irq-glue.S,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- ip27-irq-glue.S 14 Jan 2001 19:54:39 -0000 1.1.1.1 +++ ip27-irq-glue.S 10 Apr 2002 14:43:22 -0000 1.2 @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * 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. Index: ip27-irq.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/mips64/sgi-ip27/ip27-irq.c,v retrieving revision 1.1.1.2 retrieving revision 1.2 diff -u -r1.1.1.2 -r1.2 --- ip27-irq.c 25 Feb 2001 23:15:22 -0000 1.1.1.2 +++ ip27-irq.c 10 Apr 2002 14:43:22 -0000 1.2 @@ -3,6 +3,7 @@ * * Copyright (C) 1999, 2000 Ralf Baechle (ra...@gn...) * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + * Copyright (C) 1999 - 2001 Kanoj Sarcar */ #include <linux/config.h> #include <linux/init.h> @@ -25,6 +26,7 @@ #include <asm/io.h> #include <asm/mipsregs.h> #include <asm/system.h> +#include <asm/irq.h> #include <asm/ptrace.h> #include <asm/processor.h> @@ -42,6 +44,10 @@ #define DBG(x...) #endif +/* These should die */ +unsigned char bus_to_wid[256]; /* widget id for linux pci bus */ +unsigned char bus_to_nid[256]; /* nasid for linux pci bus */ +unsigned char num_bridges; /* number of bridges in the system */ /* * Linux has a controller-independent x86 interrupt architecture. @@ -67,11 +73,11 @@ unsigned long spurious_count = 0; /* - * we need to map irq's up to at least bit 7 of the INT_MASK0_A register - * since bits 0-6 are pre-allocated for other purposes. + * There is a single intpend register per node, and we want to have + * distinct levels for intercpu intrs for both cpus A and B on a node. */ -#define IRQ_TO_SWLEVEL(cpu, i) i + 7 -#define SWLEVEL_TO_IRQ(cpu, s) s - 7 +int node_level_to_irq[MAX_COMPACT_NODES][PERNODE_LEVELS]; + /* * use these macros to get the encoded nasid and widget id * from the irq value @@ -82,6 +88,41 @@ #define WID_FROM_PCI_IRQ(i) bus_to_wid[IRQ_TO_BUS(i)] #define SLOT_FROM_PCI_IRQ(i) irq_to_slot[i] +static inline int alloc_level(cpuid_t cpunum, int irq) +{ + cnodeid_t nodenum = CPUID_TO_COMPACT_NODEID(cpunum); + int j = LEAST_LEVEL + 3; /* resched & crosscall entries taken */ + + while (++j < PERNODE_LEVELS) { + if (node_level_to_irq[nodenum][j] == -1) { + node_level_to_irq[nodenum][j] = irq; + return j; + } + } + printk("Cpu %ld flooded with devices\n", cpunum); + while(1); + return -1; +} + +static inline int find_level(cpuid_t *cpunum, int irq) +{ + int j; + cnodeid_t nodenum = INVALID_CNODEID; + + while (++nodenum < MAX_COMPACT_NODES) { + j = LEAST_LEVEL + 3; /* resched & crosscall entries taken */ + while (++j < PERNODE_LEVELS) + if (node_level_to_irq[nodenum][j] == irq) { + *cpunum = 0; /* XXX Fixme */ + return(j); + } + } + printk("Could not identify cpu/level for irq %d\n", irq); + while(1); + return(-1); +} + + void disable_irq(unsigned int irq_nr) { panic("disable_irq() called ..."); @@ -146,7 +187,8 @@ } irq_exit(thiscpu, irq); - /* unmasking and bottom half handling is done magically for us. */ + if (softirq_pending(thiscpu)) + do_softirq(); } /* @@ -196,7 +238,7 @@ swlevel = ms1bit(pend0); LOCAL_HUB_CLR_INTR(swlevel); /* "map" swlevel to irq */ - irq = SWLEVEL_TO_IRQ(thiscpu, swlevel); + irq = LEVEL_TO_IRQ(thiscpu, swlevel); do_IRQ(thiscpu, irq, regs); /* clear bit in pend0 */ pend0 ^= 1ULL << swlevel; @@ -227,7 +269,7 @@ * "map" irq to a swlevel greater than 6 since the first 6 bits * of INT_PEND0 are taken */ - swlevel = IRQ_TO_SWLEVEL(cpu, irq); + swlevel = alloc_level(cpu, irq); intr_connect_level(cpu, swlevel); bridge->b_int_addr[pin].addr = (0x20000 | swlevel | (master << 8)); @@ -254,6 +296,7 @@ { bridge_t *bridge; int pin, swlevel; + cpuid_t cpu; bridge = (bridge_t *) NODE_SWIN_BASE(NASID_FROM_PCI_IRQ(irq), WID_FROM_PCI_IRQ(irq)); @@ -264,8 +307,9 @@ * map irq to a swlevel greater than 6 since the first 6 bits * of INT_PEND0 are taken */ - swlevel = IRQ_TO_SWLEVEL(cpu, irq); - intr_disconnect_level(smp_processor_id(), swlevel); + swlevel = find_level(&cpu, irq); + intr_disconnect_level(cpu, swlevel); + LEVEL_TO_IRQ(cpu, swlevel) = -1; bridge->b_int_enable &= ~(1 << pin); bridge->b_widget.w_tflush; /* Flush */ @@ -423,7 +467,6 @@ printk(" ]\nStack dumps:"); for(i = 0; i < smp_num_cpus; i++) { - unsigned long esp; if (i == cpu) continue; printk("\nCPU %d:",i); @@ -661,37 +704,50 @@ #ifdef CONFIG_SMP #if (CPUS_PER_NODE == 2) static int done = 0; - int irq; /* * This is a hack till we have a pernode irqlist. Currently, * just have the master cpu set up the handlers for the per * cpu irqs. */ + if (done == 0) { + int j; - irq = CPU_RESCHED_A_IRQ + cputoslice(cpu); - intr_connect_level(cpu, IRQ_TO_SWLEVEL(cpu, irq)); - if (done == 0) - if (request_irq(irq, handle_resched_intr, 0, "resched", 0)) - panic("intercpu intr unconnectible\n"); - irq = CPU_CALL_A_IRQ + cputoslice(cpu); - intr_connect_level(cpu, IRQ_TO_SWLEVEL(cpu, irq)); - if (done == 0) - if (request_irq(irq, smp_call_function_interrupt, 0, - "callfunc", 0)) - panic("intercpu intr unconnectible\n"); - /* HACK STARTS */ - if (done) - return; - irq = CPU_RESCHED_A_IRQ + cputoslice(cpu) + 1; - if (request_irq(irq, handle_resched_intr, 0, "resched", 0)) - panic("intercpu intr unconnectible\n"); - irq = CPU_CALL_A_IRQ + cputoslice(cpu) + 1; - if (request_irq(irq, smp_call_function_interrupt, 0, - "callfunc", 0)) - panic("intercpu intr unconnectible\n"); - done = 1; - /* HACK ENDS */ + if (request_irq(CPU_RESCHED_A_IRQ, handle_resched_intr, + 0, "resched", 0)) + panic("intercpu intr unconnectible\n"); + if (request_irq(CPU_RESCHED_B_IRQ, handle_resched_intr, + 0, "resched", 0)) + panic("intercpu intr unconnectible\n"); + if (request_irq(CPU_CALL_A_IRQ, smp_call_function_interrupt, + 0, "callfunc", 0)) + panic("intercpu intr unconnectible\n"); + if (request_irq(CPU_CALL_B_IRQ, smp_call_function_interrupt, + 0, "callfunc", 0)) + panic("intercpu intr unconnectible\n"); + + for (j = 0; j < PERNODE_LEVELS; j++) + LEVEL_TO_IRQ(0, j) = -1; + LEVEL_TO_IRQ(0, FAST_IRQ_TO_LEVEL(CPU_RESCHED_A_IRQ)) = + CPU_RESCHED_A_IRQ; + LEVEL_TO_IRQ(0, FAST_IRQ_TO_LEVEL(CPU_RESCHED_B_IRQ)) = + CPU_RESCHED_B_IRQ; + LEVEL_TO_IRQ(0, FAST_IRQ_TO_LEVEL(CPU_CALL_A_IRQ)) = + CPU_CALL_A_IRQ; + LEVEL_TO_IRQ(0, FAST_IRQ_TO_LEVEL(CPU_CALL_B_IRQ)) = + CPU_CALL_B_IRQ; + for (j = 1; j < MAX_COMPACT_NODES; j++) + memcpy(&node_level_to_irq[j][0], + &node_level_to_irq[0][0], + sizeof(node_level_to_irq[0][0])*PERNODE_LEVELS); + + done = 1; + } + + intr_connect_level(cpu, FAST_IRQ_TO_LEVEL(CPU_RESCHED_A_IRQ + + cputoslice(cpu))); + intr_connect_level(cpu, FAST_IRQ_TO_LEVEL(CPU_CALL_A_IRQ + + cputoslice(cpu))); #else /* CPUS_PER_NODE */ #error Must redefine this for more than 2 CPUS. #endif /* CPUS_PER_NODE */ @@ -700,7 +756,9 @@ void install_tlbintr(int cpu) { +#if 0 int intr_bit = N_INTPEND_BITS + TLB_INTR_A + cputoslice(cpu); intr_connect_level(cpu, intr_bit); +#endif } Index: ip27-klconfig.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/mips64/sgi-ip27/ip27-klconfig.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- ip27-klconfig.c 14 Jan 2001 19:54:42 -0000 1.1.1.1 +++ ip27-klconfig.c 10 Apr 2002 14:43:22 -0000 1.2 @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * Copyright (C) 1999, 2000 Ralf Baechle (ra...@gn...) * Copyright (C) 1999, 2000 Silicon Graphics, Inc. */ @@ -57,6 +56,19 @@ return start; start = KLCF_NEXT(start); } + /* Didn't find it. */ + return (lboard_t *)NULL; +} + +lboard_t * find_lboard_class(lboard_t *start, unsigned char brd_type) +{ + /* Search all boards stored on this node. */ + while (start) { + if (KLCLASS(start->brd_type) == KLCLASS(brd_type)) + return start; + start = KLCF_NEXT(start); + } + /* Didn't find it. */ return (lboard_t *)NULL; } Index: ip27-klnuma.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/mips64/sgi-ip27/ip27-klnuma.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- ip27-klnuma.c 14 Jan 2001 19:54:49 -0000 1.1.1.1 +++ ip27-klnuma.c 10 Apr 2002 14:43:22 -0000 1.2 @@ -1,6 +1,7 @@ /* * Ported from IRIX to Linux by Kanoj Sarcar, 06/08/00. - * Copyright 2000 Silicon Graphics, Inc. + * Copyright 2000 - 2001 Silicon Graphics, Inc. + * Copyright 2000 - 2001 Kanoj Sarcar (ka...@sg...) */ #include <linux/config.h> #include <linux/init.h> @@ -9,6 +10,7 @@ #include <linux/string.h> #include <asm/page.h> +#include <asm/smp.h> #include <asm/sn/types.h> #include <asm/sn/arch.h> #include <asm/sn/gda.h> @@ -16,10 +18,6 @@ #include <asm/sn/klkernvars.h> #include <asm/sn/mapped_kernel.h> #include <asm/sn/sn_private.h> - -#define CPUMASK_CLRALL(p) (p) = 0 -#define CPUMASK_SETB(p, bit) (p) |= 1 << (bit) -#define CPUMASK_TSTB(p, bit) ((p) & (1ULL << (bit))) extern char _end; static cpumask_t ktext_repmask; Index: ip27-memory.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/mips64/sgi-ip27/ip27-memory.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- ip27-memory.c 14 Jan 2001 19:54:43 -0000 1.1.1.1 +++ ip27-memory.c 10 Apr 2002 14:43:22 -0000 1.2 @@ -20,6 +20,7 @@ #include <asm/bootinfo.h> #include <asm/addrspace.h> #include <asm/pgtable.h> +#include <asm/pgalloc.h> #include <asm/sn/types.h> #include <asm/sn/addrs.h> #include <asm/sn/klconfig.h> @@ -227,15 +228,24 @@ void __init paging_init(void) { + pmd_t *pmd = kpmdtbl; + pte_t *pte = kptbl; + cnodeid_t node; unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; + int i; /* Initialize the entire pgd. */ pgd_init((unsigned long)swapper_pg_dir); pmd_init((unsigned long)invalid_pmd_table, (unsigned long)invalid_pte_table); memset((void *)invalid_pte_table, 0, sizeof(pte_t) * PTRS_PER_PTE); - pmd_init((unsigned long)empty_bad_pmd_table, (unsigned long)empty_bad_page_table); - memset((void *)empty_bad_page_table, 0, sizeof(pte_t) * PTRS_PER_PTE); + + /* This is for vmalloc */ + memset((void *)kptbl, 0, PAGE_SIZE << KPTBL_PAGE_ORDER); + memset((void *)kpmdtbl, 0, PAGE_SIZE); + pgd_set(swapper_pg_dir, kpmdtbl); + for (i = 0; i < (1 << KPTBL_PAGE_ORDER); pmd++,i++,pte+=PTRS_PER_PTE) + pmd_val(*pmd) = (unsigned long)pte; for (node = 0; node < numnodes; node++) { pfn_t start_pfn = slot_getbasepfn(node, 0); Index: ip27-pci-dma.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/mips64/sgi-ip27/ip27-pci-dma.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- ip27-pci-dma.c 14 Jan 2001 19:54:43 -0000 1.1.1.1 +++ ip27-pci-dma.c 10 Apr 2002 14:43:22 -0000 1.2 @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * Dynamic DMA mapping support. * * On the Origin there is dynamic DMA address translation for all PCI DMA. @@ -52,4 +51,114 @@ void *vaddr, dma_addr_t dma_handle) { free_pages((unsigned long)vaddr, __get_order(size)); +} + +/* + * Map a single buffer of the indicated size for DMA in streaming mode. + * The 32-bit bus address to use is returned. + * + * Once the device is given the dma address, the device owns this memory + * until either pci_unmap_single or pci_dma_sync_single is performed. + */ +dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size, + int direction) +{ + if (direction == PCI_DMA_NONE) + BUG(); + + return (bus_to_baddr[hwdev->bus->number] | __pa(ptr)); +} + +/* + * Unmap a single streaming mode DMA translation. The dma_addr and size + * must match what was provided for in a previous pci_map_single call. All + * other usages are undefined. + * + * After this call, reads by the cpu to the buffer are guarenteed to see + * whatever the device wrote there. + */ +void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, + size_t size, int direction) +{ + if (direction == PCI_DMA_NONE) + BUG(); + + /* Nothing to do */ +} + +/* + * Map a set of buffers described by scatterlist in streaming + * mode for DMA. This is the scather-gather version of the + * above pci_map_single interface. Here the scatter gather list + * elements are each tagged with the appropriate dma address + * and length. They are obtained via sg_dma_{address,length}(SG). + * + * NOTE: An implementation may be able to use a smaller number of + * DMA address/length pairs than there are SG table elements. + * (for example via virtual mapping capabilities) + * The routine returns the number of addr/length pairs actually + * used, at most nents. + * + * Device ownership issues as mentioned above for pci_map_single are + * the same here. + */ +int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, + int direction) +{ + int i; + + if (direction == PCI_DMA_NONE) + BUG(); + + /* Make sure that gcc doesn't leave the empty loop body. */ + for (i = 0; i < nents; i++, sg++) { + sg->address = (char *)(bus_to_baddr[hwdev->bus->number] | __pa(sg->address)); + } + + return nents; +} + +/* + * Unmap a set of streaming mode DMA translations. + * Again, cpu read rules concerning calls here are the same as for + * pci_unmap_single() above. + */ +void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, + int direction) +{ + if (direction == PCI_DMA_NONE) + BUG(); + + /* Nothing to do */ +} + +/* + * Make physical memory consistent for a single + * streaming mode DMA translation after a transfer. + * + * If you perform a pci_map_single() but wish to interrogate the + * buffer using the cpu, yet do not wish to teardown the PCI dma + * mapping, you must call this function before doing so. At the + * next point you give the PCI dma address back to the card, the + * device again owns the buffer. + */ +void pci_dma_sync_single(struct pci_dev *hwdev, dma_addr_t dma_handle, + size_t size, int direction) +{ + if (direction == PCI_DMA_NONE) + BUG(); +} + +/* + * Make physical memory consistent for a set of streaming + * mode DMA translations after a transfer. + * + * The same as pci_dma_sync_single but for a scatter-gather list, + * same rules and usage. + */ +void pci_dma_sync_sg(struct pci_dev *hwdev, struct scatterlist *sg, + int nelems, int direction) +{ + if (direction == PCI_DMA_NONE) + BUG(); } Index: ip27-pci.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/mips64/sgi-ip27/ip27-pci.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- ip27-pci.c 14 Jan 2001 19:54:44 -0000 1.1.1.1 +++ ip27-pci.c 10 Apr 2002 14:43:22 -0000 1.2 @@ -18,7 +18,7 @@ /* * Max #PCI busses we can handle; ie, max #PCI bridges. */ -#define MAX_PCI_BUSSES 20 +#define MAX_PCI_BUSSES 40 /* * Max #PCI devices (like scsi controllers) we handle on a bus. @@ -55,8 +55,12 @@ bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id], \ bus_to_wid[bus_id]); \ \ - /*if (dev->bus->number) */ \ - /* return PCIBIOS_DEVICE_NOT_FOUND; */ \ + if (dev->vendor == PCI_VENDOR_ID_SGI \ + && dev->device == PCI_DEVICE_ID_SGI_IOC3 \ + && ((where >= 0x14 && where < 0x40) || (where >= 0x48))) { \ + *value = 0; \ + return PCIBIOS_SUCCESSFUL; \ + } \ \ __bit = (((where) & (bm)) << 3); \ addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; \ @@ -96,11 +100,9 @@ bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id], \ bus_to_wid[bus_id]); \ \ - /* if (dev->bus->number) */ \ - /* return PCIBIOS_DEVICE_NOT_FOUND; */ \ - \ if (dev->vendor == PCI_VENDOR_ID_SGI \ - && dev->device == PCI_DEVICE_ID_SGI_IOC3) \ + && dev->device == PCI_DEVICE_ID_SGI_IOC3 \ + && ((where >= 0x14 && where < 0x40) || (where >= 0x48))) \ return PCIBIOS_SUCCESSFUL; \ \ __bit = (((where) & (bm)) << 3); \ @@ -147,6 +149,7 @@ int i; ioport_resource.end = ~0UL; + iomem_resource.end = ~0UL; for (i=0; i<num_bridges; i++) { printk("PCI: Probing PCI hardware on host bus %2d.\n", i); @@ -178,7 +181,7 @@ * All observed requests have pin == 1. We could have a global here, that * gets incremented and returned every time - unfortunately, pci_map_irq * may be called on the same device over and over, and need to return the - * same value. On o2000, pin can be 0 or 1, and PCI slots can be [0..7]. + * same value. On O2000, pin can be 0 or 1, and PCI slots can be [0..7]. * * A given PCI device, in general, should be able to intr any of the cpus * on any one of the hubs connected to its xbow. @@ -186,25 +189,23 @@ static int __init pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { - if ((dev->bus->number >= MAX_PCI_BUSSES) || (pin != 1) || \ - (slot >= MAX_DEVICES_PER_PCIBUS)) { - printk("Increase supported PCI busses %d,%d,%d\n", \ - dev->bus->number, slot, pin); - while(1); - } + if ((dev->bus->number >= MAX_PCI_BUSSES) + || (pin != 1) + || (slot >= MAX_DEVICES_PER_PCIBUS)) + panic("Increase supported PCI busses %d,%d,%d\n", + dev->bus->number, slot, pin); /* * Already assigned? Then return previously assigned value ... */ if (irqstore[dev->bus->number][slot]) - return(irqstore[dev->bus->number][slot]); - else { - irq_to_bus[lastirq] = dev->bus->number; - irq_to_slot[lastirq] = slot; - irqstore[dev->bus->number][slot] = lastirq; - lastirq++; - return (lastirq - 1); - } + return irqstore[dev->bus->number][slot]; + + irq_to_bus[lastirq] = dev->bus->number; + irq_to_slot[lastirq] = slot; + irqstore[dev->bus->number][slot] = lastirq; + lastirq++; + return lastirq - 1; } void __init @@ -237,10 +238,10 @@ pcibios_fixup_pbus_ranges(struct pci_bus * bus, struct pbus_set_ranges_data * ranges) { - ranges->io_start -= bus->resource[0]->start; - ranges->io_end -= bus->resource[0]->start; + ranges->io_start -= bus->resource[0]->start; + ranges->io_end -= bus->resource[0]->start; ranges->mem_start -= bus->resource[1]->start; - ranges->mem_end -= bus->resource[1]->start; + ranges->mem_end -= bus->resource[1]->start; } int __init @@ -255,6 +256,11 @@ { } +unsigned __init int pcibios_assign_all_busses(void) +{ + return 0; +} + char * __init pcibios_setup(char *str) { @@ -263,19 +269,23 @@ return str; } +/* + * Device might live on a subordinate PCI bus. XXX Walk up the chain of buses + * to find the slot number in sense of the bridge device register. + * XXX This also means multiple devices might rely on conflicting bridge + * settings. + */ + static void __init pci_disable_swapping(struct pci_dev *dev) { unsigned int bus_id = (unsigned) dev->bus->number; bridge_t *bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id], - bus_to_wid[bus_id]); + bus_to_wid[bus_id]); int slot = PCI_SLOT(dev->devfn); - bridgereg_t devreg; - - devreg = bridge->b_device[slot].reg; - devreg &= ~BRIDGE_DEV_SWAP_DIR; /* turn off byte swapping */ - bridge->b_device[slot].reg = devreg; + /* Turn off byte swapping */ + bridge->b_device[slot].reg &= ~BRIDGE_DEV_SWAP_DIR; bridge->b_widget.w_tflush; /* Flush */ } @@ -284,56 +294,25 @@ { unsigned int bus_id = (unsigned) dev->bus->number; bridge_t *bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id], - bus_to_wid[bus_id]); + bus_to_wid[bus_id]); int slot = PCI_SLOT(dev->devfn); - bridgereg_t devreg; - - devreg = bridge->b_device[slot].reg; - devreg |= BRIDGE_DEV_SWAP_DIR; /* turn on byte swapping */ - bridge->b_device[slot].reg = devreg; + /* Turn on byte swapping */ + bridge->b_device[slot].reg |= BRIDGE_DEV_SWAP_DIR; bridge->b_widget.w_tflush; /* Flush */ } static void __init pci_fixup_ioc3(struct pci_dev *d) { - unsigned int bus_id = (unsigned) d->bus->number; - int i; + unsigned long bus_id = (unsigned) d->bus->number; - /* IOC3 only decodes 0x20 bytes of the config space, so we end up - with tons of bogus information in the pci_dev. On Origins the - INTA, INTB and INTC pins are all wired together as if it'd only - use INTA. */ printk("PCI: Fixing base addresses for IOC3 device %s\n", d->slot_name); d->resource[0].start |= NODE_OFFSET(bus_to_nid[bus_id]); - d->resource[0].end |= NODE_OFFSET(bus_to_nid[bus_id]); - - for (i = 1; i <= PCI_ROM_RESOURCE; i++) { - d->resource[i].start = 0UL; - d->resource[i].end = 0UL; - d->resource[i].flags = 0UL; - } + d->resource[0].end |= NODE_OFFSET(bus_to_nid[bus_id]); pci_disable_swapping(d); - - /* - * The serial driver will try to probe for serial ports - * later on. MENET boards dbe out unrecoverably on sio space - * access to the 4th ioc3. (The first 3 iocs work okay, they - * have kbd/ms ports; all have ethernet ports). Catch this - * case now and disable the serial driver from looking at - * these ioc3s. Identify MENET cards by seeing if an ioc3 is - * at slot 3. - */ - d->subsystem_vendor = 0xFF00; - if (PCI_SLOT(d->devfn) == 3) { - struct list_head *p; - list_for_each(p, &d->bus->devices) { - list_entry(p, struct pci_dev, bus_list)->subsystem_vendor = 0; - } - } } static void __init @@ -344,7 +323,8 @@ d->resource[0].start |= ((unsigned long)(bus_to_nid[d->bus->number])<<32); printk("PCI: Fixing isp1020 in [bus:slot.fn] %s\n", d->slot_name); - /* Configure device to allow bus mastering, i/o and memory mapping. + /* + * Configure device to allow bus mastering, i/o and memory mapping. * Older qlogicisp driver expects to have the IO space enable * bit set. Things stop working if we program the controllers as not * having PCI_COMMAND_MEMORY, so we have to fudge the mem_flags. Index: ip27-setup.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/mips64/sgi-ip27/ip27-setup.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- ip27-setup.c 14 Jan 2001 19:54:47 -0000 1.1.1.1 +++ ip27-setup.c 10 Apr 2002 14:43:22 -0000 1.2 @@ -14,6 +14,7 @@ #include <linux/spinlock.h> #include <linux/sched.h> #include <linux/smp.h> +#include <asm/io.h> #include <asm/sn/types.h> #include <asm/sn/sn0/addrs.h> #include <asm/sn/sn0/hubni.h> @@ -39,6 +40,7 @@ #define DBG(x...) #endif +unsigned long mips_io_port_base = IO_BASE; /* * get_nasid() returns the physical node id number of the caller. Index: ip27-timer.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/mips64/sgi-ip27/ip27-timer.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- ip27-timer.c 14 Jan 2001 19:54:48 -0000 1.1.1.1 +++ ip27-timer.c 10 Apr 2002 14:43:22 -0000 1.2 @@ -145,6 +145,9 @@ } write_unlock(&xtime_lock); + + if (softirq_pending(cpu)) + do_softirq(); } unsigned long inline do_gettimeoffset(void) |