diff --git a/arch/mips/include/asm/irq.h b/arch/mips/include/asm/irq.h index 15e0fec..7b413c7 100644 --- a/arch/mips/include/asm/irq.h +++ b/arch/mips/include/asm/irq.h @@ -33,9 +33,11 @@ extern void do_IRQ(unsigned int irq); extern void arch_init_irq(void); extern void spurious_interrupt(void); -extern int allocate_irqno(void); -extern void alloc_legacy_irqno(void); -extern void free_irqno(unsigned int irq); +#if defined(CONFIG_SGI_IP27) +extern int ip27_alloc_irq_num(void); +extern void ip27_force_irq_num(int irq); +extern void ip27_free_irq_num(int irq); +#endif /* * Before R2 the timer and performance counter interrupts were both fixed to diff --git a/arch/mips/include/asm/mach-ip27/dma-coherence.h b/arch/mips/include/asm/mach-ip27/dma-coherence.h index 1daa644..04d8620 100644 --- a/arch/mips/include/asm/mach-ip27/dma-coherence.h +++ b/arch/mips/include/asm/mach-ip27/dma-coherence.h @@ -64,7 +64,7 @@ static inline void plat_post_dma_flush(struct device *dev) static inline int plat_device_is_coherent(struct device *dev) { - return 1; /* IP27 non-cohernet mode is unsupported */ + return 1; /* IP27 non-coherent mode is unsupported */ } #endif /* __ASM_MACH_IP27_DMA_COHERENCE_H */ diff --git a/arch/mips/include/asm/mach-ip27/mangle-port.h b/arch/mips/include/asm/mach-ip27/mangle-port.h index f6e4912..5184c94 100644 --- a/arch/mips/include/asm/mach-ip27/mangle-port.h +++ b/arch/mips/include/asm/mach-ip27/mangle-port.h @@ -8,7 +8,7 @@ #ifndef __ASM_MACH_IP27_MANGLE_PORT_H #define __ASM_MACH_IP27_MANGLE_PORT_H -#define __swizzle_addr_b(port) (port) +#define __swizzle_addr_b(port) ((port) ^ 3) #define __swizzle_addr_w(port) ((port) ^ 2) #define __swizzle_addr_l(port) (port) #define __swizzle_addr_q(port) (port) @@ -20,6 +20,6 @@ # define ioswabl(a, x) (x) # define __mem_ioswabl(a, x) cpu_to_le32(x) # define ioswabq(a, x) (x) -# define __mem_ioswabq(a, x) cpu_to_le32(x) +# define __mem_ioswabq(a, x) cpu_to_le64(x) #endif /* __ASM_MACH_IP27_MANGLE_PORT_H */ diff --git a/arch/mips/include/asm/mach-ip27/mmzone.h b/arch/mips/include/asm/mach-ip27/mmzone.h index ebc9377..52aa978 100644 --- a/arch/mips/include/asm/mach-ip27/mmzone.h +++ b/arch/mips/include/asm/mach-ip27/mmzone.h @@ -5,14 +5,10 @@ #include #include -#define pa_to_nid(addr) NASID_TO_COMPACT_NODEID(NASID_GET(addr)) +#define pa_to_nid(addr) sn_nasid_to_cnodeid[NASID_GET(addr)] -#define LEVELS_PER_SLICE 128 - -struct slice_data { - unsigned long irq_enable_mask[2]; - int level_to_irq[LEVELS_PER_SLICE]; -}; +#define LEVELS_PER_SLICE 128 +#define BITS_PER_SLICE 128 struct hub_data { kern_vars_t kern_vars; @@ -20,7 +16,18 @@ struct hub_data { cpumask_t h_cpus; unsigned long slice_map; unsigned long irq_alloc_mask[2]; - struct slice_data slice[2]; +}; + +struct ip27_percpu_data { + u32 id; + s16 nasid; + s16 cnodeid; + u8 slice; + unsigned long irq_mask[2]; + bool irq_owner[BITS_PER_SLICE]; + s8 irq_to_bit[BITS_PER_SLICE]; + s8 bit_to_irq[BITS_PER_SLICE]; + struct hub_data *hub; }; struct node_data { diff --git a/arch/mips/include/asm/mach-ip27/pcibr.h b/arch/mips/include/asm/mach-ip27/pcibr.h new file mode 100644 index 0000000..6a615bf --- /dev/null +++ b/arch/mips/include/asm/mach-ip27/pcibr.h @@ -0,0 +1,48 @@ +/* + * Definitions for PCI bridges in IP27. + * + * Copyright (C) 2004-2007 Stanislaw Skowronek + * Copyright (C) 2015-2016 Joshua Kinard + * + * 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. + */ + +#ifndef __ASM_MACH_IP27_PCIBR_H +#define __ASM_MACH_IP27_PCIBR_H + +#include +#include + +/* Xtalk */ +#define PCIBR_OFFSET_MEM 0x200000 +#define PCIBR_OFFSET_IO 0xa00000 +#define PCIBR_OFFSET_END 0xc00000 + +#define PCIBR_DIR_ALLOC_BASE 0x1000000 + +/* + * This is how XIO sees HUB's PI_INT_PEND_MOD register. + */ +#define PCIBR_XIO_SEES_HUB 0x00000080 + +/* + * Max # of PCI buses we can handle; ie, max #PCI bridges. + */ +#define PCIBR_MAX_NUM_PCIBUS 40 + +/* + * Max # of PCI devices (like scsi controllers) we handle on a bus. + */ +#define PCIBR_MAX_DEV_PCIBUS 8 + +/* + * Used by pci-ip27.c and ip27-irq.c. + */ +#define PCIBR_MAX_BUS_X_DEV PCIBR_MAX_NUM_PCIBUS * PCIBR_MAX_DEV_PCIBUS +extern struct bridge_controller *ip27_irq_to_bridge[PCIBR_MAX_BUS_X_DEV]; +extern unsigned int ip27_irq_to_slot[PCIBR_MAX_BUS_X_DEV]; + +#endif /* __ASM_MACH_IP27_PCIBR_H */ + diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h index 21ed715..2046c02 100644 --- a/arch/mips/include/asm/page.h +++ b/arch/mips/include/asm/page.h @@ -33,7 +33,7 @@ #define PAGE_SHIFT 16 #endif #define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT) -#define PAGE_MASK (~((1 << PAGE_SHIFT) - 1)) +#define PAGE_MASK (~(PAGE_SIZE - 1)) /* * This is used for calculating the real page sizes diff --git a/arch/mips/include/asm/pci/bridge.h b/arch/mips/include/asm/pci/bridge.h index 8d7a63b..9d6a355 100644 --- a/arch/mips/include/asm/pci/bridge.h +++ b/arch/mips/include/asm/pci/bridge.h @@ -14,6 +14,8 @@ #include #include +#include + #include /* generic widget header */ #include @@ -839,17 +841,14 @@ struct bridge_controller { bridge_t *base; nasid_t nasid; unsigned int widget_id; - unsigned int irq_cpu; u64 baddr; unsigned int pci_int[8]; + spinlock_t lock; }; #define BRIDGE_CONTROLLER(bus) \ ((struct bridge_controller *)((bus)->sysdata)) -extern void register_bridge_irq(unsigned int irq); -extern int request_bridge_irq(struct bridge_controller *bc); - extern struct pci_ops bridge_pci_ops; #endif /* _ASM_PCI_BRIDGE_H */ diff --git a/arch/mips/include/asm/sn/agent.h b/arch/mips/include/asm/sn/agent.h index e33d092..0ea2216 100644 --- a/arch/mips/include/asm/sn/agent.h +++ b/arch/mips/include/asm/sn/agent.h @@ -25,8 +25,8 @@ */ #if defined(CONFIG_SGI_IP27) -#define HUB_NIC_ADDR(_cpuid) \ - REMOTE_HUB_ADDR(COMPACT_TO_NASID_NODEID(cpu_to_node(_cpuid)), \ +#define HUB_NIC_ADDR(_cpuid) \ + REMOTE_HUB_ADDR(sn_cnodeid_to_nasid(sn_cpuid_to_cnodeid[(_cpuid)]), \ MD_MLAN_CTL) #endif diff --git a/arch/mips/include/asm/sn/arch.h b/arch/mips/include/asm/sn/arch.h index 471e687..18466fe 100644 --- a/arch/mips/include/asm/sn/arch.h +++ b/arch/mips/include/asm/sn/arch.h @@ -12,6 +12,8 @@ #define _ASM_SN_ARCH_H #include +#include + #include #ifdef CONFIG_SGI_IP27 #include @@ -19,8 +21,8 @@ typedef u64 hubreg_t; -#define cputonasid(cpu) (sn_cpu_info[(cpu)].p_nasid) -#define cputoslice(cpu) (sn_cpu_info[(cpu)].p_slice) +#define cpu_to_nasid(cpu) (sn_cpu_info[(cpu)].p_nasid) +#define cpu_to_slice(cpu) (sn_cpu_info[(cpu)].p_slice) #define makespnum(_nasid, _slice) \ (((_nasid) << CPUS_PER_NODE_SHFT) | (_slice)) @@ -30,35 +32,25 @@ typedef u64 hubreg_t; #define INVALID_MODULE (moduleid_t)-1 #define INVALID_PARTID (partid_t)-1 -extern nasid_t get_nasid(void); +extern nasid_t ip27_get_nasid(void); extern cnodeid_t get_cpu_cnode(cpuid_t); extern int get_cpu_slice(cpuid_t); -/* - * NO ONE should access these arrays directly. The only reason we refer to - * them here is to avoid the procedure call that would be required in the - * macros below. (Really want private data members here :-) - */ -extern cnodeid_t nasid_to_compact_node[MAX_NASIDS]; -extern nasid_t compact_to_nasid_node[MAX_COMPACT_NODES]; +#define NASID_TO_REGION(nnode) \ + ((nnode) >> (is_fine_dirmode() ? \ + NASID_TO_FINEREG_SHFT : NASID_TO_COARSEREG_SHFT)) -/* - * These macros are used by various parts of the kernel to convert - * between the three different kinds of node numbering. At least some - * of them may change to procedure calls in the future, but the macros - * will continue to work. Don't use the arrays above directly. - */ -#define NASID_TO_REGION(nnode) \ - ((nnode) >> \ - (is_fine_dirmode() ? NASID_TO_FINEREG_SHFT : NASID_TO_COARSEREG_SHFT)) +/* Compact node ID to nasid mappings as per-cpu data */ +DECLARE_PER_CPU(cnodeid_t, __sn_cnodeid_to_nasid[MAX_COMPACT_NODES]); +#define sn_cnodeid_to_nasid this_cpu_ptr(&__sn_cnodeid_to_nasid[0]) -extern cnodeid_t nasid_to_compact_node[MAX_NASIDS]; -extern nasid_t compact_to_nasid_node[MAX_COMPACT_NODES]; -extern cnodeid_t cpuid_to_compact_node[MAXCPUS]; +/* NUMA-node-as-ID to compact node ID mappings as per-cpu data */ +DECLARE_PER_CPU(nasid_t, __sn_nasid_to_cnodeid[MAX_NASIDS]); +#define sn_nasid_to_cnodeid this_cpu_ptr(&__sn_nasid_to_cnodeid[0]) -#define NASID_TO_COMPACT_NODEID(nnode) (nasid_to_compact_node[nnode]) -#define COMPACT_TO_NASID_NODEID(cnode) (compact_to_nasid_node[cnode]) -#define CPUID_TO_COMPACT_NODEID(cpu) (cpuid_to_compact_node[(cpu)]) +/* CPUID to compact node ID mappings as per-cpu data */ +DECLARE_PER_CPU(cnodeid_t, __sn_cpuid_to_cnodeid[MAXCPUS]); +#define sn_cpuid_to_cnodeid this_cpu_ptr(&__sn_cpuid_to_cnodeid[0]) #endif /* _ASM_SN_ARCH_H */ diff --git a/arch/mips/include/asm/sn/fru.h b/arch/mips/include/asm/sn/fru.h index bbb8325..b92901e 100644 --- a/arch/mips/include/asm/sn/fru.h +++ b/arch/mips/include/asm/sn/fru.h @@ -14,13 +14,11 @@ #define MAX_DIMMS 8 /* max # of dimm banks */ #define MAX_PCIDEV 8 /* max # of pci devices on a pci bus */ -typedef unsigned char confidence_t; - typedef struct kf_mem_s { - confidence_t km_confidence; /* confidence level that the memory is bad + u8 km_confidence; /* confidence level that the memory is bad * is this necessary ? */ - confidence_t km_dimm[MAX_DIMMS]; + u8 km_dimm[MAX_DIMMS]; /* confidence level that dimm[i] is bad *I think this is the right number */ @@ -28,16 +26,16 @@ typedef struct kf_mem_s { } kf_mem_t; typedef struct kf_cpu_s { - confidence_t kc_confidence; /* confidence level that cpu is bad */ - confidence_t kc_icache; /* confidence level that instr. cache is bad */ - confidence_t kc_dcache; /* confidence level that data cache is bad */ - confidence_t kc_scache; /* confidence level that sec. cache is bad */ - confidence_t kc_sysbus; /* confidence level that sysad/cmd/state bus is bad */ + u8 kc_confidence; /* confidence level that cpu is bad */ + u8 kc_icache; /* confidence level that instr. cache is bad */ + u8 kc_dcache; /* confidence level that data cache is bad */ + u8 kc_scache; /* confidence level that sec. cache is bad */ + u8 kc_sysbus; /* confidence level that sysad/cmd/state bus is bad */ } kf_cpu_t; typedef struct kf_pci_bus_s { - confidence_t kpb_belief; /* confidence level that the pci bus is bad */ - confidence_t kpb_pcidev_belief[MAX_PCIDEV]; + u8 kpb_belief; /* confidence level that the pci bus is bad */ + u8 kpb_pcidev_belief[MAX_PCIDEV]; /* confidence level that the pci dev is bad */ } kf_pci_bus_t; diff --git a/arch/mips/include/asm/sn/gda.h b/arch/mips/include/asm/sn/gda.h index 85fa1b5..852d48c 100644 --- a/arch/mips/include/asm/sn/gda.h +++ b/arch/mips/include/asm/sn/gda.h @@ -65,7 +65,7 @@ typedef struct gda { */ } gda_t; -#define GDA ((gda_t*) GDA_ADDR(get_nasid())) +#define GDA ((gda_t*) GDA_ADDR(ip27_get_nasid())) #endif /* !__ASSEMBLY__ */ /* diff --git a/arch/mips/include/asm/sn/hub.h b/arch/mips/include/asm/sn/hub.h index 1992d92..c4e33fa 100644 --- a/arch/mips/include/asm/sn/hub.h +++ b/arch/mips/include/asm/sn/hub.h @@ -11,6 +11,6 @@ /* ip27-hubio.c */ extern unsigned long hub_pio_map(cnodeid_t cnode, xwidgetnum_t widget, unsigned long xtalk_addr, size_t size); -extern void hub_pio_init(cnodeid_t cnode); +extern void __init ip27_hub_pio_init(cnodeid_t cnode); #endif /* __ASM_SN_HUB_H */ diff --git a/arch/mips/include/asm/sn/klconfig.h b/arch/mips/include/asm/sn/klconfig.h index 467c313..107a36f 100644 --- a/arch/mips/include/asm/sn/klconfig.h +++ b/arch/mips/include/asm/sn/klconfig.h @@ -11,210 +11,28 @@ #ifndef _ASM_SN_KLCONFIG_H #define _ASM_SN_KLCONFIG_H -/* - * The KLCONFIG structures store info about the various BOARDs found - * during Hardware Discovery. In addition, it stores info about the - * components found on the BOARDs. - */ - -/* - * WARNING: - * Certain assembly language routines (notably xxxxx.s) in the IP27PROM - * will depend on the format of the data structures in this file. In - * most cases, rearranging the fields can seriously break things. - * Adding fields in the beginning or middle can also break things. - * Add fields if necessary, to the end of a struct in such a way - * that offsets of existing fields do not change. - */ - #include #include #if defined(CONFIG_SGI_IP27) - #include -//#include -// XXX Stolen from : -#define MAX_ROUTER_PORTS (6) /* Max. number of ports on a router */ #include -//#include -//#include - -#elif defined(CONFIG_SGI_IP35) - -#include -#include -#include -#include +/* CONFIG_SGI_IP35 bits will go here in the future. */ +#endif /* CONFIG_SGI_IP27 */ -#endif /* !CONFIG_SGI_IP27 && !CONFIG_SGI_IP35 */ - -#if defined(CONFIG_SGI_IP27) || defined(CONFIG_SGI_IP35) +#if defined(CONFIG_SGI_IP27) /* || defined(CONFIG_SGI_IP35) */ #include #include #include -#if defined(CONFIG_SGI_IP35) -// The hack file has to be before vector and after sn0_fru.... -#include -#include -#include -#endif /* CONFIG_SGI_IP35 */ -#endif /* CONFIG_SGI_IP27 || CONFIG_SGI_IP35 */ - -typedef u64 nic_t; - -#define KLCFGINFO_MAGIC 0xbeedbabe +/* CONFIG_SGI_IP35 bits will go here in the future. */ +#endif /* CONFIG_SGI_IP27 */ -typedef s32 klconf_off_t; - -/* - * Some IMPORTANT OFFSETS. These are the offsets on all NODES. - */ -#define MAX_MODULE_ID 255 -#define SIZE_PAD 4096 /* 4k padding for structures */ -/* - * 1 NODE brd, 2 Router brd (1 8p, 1 meta), 6 Widgets, - * 2 Midplanes assuming no pci card cages - */ -#define MAX_SLOTS_PER_NODE (1 + 2 + 6 + 2) - -/* XXX if each node is guaranteed to have some memory */ - -#define MAX_PCI_DEVS 8 - -/* lboard_t->brd_flags fields */ -/* All bits in this field are currently used. Try the pad fields if - you need more flag bits */ - -#define ENABLE_BOARD 0x01 -#define FAILED_BOARD 0x02 -#define DUPLICATE_BOARD 0x04 /* Boards like midplanes/routers which - are discovered twice. Use one of them */ -#define VISITED_BOARD 0x08 /* Used for compact hub numbering. */ -#define LOCAL_MASTER_IO6 0x10 /* master io6 for that node */ -#define GLOBAL_MASTER_IO6 0x20 -#define THIRD_NIC_PRESENT 0x40 /* for future use */ -#define SECOND_NIC_PRESENT 0x80 /* addons like MIO are present */ - -/* klinfo->flags fields */ - -#define KLINFO_ENABLE 0x01 /* This component is enabled */ -#define KLINFO_FAILED 0x02 /* This component failed */ -#define KLINFO_DEVICE 0x04 /* This component is a device */ -#define KLINFO_VISITED 0x08 /* This component has been visited */ -#define KLINFO_CONTROLLER 0x10 /* This component is a device controller */ -#define KLINFO_INSTALL 0x20 /* Install a driver */ -#define KLINFO_HEADLESS 0x40 /* Headless (or hubless) component */ -#define IS_CONSOLE_IOC3(i) ((((klinfo_t *)i)->flags) & KLINFO_INSTALL) - -#define GB2 0x80000000 - -#define MAX_RSV_PTRS 32 - -/* Structures to manage various data storage areas */ -/* The numbers must be contiguous since the array index i - is used in the code to allocate various areas. -*/ - -#define BOARD_STRUCT 0 -#define COMPONENT_STRUCT 1 -#define ERRINFO_STRUCT 2 -#define KLMALLOC_TYPE_MAX (ERRINFO_STRUCT + 1) -#define DEVICE_STRUCT 3 - - -typedef struct console_s { - unsigned long uart_base; - unsigned long config_base; - unsigned long memory_base; - short baud; - short flag; - int type; - nasid_t nasid; - char wid; - char npci; - nic_t baseio_nic; -} console_t; - -typedef struct klc_malloc_hdr { - klconf_off_t km_base; - klconf_off_t km_limit; - klconf_off_t km_current; -} klc_malloc_hdr_t; - -/* Functions/macros needed to use this structure */ - -typedef struct kl_config_hdr { - u64 ch_magic; /* set this to KLCFGINFO_MAGIC */ - u32 ch_version; /* structure version number */ - klconf_off_t ch_malloc_hdr_off; /* offset of ch_malloc_hdr */ - klconf_off_t ch_cons_off; /* offset of ch_cons */ - klconf_off_t ch_board_info; /* the link list of boards */ - console_t ch_cons_info; /* address info of the console */ - klc_malloc_hdr_t ch_malloc_hdr[KLMALLOC_TYPE_MAX]; - confidence_t ch_sw_belief; /* confidence that software is bad*/ - confidence_t ch_sn0net_belief; /* confidence that sn0net is bad */ -} kl_config_hdr_t; - - -#define KL_CONFIG_HDR(_nasid) ((kl_config_hdr_t *)(KLCONFIG_ADDR(_nasid))) -#define KL_CONFIG_INFO_OFFSET(_nasid) \ - (KL_CONFIG_HDR(_nasid)->ch_board_info) -#define KL_CONFIG_INFO_SET_OFFSET(_nasid, _off) \ - (KL_CONFIG_HDR(_nasid)->ch_board_info = (_off)) - -#define KL_CONFIG_INFO(_nasid) \ - (lboard_t *)((KL_CONFIG_HDR(_nasid)->ch_board_info) ? \ - NODE_OFFSET_TO_K1((_nasid), KL_CONFIG_HDR(_nasid)->ch_board_info) : \ - 0) -#define KL_CONFIG_MAGIC(_nasid) (KL_CONFIG_HDR(_nasid)->ch_magic) - -#define KL_CONFIG_CHECK_MAGIC(_nasid) \ - (KL_CONFIG_HDR(_nasid)->ch_magic == KLCFGINFO_MAGIC) - -#define KL_CONFIG_HDR_INIT_MAGIC(_nasid) \ - (KL_CONFIG_HDR(_nasid)->ch_magic = KLCFGINFO_MAGIC) - -/* --- New Macros for the changed kl_config_hdr_t structure --- */ - -#define PTR_CH_MALLOC_HDR(_k) ((klc_malloc_hdr_t *)\ - ((unsigned long)_k + (_k->ch_malloc_hdr_off))) - -#define KL_CONFIG_CH_MALLOC_HDR(_n) PTR_CH_MALLOC_HDR(KL_CONFIG_HDR(_n)) - -#define PTR_CH_CONS_INFO(_k) ((console_t *)\ - ((unsigned long)_k + (_k->ch_cons_off))) - -#define KL_CONFIG_CH_CONS_INFO(_n) PTR_CH_CONS_INFO(KL_CONFIG_HDR(_n)) - -/* ------------------------------------------------------------- */ - -#define KL_CONFIG_INFO_START(_nasid) \ - (klconf_off_t)(KLCONFIG_OFFSET(_nasid) + sizeof(kl_config_hdr_t)) - -#define KL_CONFIG_BOARD_NASID(_brd) ((_brd)->brd_nasid) -#define KL_CONFIG_BOARD_SET_NEXT(_brd, _off) ((_brd)->brd_next = (_off)) - -#define KL_CONFIG_DUPLICATE_BOARD(_brd) ((_brd)->brd_flags & DUPLICATE_BOARD) - -#define XBOW_PORT_TYPE_HUB(_xbowp, _link) \ - ((_xbowp)->xbow_port_info[(_link) - BASE_XBOW_PORT].port_flag & XBOW_PORT_HUB) -#define XBOW_PORT_TYPE_IO(_xbowp, _link) \ - ((_xbowp)->xbow_port_info[(_link) - BASE_XBOW_PORT].port_flag & XBOW_PORT_IO) - -#define XBOW_PORT_IS_ENABLED(_xbowp, _link) \ - ((_xbowp)->xbow_port_info[(_link) - BASE_XBOW_PORT].port_flag & XBOW_PORT_ENABLE) -#define XBOW_PORT_NASID(_xbowp, _link) \ - ((_xbowp)->xbow_port_info[(_link) - BASE_XBOW_PORT].port_nasid) - -#define XBOW_PORT_IO 0x1 -#define XBOW_PORT_HUB 0x2 -#define XBOW_PORT_ENABLE 0x4 - -#define SN0_PORT_FENCE_SHFT 0 -#define SN0_PORT_FENCE_MASK (1 << SN0_PORT_FENCE_SHFT) /* + * The KLCONFIG structures store info about the various BOARDs found + * during Hardware Discovery. In addition, it stores info about the + * components found on the BOARDs. + * * The KLCONFIG area is organized as a LINKED LIST of BOARDs. A BOARD * can be either 'LOCAL' or 'REMOTE'. LOCAL means it is attached to * the LOCAL/current NODE. REMOTE means it is attached to a different @@ -240,31 +58,31 @@ typedef struct kl_config_hdr { * the local base address and ignoring all rboard values. * * - KLCONFIG - - +------------+ +------------+ +------------+ +------------+ - | lboard | +-->| lboard | +-->| rboard | +-->| lboard | - +------------+ | +------------+ | +------------+ | +------------+ - | board info | | | board info | | |errinfo,bptr| | | board info | - +------------+ | +------------+ | +------------+ | +------------+ - | offset |--+ | offset |--+ | offset |--+ |offset=NULL | - +------------+ +------------+ +------------+ +------------+ - - - +------------+ - | board info | - +------------+ +--------------------------------+ - | compt 1 |------>| type, rev, diaginfo, size ... | (CPU) - +------------+ +--------------------------------+ - | compt 2 |--+ - +------------+ | +--------------------------------+ - | ... | +--->| type, rev, diaginfo, size ... | (MEM_BANK) - +------------+ +--------------------------------+ - | errinfo |--+ - +------------+ | +--------------------------------+ - +--->|r/l brd errinfo,compt err flags | - +--------------------------------+ - + * KLCONFIG + * + * +------------+ +------------+ +------------+ +------------+ + * | lboard | +-->| lboard | +-->| rboard | +-->| lboard | + * +------------+ | +------------+ | +------------+ | +------------+ + * | board info | | | board info | | |errinfo,bptr| | | board info | + * +------------+ | +------------+ | +------------+ | +------------+ + * | offset |--+ | offset |--+ | offset |--+ |offset=NULL | + * +------------+ +------------+ +------------+ +------------+ + * + * + * +------------+ + * | board info | + * +------------+ +--------------------------------+ + * | comp 1 |------>| type, rev, diaginfo, size ... | (CPU) + * +------------+ +--------------------------------+ + * | comp 2 |--+ + * +------------+ | +--------------------------------+ + * | ... | +--->| type, rev, diaginfo, size ... | (MEM_BANK) + * +------------+ +--------------------------------+ + * | errinfo |--+ + * +------------+ | +--------------------------------+ + * +--->|r/l brd errinfo,compt err flags | + * +--------------------------------+ + * * * Each BOARD consists of COMPONENTs and the BOARD structure has * pointers (offsets) to its COMPONENT structure. @@ -292,11 +110,12 @@ typedef struct kl_config_hdr { * using the rboard errinfo pointer. * * In order to get useful information from this Data organization, a set of - * interface routines are provided (TBD). The important thing to remember while - * manipulating the structures, is that, the NODE number information should - * be used. If the NODE is non-zero (remote) then each offset should - * be added to the REMOTE BASE ADDR else it should be added to the LOCAL BASE ADDR. - * This includes offsets for BOARDS, COMPONENTS and ERRORINFO. + * interface routines are provided (TBD). The important thing to remember + * while manipulating the structures, is that, the NODE number information + * should be used. If the NODE is non-zero (remote) then each offset should + * be added to the REMOTE_BASE_ADDR else it should be added to the + * LOCAL_BASE_ADDR. This includes offsets for BOARDS, COMPONENTS and + * ERRORINFO. * * Note that these structures do not provide much info about connectivity. * That info will be part of HWGRAPH, which is an extension of the cfg_t @@ -304,595 +123,1100 @@ typedef struct kl_config_hdr { * the IO part of the Network(TBD). * * The data structures below define the above concepts. + * + * XXX: Missing definition for struct klc_rboard! */ /* - * Values for CPU types + * XXX: Linux note: The below warning is apparently a relic from IRIX. + * + * WARNING: + * Certain assembly language routines (notably xxxxx.s) in the IP27PROM + * will depend on the format of the data structures in this file. In + * most cases, rearranging the fields can seriously break things. + * Adding fields in the beginning or middle can also break things. + * Add fields if necessary, to the end of a struct in such a way + * that offsets of existing fields do not change. */ -#define KL_CPU_R4000 0x1 /* Standard R4000 */ -#define KL_CPU_TFP 0x2 /* TFP processor */ -#define KL_CPU_R10000 0x3 /* R10000 (T5) */ -#define KL_CPU_NONE (-1) /* no cpu present in slot */ + + +/* XXX: Linux note: The below defines aren't used anywhere. Keep? */ +#define MAX_MODULE_ID 255 +#define SIZE_PAD 4096 /* 4k padding for structures */ +#define GB2 0x80000000 +#define MAX_RSV_PTRS 32 +#define SN0_PORT_FENCE_SHFT 0 +#define SN0_PORT_FENCE_MASK (1 << SN0_PORT_FENCE_SHFT) /* - * IP27 BOARD classes + * 1 NODE brd, 2 Router brd (1 8p, 1 meta), 6 Widgets, + * 2 Midplanes assuming no pci card cages */ +#define MAX_SLOTS_PER_NODE (1 + 2 + 6 + 2) -#define KLCLASS_MASK 0xf0 -#define KLCLASS_NONE 0x00 -#define KLCLASS_NODE 0x10 /* CPU, Memory and HUB board */ -#define KLCLASS_CPU KLCLASS_NODE -#define KLCLASS_IO 0x20 /* BaseIO, 4 ch SCSI, ethernet, FDDI - and the non-graphics widget boards */ -#define KLCLASS_ROUTER 0x30 /* Router board */ -#define KLCLASS_MIDPLANE 0x40 /* We need to treat this as a board - so that we can record error info */ -#define KLCLASS_GFX 0x50 /* graphics boards */ +/* ----------------------------------------------------------------------- */ +/* struct klc_* casting wrappers - Add more as needed */ -#define KLCLASS_PSEUDO_GFX 0x60 /* HDTV type cards that use a gfx - * hw ifc to xtalk and are not gfx - * class for sw purposes */ +/* + * Common parameter conventions for macros: + * _b: BOARD or MEMBANK + * _c: Component + * _i: struct klc_info passed by value + * _k: Refers to either K0 or K1 MIPS memory area + * _n: NASID + * _o: Offset + * _t: Type + * _x: XBOW + */ -#define KLCLASS_MAX 7 /* Bump this if a new CLASS is added */ -#define KLTYPE_MAX 10 /* Bump this if a new CLASS is added */ +#define KLCF_CAST(_t) (struct klc_##_t *) +#define KLCF_CAST_CONS(_t) (KLCF_CAST(cons)(_t)) /* klc_cons */ +#define KLCF_CAST_MALLOC(_t) (KLCF_CAST(malloc)(_t)) /* klc_malloc */ +#define KLCF_CAST_HEADER(_t) (KLCF_CAST(header)(_t)) /* klc_header */ +#define KLCF_CAST_INFO(_t) (KLCF_CAST(info)(_t)) /* klc_info */ +#define KLCF_CAST_LBOARD(_t) (KLCF_CAST(lboard)(_t)) /* klc_lboard */ +#define KLCF_CAST_ROUTER(_t) (KLCF_CAST(router)(_t)) /* klc_router */ +#define KLCF_CAST_CPU(_t) (KLCF_CAST(cpu)(_t)) /* klc_cpu */ +#define KLCF_CAST_HUB(_t) (KLCF_CAST(hub)(_t)) /* klc_hub */ +#define KLCF_CAST_MEMBANK(_t) (KLCF_CAST(membank)(_t)) /* klc_membank */ +#define KLCF_CAST_MOD_SN(_t) (KLCF_CAST(mod_sn)(_t)) /* klc_mod_sn */ +#define KLCF_CAST_XBOW(_t) (KLCF_CAST(xbow)(_t)) /* klc_xbow */ -#define KLCLASS_UNKNOWN 0xf0 -#define KLCLASS(_x) ((_x) & KLCLASS_MASK) +/* ----------------------------------------------------------------------- */ +/* struct klc_cons, struct klc_malloc, and struct klc_header */ /* - * IP27 board types - */ - -#define KLTYPE_MASK 0x0f -#define KLTYPE_NONE 0x00 -#define KLTYPE_EMPTY 0x00 - -#define KLTYPE_WEIRDCPU (KLCLASS_CPU | 0x0) -#define KLTYPE_IP27 (KLCLASS_CPU | 0x1) /* 2 CPUs(R10K) per board */ - -#define KLTYPE_WEIRDIO (KLCLASS_IO | 0x0) -#define KLTYPE_BASEIO (KLCLASS_IO | 0x1) /* IOC3, SuperIO, Bridge, SCSI */ -#define KLTYPE_IO6 KLTYPE_BASEIO /* Additional name */ -#define KLTYPE_4CHSCSI (KLCLASS_IO | 0x2) -#define KLTYPE_MSCSI KLTYPE_4CHSCSI /* Additional name */ -#define KLTYPE_ETHERNET (KLCLASS_IO | 0x3) -#define KLTYPE_MENET KLTYPE_ETHERNET /* Additional name */ -#define KLTYPE_FDDI (KLCLASS_IO | 0x4) -#define KLTYPE_UNUSED (KLCLASS_IO | 0x5) /* XXX UNUSED */ -#define KLTYPE_HAROLD (KLCLASS_IO | 0x6) /* PCI SHOE BOX */ -#define KLTYPE_PCI KLTYPE_HAROLD -#define KLTYPE_VME (KLCLASS_IO | 0x7) /* Any 3rd party VME card */ -#define KLTYPE_MIO (KLCLASS_IO | 0x8) -#define KLTYPE_FC (KLCLASS_IO | 0x9) -#define KLTYPE_LINC (KLCLASS_IO | 0xA) -#define KLTYPE_TPU (KLCLASS_IO | 0xB) /* Tensor Processing Unit */ -#define KLTYPE_GSN_A (KLCLASS_IO | 0xC) /* Main GSN board */ -#define KLTYPE_GSN_B (KLCLASS_IO | 0xD) /* Auxiliary GSN board */ - -#define KLTYPE_GFX (KLCLASS_GFX | 0x0) /* unknown graphics type */ -#define KLTYPE_GFX_KONA (KLCLASS_GFX | 0x1) /* KONA graphics on IP27 */ -#define KLTYPE_GFX_MGRA (KLCLASS_GFX | 0x3) /* MGRAS graphics on IP27 */ - -#define KLTYPE_WEIRDROUTER (KLCLASS_ROUTER | 0x0) -#define KLTYPE_ROUTER (KLCLASS_ROUTER | 0x1) -#define KLTYPE_ROUTER2 KLTYPE_ROUTER /* Obsolete! */ -#define KLTYPE_NULL_ROUTER (KLCLASS_ROUTER | 0x2) -#define KLTYPE_META_ROUTER (KLCLASS_ROUTER | 0x3) - -#define KLTYPE_WEIRDMIDPLANE (KLCLASS_MIDPLANE | 0x0) -#define KLTYPE_MIDPLANE8 (KLCLASS_MIDPLANE | 0x1) /* 8 slot backplane */ -#define KLTYPE_MIDPLANE KLTYPE_MIDPLANE8 -#define KLTYPE_PBRICK_XBOW (KLCLASS_MIDPLANE | 0x2) - -#define KLTYPE_IOBRICK (KLCLASS_IOBRICK | 0x0) -#define KLTYPE_IBRICK (KLCLASS_IOBRICK | 0x1) -#define KLTYPE_PBRICK (KLCLASS_IOBRICK | 0x2) -#define KLTYPE_XBRICK (KLCLASS_IOBRICK | 0x3) + * The numbers must be contiguous since the array index i is used in the code + * to allocate the various areas. + */ +#define BOARD_STRUCT 0 +#define COMPONENT_STRUCT 1 +#define ERRINFO_STRUCT 2 +#define KLMALLOC_TYPE_MAX (ERRINFO_STRUCT + 1) +#define DEVICE_STRUCT 3 -#define KLTYPE_PBRICK_BRIDGE KLTYPE_PBRICK +/** + * struct klc_cons - KLCONFIG main console + * @uart_base: base addr of UART + * @config_base: base addr of UART config + * @memory_base: base addr of UART mem + * @baud: Baud rate + * @flag: UART flags + * @type: UART type + * @nasid: NASID of node + * @wid: Widget ID + * @npci: ? + * @baseio_nic: BaseIO Number + */ +struct klc_cons { + unsigned long uart_base; + unsigned long config_base; + unsigned long memory_base; + s16 baud; + s16 flag; + int type; + nasid_t nasid; + s8 wid; + s8 npci; + u64 baseio_nic; +}; + +/** + * struct klc_malloc - KLCONFIG main console + * @base: ? + * @limit: ? + * @curr: ? + */ +struct klc_malloc { + s32 base; + s32 limit; + s32 curr; +}; + +/* KLCONFIG Header */ +#define KLCONFIG_MAGIC 0xbeedbabe + +/** + * struct klc_header - KLCONFIG main console + * @magic: set to KLCONFIG_MAGIC + * @version: STRUCTURE VERSION + * @malloc_hdr_off: offset to klc_malloc + * @cons_off: offset to klc_cons + * @board_info: beginning of linked list of boards + * @cons_info: console info as struct klc_cons + * @malloc_hdr: + * @sw_belief: confidence that software is bad + * @sn0net_belief: confidence that sn0net is bad + */ +struct klc_header { + u64 magic; + u32 version; + s32 malloc_hdr_off; + s32 cons_off; + s32 board_info; + struct klc_cons cons_info; + struct klc_malloc malloc_hdr[KLMALLOC_TYPE_MAX]; + u8 sw_belief; + u8 sn0net_belief; +}; + +/* Gets a pointer to the start of the KLCONFIG data area. */ +#define KL_CONFIG_HDR(_n) (KLCF_CAST_HEADER(KLCONFIG_ADDR(_n))) + +/* Gets a pointer to the start of the linked list of boards. */ +#define KL_CONFIG_BRD_INFO_OFF(_n) \ + (KL_CONFIG_HDR(_n)->board_info) + +/* Get the KLCONFIG magic value. */ +#define KL_CONFIG_MAGIC(_n) (KL_CONFIG_HDR(_n)->magic) + +/* Check the KLCONFIG magic value against KLCFGINFO_MAGIC. */ +#define KL_CONFIG_CHECK_MAGIC(_n) \ + (KL_CONFIG_MAGIC(_n) == KLCFGINFO_MAGIC) + +/* Initialize the KLCONFIG magic value. */ +#define KL_CONFIG_HDR_INIT_MAGIC(_n) \ + (KL_CONFIG_MAGIC(_n) = KLCFGINFO_MAGIC) + +/* Pointer macro to struct klc_header->cons_info */ +#define PTR_CONS_INFO(_k) \ + (KLCF_CAST_CONS((unsigned long)_k + (_k->cons_off))) + +/* Returns struct klc_cons from struct klc_header->cons_info */ +#define KL_CONFIG_CONS_INFO(_n) \ + PTR_CONS_INFO(KL_CONFIG_HDR(_n)) + +/* Pointer macro to struct klc_header->malloc_hdr_off */ +#define PTR_MALLOC_HDR(_k) \ + (KLCF_CAST_MALLOC((unsigned long)_k + (_k->malloc_hdr_off))) + +/* Returns struct klc_malloc from struct klc_header->malloc_hdr_off */ +#define KL_CONFIG_MALLOC_HDR(_n) \ + PTR_MALLOC_HDR(KL_CONFIG_HDR(_n)) + +/* Points at the first struct klc_info area (?) */ +#define KL_CONFIG_INFO_START(_n) \ + (s32)(KLCONFIG_OFFSET(_n) + sizeof(struct klc_header)) + + +/* ----------------------------------------------------------------------- */ +/* struct klc_info */ + +/** + * struct klc_info - stores common info about a component + * @struct_type: type of this structure + * @struct_version: ver of this structure + * @flags: enabled/disabled state, etc + * @revision: component revision + * @diag_val: diagnostic value + * @diag_parm: diagnostic param + * @inventory: prev inventory status + * @nic: must be aligned properly + * @physid: physical id of component + * @virtid: virtual id as seen by system + * @widid: widget id (if applicable) + * @nasid: node number (from parent) + * @_pad0: padding + * @arcs_compt: ptr to the ARCS struct for ease + * @errinfo: component specific errors + * @_pad1: padding + */ +struct klc_info { + u8 struct_type; + u8 struct_version; + u8 flags; + u8 revision; + u16 diag_val; + u16 diag_parm; + u8 inventory; + u64 nic; + u8 physid; + u32 virtid; + u8 widid; + nasid_t nasid; + u16 _pad0; + COMPONENT *arcs_compt; + s32 errinfo; + u32 _pad1; +}; + +/* struct klc_info->flags definitions */ +#define KLINFO_ENABLE 0x01 /* Component is enabled */ +#define KLINFO_FAILED 0x02 /* Component failed */ +#define KLINFO_DEVICE 0x04 /* Component is a device */ +#define KLINFO_VISITED 0x08 /* Component has been visited */ +#define KLINFO_CONTROLLER 0x10 /* Component is a device controller */ +#define KLINFO_INSTALL 0x20 /* Install a driver */ +#define KLINFO_HEADLESS 0x40 /* Headless (or hubless) component */ -/* The value of type should be more than 8 so that hinv prints - * out the board name from the NIC string. For values less than - * 8 the name of the board needs to be hard coded in a few places. - * When bringup started nic names had not standardized and so we - * had to hard code. (For people interested in history.) +#define IS_CONSOLE_IOC3(i) ((KLCF_CAST_INFO(i)->flags) & KLINFO_INSTALL) + +/* Wrapper to get the NUMA-as-node-ID from a board */ +#define KLCF_BOARD_NASID(_b) ((_b)->nasid) + +/* Wrapper to get the next board in the linked list */ +#define KLCF_BOARD_NEXT(_b) ((_b)->next) + +/* Wrapper to check the board flags for a duplicate board */ +#define KL_CONFIG_DUPLICATE_BOARD(_b) \ + ((_b)->flags & DUPLICATE_BOARD) + +/* Test whether a board is local or remote */ +#define KLCF_REMOTE(_b) (((_b)->struct_type & KLBOARD_LOCAL) ? 0 : 1) + +/* Test if a board is enabled - pass by value, not reference */ +#define KLCF_INFO_ENABLED(_i) ((_i).flags & KLINFO_ENABLE) + +/* ----------------------------------------------------------------------- */ +/* struct klc_lboard */ + +#define MAX_COMPONENTS 24 /* Max components per board */ +#define KLBOARD_LOCAL 0x1 /* Board is local to node */ +#define KLBOARD_REMOTE 0x2 /* Board is on another node */ + +/** + * struct klc_info - stores info about a local BOARD + * @next: next BOARD + * @struct_type: type of struct, local or remote + * @type: board type + class + * @struct_ver: structure version + * @rev: board revision + * @prom_ver: board prom version, if any + * @flags: board flags + * @slot: board slot num + * @debug_switch: debug switches + * @module: module to which board belongs + * @partition: partition number + * @diag_val: diag value + * @diag_parm: diag param + * @inventory: inventory history + * @num_components: num of components + * @nic: Number-in-a-Can (NIC) + * @nasid: NUMA-node-AS-ID + * @components: board components + * @err_info: board's error information + * @parent: logical parent for this board + * @graph_link: vertex handle for external components + * @confidence: belief that board is bad + * @owner: who owns this board + * @nic_flags: to handle 8 more NICs + * @name: static string for board name */ -#define KLTYPE_XTHD (KLCLASS_PSEUDO_GFX | 0x9) +struct klc_lboard { + s32 next; + u8 struct_type; + u8 type; + u8 struct_ver; + u8 rev; + u8 prom_ver; + u8 flags; + u8 slot; + u16 debug_switch; + moduleid_t module; + partid_t partition; + u16 diag_val; + u16 diag_parm; + u8 inventory; + u8 num_components; + u64 nic; + nasid_t nasid; + s32 components[MAX_COMPONENTS]; + s32 err_info; + struct klc_lboard *parent; + dev_t graph_link; + u8 confidence; + nasid_t owner; + u8 nic_flags; + s8 name[32]; +}; -#define KLTYPE_UNKNOWN (KLCLASS_UNKNOWN | 0xf) +/* + * struct klc_lboard->flags fields + * + * All bits in this field are currently used. Try the __padX fields if + * additional flag bits are needed + */ +#define ENABLE_BOARD 0x01 +#define FAILED_BOARD 0x02 +#define DUPLICATE_BOARD 0x04 /* Boards like midplanes/routers which + are discovered twice. Use only 1 */ +#define VISITED_BOARD 0x08 /* Used for compact hub numbering. */ +#define LOCAL_MASTER_IO6 0x10 /* Master IO6 for that node */ +#define GLOBAL_MASTER_IO6 0x20 /* Global IO6 for all nodes */ +#define THIRD_NIC_PRESENT 0x40 /* For the future (?) */ +#define SECOND_NIC_PRESENT 0x80 /* Add-ons like MIO are present */ + +/* These are the indices of various components within a lboard structure */ +#define IP27_CPU0_INDEX 0 +#define IP27_CPU1_INDEX 1 +#define IP27_HUB_INDEX 2 +#define IP27_MEM_INDEX 3 +#define BASEIO_BRIDGE_INDEX 0 +#define BASEIO_IOC3_INDEX 1 +#define BASEIO_SCSI0_INDEX 2 +#define BASEIO_SCSI1_INDEX 3 +#define MIDPLANE_XBOW_INDEX 0 +#define ROUTER_COMPONENT_INDEX 0 +#define CH4SCSI_BRIDGE_INDEX 0 + +/* Gets the board info from the specified node. */ +#define KL_CONFIG_INFO(_n) \ + (KLCF_CAST_LBOARD(KL_CONFIG_BRD_INFO_OFF(_n) ? \ + NODE_OFFSET_TO_K1((_n), KL_CONFIG_BRD_INFO_OFF(_n)) : 0)) + +/* Get board information */ +#define KLCF_SLOT(_b) ((_b)->slot) +#define KLCF_CLASS(_b) KLCLASS((_b)->type) +#define KLCF_TYPE(_b) KLTYPE((_b)->type) +#define KLCF_NUM_COMPS(_b) ((_b)->num_components) /* # of components */ +#define KLCF_MODULE_ID(_b) ((_b)->module) /* Module ID */ + + +/* ----------------------------------------------------------------------- */ +/* Various BOARD definition values */ + +/* Values for CPU types */ +#define KL_CPU_R4000 0x1 /* Standard R4000 */ +#define KL_CPU_TFP 0x2 /* R8000 (TFP) */ +#define KL_CPU_R10000 0x3 /* R10000 (T5) */ +#define KL_CPU_NONE (-1) /* No cpu present in slot */ + +/* IP27 BOARD Classes */ +#define KLCLASS_MASK 0xf0 +#define KLCLASS_UNKNOWN 0xf0 /* XXX: Same as KLCLASS_MASK */ +#define KLCLASS_NONE 0x00 +#define KLCLASS_NODE 0x10 /* CPU/Mem/HUB nodeboard */ +#define KLCLASS_CPU KLCLASS_NODE +#define KLCLASS_IO 0x20 /* BaseIO, 4ch SCSI, Eth, FDDI, + * & the non-graphics widget + * boards + */ +#define KLCLASS_ROUTER 0x30 /* Router board */ +#define KLCLASS_MIDPLANE 0x40 /* We need to treat this as a + * board so that we can record + * error info + */ +#define KLCLASS_GFX 0x50 /* Gfx boards (kona, mgras) */ +#define KLCLASS_PSEUDO_GFX 0x60 /* HDTV type cards that use a + * gfx hw interface to xtalk + * and are not gfx class for + * software purposes. + */ +/* Bump both of these if a new CLASS is added */ +#define KLCLASS_MAX 7 +#define KLTYPE_MAX 10 + +/* Given struct klc_lboard->type, returns the BOARD's class */ +#define KLCLASS(_x) ((_x) & KLCLASS_MASK) + + +/* IP27 BOARD Types */ +#define KLTYPE_MASK 0x0f +#define KLTYPE_NONE 0x00 +#define KLTYPE_EMPTY 0x00 +#define KLTYPE_UNKNOWN (KLCLASS_UNKNOWN | 0xf) +/* CPU */ +#define KLTYPE_WEIRDCPU (KLCLASS_CPU | 0x0) /* Unknown CPU */ +#define KLTYPE_IP27 (KLCLASS_CPU | 0x1) /* 2 CPUs/nodeboard */ +/* I/O */ +#define KLTYPE_WEIRDIO (KLCLASS_IO | 0x0) +#define KLTYPE_BASEIO (KLCLASS_IO | 0x1) /* IOC3/BRIDGE/SCSI */ +#define KLTYPE_IO6 KLTYPE_BASEIO +#define KLTYPE_4CHSCSI (KLCLASS_IO | 0x2) /* Quad SCSI Xtalk */ +#define KLTYPE_MSCSI KLTYPE_4CHSCSI +#define KLTYPE_MENET (KLCLASS_IO | 0x3) /* IOC3 Ethernet */ +#define KLTYPE_ETHERNET KLTYPE_MENET +#define KLTYPE_FDDI (KLCLASS_IO | 0x4) /* FDDI Xtalk */ +#define KLTYPE_UNUSED (KLCLASS_IO | 0x5) /* XXX: Unused */ +#define KLTYPE_PCIBOX (KLCLASS_IO | 0x6) /* PCI Shoebox */ +#define KLTYPE_HAROLD KLTYPE_PCIBOX +#define KLTYPE_VME (KLCLASS_IO | 0x7) /* VME cards */ +#define KLTYPE_MIO (KLCLASS_IO | 0x8) /* XXX: Unknown */ +#define KLTYPE_FC (KLCLASS_IO | 0x9) /* FibreChannel */ +#define KLTYPE_LINC (KLCLASS_IO | 0xa) /* LINC (HIPPI/ATM) */ +#define KLTYPE_TPU (KLCLASS_IO | 0xb) /* Tensor Processor */ +#define KLTYPE_GSN_A (KLCLASS_IO | 0xc) /* Main GSN board */ +#define KLTYPE_GSN_B (KLCLASS_IO | 0xd) /* Aux GSN board */ +/* GFX */ +#define KLTYPE_GFX (KLCLASS_GFX | 0x0) /* Unknown Gfx type */ +#define KLTYPE_GFX_KONA (KLCLASS_GFX | 0x1) /* InfiniteReality */ +#define KLTYPE_GFX_MGRA (KLCLASS_GFX | 0x3) /* MGRAS/Impact Gfx */ +#define KLTYPE_HDTV (KLCLASS_PSEUDO_GFX | 0x9) /* HDTV board */ +/* Routers */ +#define KLTYPE_WEIRDROUTER (KLCLASS_ROUTER | 0x0) /* Unknown router */ +#define KLTYPE_ROUTER (KLCLASS_ROUTER | 0x1) /* Std router */ +#define KLTYPE_NULL_ROUTER (KLCLASS_ROUTER | 0x2) /* Null Router */ +#define KLTYPE_META_ROUTER (KLCLASS_ROUTER | 0x3) /* Metarouter */ +/* Midplanes */ +#define KLTYPE_WEIRDMIDPLANE (KLCLASS_MIDPLANE | 0x0)/* Unknown Midplane */ +#define KLTYPE_MIDPLANE (KLCLASS_MIDPLANE | 0x1)/* 8 slot backplane */ +#define KLTYPE_PBRICK_XBOW (KLCLASS_MIDPLANE | 0x2)/* IP35 P-BRICK Xbow */ +/* IP35 BRICKs */ +#define KLTYPE_IOBRICK (KLCLASS_IOBRICK | 0x0) /* IP35 Basic I/O */ +#define KLTYPE_IBRICK (KLCLASS_IOBRICK | 0x1) +#define KLTYPE_PBRICK (KLCLASS_IOBRICK | 0x2) /* IP35 PCI */ +#define KLTYPE_XBRICK (KLCLASS_IOBRICK | 0x3) /* IP35 XIO */ +#define KLTYPE_PBRICK_BRIDGE KLTYPE_PBRICK -#define KLTYPE(_x) ((_x) & KLTYPE_MASK) -#define IS_MIO_PRESENT(l) ((l->brd_type == KLTYPE_BASEIO) && \ - (l->brd_flags & SECOND_NIC_PRESENT)) -#define IS_MIO_IOC3(l, n) (IS_MIO_PRESENT(l) && (n > 2)) +/* Given struct klc_lboard->type, returns the BOARD's type */ +#define KLTYPE(_t) ((_t) & KLTYPE_MASK) /* - * board structures - */ - -#define MAX_COMPTS_PER_BRD 24 - -#define LOCAL_BOARD 1 -#define REMOTE_BOARD 2 - -#define LBOARD_STRUCT_VERSION 2 - -typedef struct lboard_s { - klconf_off_t brd_next; /* Next BOARD */ - unsigned char struct_type; /* type of structure, local or remote */ - unsigned char brd_type; /* type+class */ - unsigned char brd_sversion; /* version of this structure */ - unsigned char brd_brevision; /* board revision */ - unsigned char brd_promver; /* board prom version, if any */ - unsigned char brd_flags; /* Enabled, Disabled etc */ - unsigned char brd_slot; /* slot number */ - unsigned short brd_debugsw; /* Debug switches */ - moduleid_t brd_module; /* module to which it belongs */ - partid_t brd_partition; /* Partition number */ - unsigned short brd_diagval; /* diagnostic value */ - unsigned short brd_diagparm; /* diagnostic parameter */ - unsigned char brd_inventory; /* inventory history */ - unsigned char brd_numcompts; /* Number of components */ - nic_t brd_nic; /* Number in CAN */ - nasid_t brd_nasid; /* passed parameter */ - klconf_off_t brd_compts[MAX_COMPTS_PER_BRD]; /* pointers to COMPONENTS */ - klconf_off_t brd_errinfo; /* Board's error information */ - struct lboard_s *brd_parent; /* Logical parent for this brd */ - vertex_hdl_t brd_graph_link; /* vertex hdl to connect extern compts */ - confidence_t brd_confidence; /* confidence that the board is bad */ - nasid_t brd_owner; /* who owns this board */ - unsigned char brd_nic_flags; /* To handle 8 more NICs */ - char brd_name[32]; -} lboard_t; + * Linux note: The below is apocryphal information. No idea where it belongs. + * + * The value of type should be more than 8 so that hinv prints out the board + * name from the NIC string. For values less than 8 the name of the board + * needs to be hard coded in a few places. When bringup started NIC names + * had not been standardized and so we had to hard code. (For people + * interested in history.) + */ + +/* ----------------------------------------------------------------------- */ +/* Various Component definitions */ /* - * Make sure we pass back the calias space address for local boards. - * klconfig board traversal and error structure extraction defines. + * Following are the currently identified components: + * - CPU, HUB, MEM_BANK, + * - XBOW (consists of 16 WIDGETs, each of which can be HUB/GFX/BRIDGE), + * - BRIDGE, IOC3, SuperIO, SCSI, FDDI, + * - ROUTER, + * - GRAPHICS, */ +#define KLSTRUCT_UNKNOWN 0 +#define KLSTRUCT_CPU 1 +#define KLSTRUCT_HUB 2 +#define KLSTRUCT_MEMBNK 3 +#define KLSTRUCT_XBOW 4 +#define KLSTRUCT_BRI 5 +#define KLSTRUCT_IOC3 6 +#define KLSTRUCT_PCI 7 +#define KLSTRUCT_VME 8 +#define KLSTRUCT_ROU 9 +#define KLSTRUCT_GFX 10 +#define KLSTRUCT_SCSI 11 +#define KLSTRUCT_FDDI 12 +#define KLSTRUCT_MIO 13 +#define KLSTRUCT_DISK 14 +#define KLSTRUCT_TAPE 15 +#define KLSTRUCT_CDROM 16 +#define KLSTRUCT_HUB_UART 17 +#define KLSTRUCT_IOC3ENET 18 +#define KLSTRUCT_IOC3UART 19 +#define KLSTRUCT_UNUSED 20 /* XXX: UNUSED */ +#define KLSTRUCT_IOC3PCKM 21 +#define KLSTRUCT_RAD 22 +#define KLSTRUCT_HUB_TTY 23 +#define KLSTRUCT_IOC3_TTY 24 -#define BOARD_SLOT(_brd) ((_brd)->brd_slot) +/* + * Linux note: The below likely refers to something IRIX-specific. + * + * Early access IO proms are compatible only with KLSTRUCT values up to 24. + */ +#define KLSTRUCT_FIBERCHANNEL 25 +#define KLSTRUCT_MOD_SERIAL_NUM 26 +#define KLSTRUCT_IOC3MS 27 +#define KLSTRUCT_TPU 28 +#define KLSTRUCT_GSN_A 29 +#define KLSTRUCT_GSN_B 30 +#define KLSTRUCT_HDTV 31 -#define KLCF_CLASS(_brd) KLCLASS((_brd)->brd_type) -#define KLCF_TYPE(_brd) KLTYPE((_brd)->brd_type) -#define KLCF_REMOTE(_brd) (((_brd)->struct_type & LOCAL_BOARD) ? 0 : 1) -#define KLCF_NUM_COMPS(_brd) ((_brd)->brd_numcompts) -#define KLCF_MODULE_ID(_brd) ((_brd)->brd_module) -#define KLCF_NEXT(_brd) \ - ((_brd)->brd_next ? \ - (lboard_t *)(NODE_OFFSET_TO_K1(NASID_GET(_brd), (_brd)->brd_next)):\ - NULL) -#define KLCF_COMP(_brd, _ndx) \ - (klinfo_t *)(NODE_OFFSET_TO_K1(NASID_GET(_brd), \ - (_brd)->brd_compts[(_ndx)])) +/* ----------------------------------------------------------------------- */ +/* Component struct definitions */ -#define KLCF_COMP_ERROR(_brd, _comp) \ - (NODE_OFFSET_TO_K1(NASID_GET(_brd), (_comp)->errinfo)) +/* + * Linux note: The below applies to struct klc_port. + * + * The port info in ip27_cfg area translates to a struct klc_lboard in the + * KLCONFIG area. But since KLCONFIG does not use pointers, struct klc_lboard + * is stored in terms of a nasid and a offset from start of KLCONFIG area on + * that nasid. + */ -#define KLCF_COMP_TYPE(_comp) ((_comp)->struct_type) -#define KLCF_BRIDGE_W_ID(_comp) ((_comp)->physid) /* Widget ID */ +/** + * struct klc_port - stores info about a port on HUB or XBOW + * @nasid: NUMA-node-AS-ID + * @flag: port flags + * @offset: port offset + */ +struct klc_port { + nasid_t nasid; + u8 flag; + s32 offset; +}; + + +/** + * struct klc_cpu - stores info about a CPU + * @kl_info: common info + * @prid: processor PRID value + * @fpirr: FPU IRR value + * @speed: speed in MHZ + * @scache_sz: L2 size in MB + * @scache_spd: L2 speed in MHz + */ +struct klc_cpu { + struct klc_info kl_info; + u16 prid; + u16 fpirr; + u16 speed; + u16 scache_sz; + u16 scache_spd; +}; + + +/** + * struct klc_hub - stores info about a HUB chip on a nodeboard + * @kl_info: common info + * @flags: PCFG_HUB_xxx flags + * @port: XBOW port that HUB is connected to + * @box_nic: ? + * @mfg_nic: mfgr NIC string + * @speed: speed of HUB in HZ + */ +struct klc_hub { + struct klc_info kl_info; + u32 flags; + struct klc_port port; + u64 box_nic; + s32 mfg_nic; + u64 speed; +}; + + +/** + * struct klc_hub_uart - stores info about a UART chip attached to a HUB + * @kl_info: common info + * @flags: PCFG_HUB_xxx flags + * @box_nic: ? + */ +struct klc_hub_uart { + struct klc_info kl_info; + u32 flags; + u64 box_nic; +}; + + +/** + * struct klc_membank - stores info about a memory bank + * @kl_info: common info + * @mem_sz: total memory in MB + * @dimm_select: bank to physaddr mapping + * @bank_sz: memory bank sizes + * @attr: bank attributes + */ +struct klc_membank { + struct klc_info kl_info; + s16 mem_sz; + s16 dimm_select; + s16 bank_sz[MD_MEM_BANKS]; + s16 attr; +}; + +/* Get the size of a memory bank. */ +#define KLCONFIG_MEMBANK_SIZE(_i, _b) \ + ((_i)->bank_sz[(_b)]) + +/* Check if a memory bank has premium DIMMs (directory memory). */ +#define MEMBANK_PREM 1 +#define KLCONFIG_MEMBANK_PREM(_i, _b) \ + ((_i)->attr & (MEMBANK_PREM << (_b))) + + +#define MAX_SERIAL_NUM_SIZE 10 +/** + * struct klc_mod_sn - stores info about a module serial + * @kl_info: common info + * @sn: union sn: read S/N as either string or integer + * @str: read S/N as str + * @num: read S/N as integer + */ +struct klc_mod_sn { + struct klc_info kl_info; + union { + s8 str[MAX_SERIAL_NUM_SIZE]; + u64 num; + } sn; +}; +/* + * Hard coded values are necessary since we cannot treat the serial number + * as a component without losing compatibility between PROM versions. + */ +#define GET_COMP_SERIAL(_c) \ + (KLCF_CAST_MOD_SN(KLCF_COMP(_c, _c->num_components))) -/* - * Generic info structure. This stores common info about a - * component. - */ - -typedef struct klinfo_s { /* Generic info */ - unsigned char struct_type; /* type of this structure */ - unsigned char struct_version; /* version of this structure */ - unsigned char flags; /* Enabled, disabled etc */ - unsigned char revision; /* component revision */ - unsigned short diagval; /* result of diagnostics */ - unsigned short diagparm; /* diagnostic parameter */ - unsigned char inventory; /* previous inventory status */ - nic_t nic; /* MUst be aligned properly */ - unsigned char physid; /* physical id of component */ - unsigned int virtid; /* virtual id as seen by system */ - unsigned char widid; /* Widget id - if applicable */ - nasid_t nasid; /* node number - from parent */ - char pad1; /* pad out structure. */ - char pad2; /* pad out structure. */ - COMPONENT *arcs_compt; /* ptr to the arcs struct for ease*/ - klconf_off_t errinfo; /* component specific errors */ - unsigned short pad3; /* pci fields have moved over to */ - unsigned short pad4; /* klbri_t */ -} klinfo_t ; - -#define KLCONFIG_INFO_ENABLED(_i) ((_i)->flags & KLINFO_ENABLE) -/* - * Component structures. - * Following are the currently identified components: - * CPU, HUB, MEM_BANK, - * XBOW(consists of 16 WIDGETs, each of which can be HUB or GRAPHICS or BRIDGE) - * BRIDGE, IOC3, SuperIO, SCSI, FDDI - * ROUTER - * GRAPHICS - */ -#define KLSTRUCT_UNKNOWN 0 -#define KLSTRUCT_CPU 1 -#define KLSTRUCT_HUB 2 -#define KLSTRUCT_MEMBNK 3 -#define KLSTRUCT_XBOW 4 -#define KLSTRUCT_BRI 5 -#define KLSTRUCT_IOC3 6 -#define KLSTRUCT_PCI 7 -#define KLSTRUCT_VME 8 -#define KLSTRUCT_ROU 9 -#define KLSTRUCT_GFX 10 -#define KLSTRUCT_SCSI 11 -#define KLSTRUCT_FDDI 12 -#define KLSTRUCT_MIO 13 -#define KLSTRUCT_DISK 14 -#define KLSTRUCT_TAPE 15 -#define KLSTRUCT_CDROM 16 -#define KLSTRUCT_HUB_UART 17 -#define KLSTRUCT_IOC3ENET 18 -#define KLSTRUCT_IOC3UART 19 -#define KLSTRUCT_UNUSED 20 /* XXX UNUSED */ -#define KLSTRUCT_IOC3PCKM 21 -#define KLSTRUCT_RAD 22 -#define KLSTRUCT_HUB_TTY 23 -#define KLSTRUCT_IOC3_TTY 24 - -/* Early Access IO proms are compatible - only with KLSTRUCT values up to 24. */ - -#define KLSTRUCT_FIBERCHANNEL 25 -#define KLSTRUCT_MOD_SERIAL_NUM 26 -#define KLSTRUCT_IOC3MS 27 -#define KLSTRUCT_TPU 28 -#define KLSTRUCT_GSN_A 29 -#define KLSTRUCT_GSN_B 30 -#define KLSTRUCT_XTHD 31 +#define MAX_XBOW_LINKS 16 +#define XBOW_PORT_IO 0x1 +#define XBOW_PORT_HUB 0x2 +#define XBOW_PORT_ENABLE 0x4 -/* - * These are the indices of various components within a lboard structure. +/** + * struct klc_xbow - stores info about a XBOW chip + * @kl_info: common info + * @port_info: represents each XBOW port as struct klc_port + * @master_hub_link: holds numeric value of which XBOW port HUB is connected */ +struct klc_xbow { + struct klc_info kl_info; + struct klc_port port_info[MAX_XBOW_LINKS]; + int master_hub_link; + /* type of brd connected + component struct ptr+flags */ +}; -#define IP27_CPU0_INDEX 0 -#define IP27_CPU1_INDEX 1 -#define IP27_HUB_INDEX 2 -#define IP27_MEM_INDEX 3 +/* Get struct klc_xbow->port_info[offset] */ +#define XBOW_PORT_INFO(_x, _o) \ + ((_x)->port_info[(_o) - BASE_XBOW_PORT]) -#define BASEIO_BRIDGE_INDEX 0 -#define BASEIO_IOC3_INDEX 1 -#define BASEIO_SCSI1_INDEX 2 -#define BASEIO_SCSI2_INDEX 3 +/* Get struct klc_xbow->port_info[offset].flag */ +#define XBOW_PORT_FLAG(_x, _o) \ + XBOW_PORT_INFO(_x, _o).flag -#define MIDPLANE_XBOW_INDEX 0 -#define ROUTER_COMPONENT_INDEX 0 +/* Check if port flag indicates a HUB is attached */ +#define XBOW_PORT_TYPE_HUB(_x, _o) \ + (XBOW_PORT_FLAG(_x, _o) & XBOW_PORT_HUB) -#define CH4SCSI_BRIDGE_INDEX 0 +/* Check if port flag indicates an I/O device is attached */ +#define XBOW_PORT_TYPE_IO(_x, _o) \ + (XBOW_PORT_FLAG(_x, _o) & XBOW_PORT_IO) -/* Info holders for various hardware components */ +/* Check if port is enabled */ +#define XBOW_PORT_IS_ENABLED(_x, _o) \ + (XBOW_PORT_FLAG(_x, _o) & XBOW_PORT_ENABLE) -typedef u64 *pci_t; -typedef u64 *vmeb_t; -typedef u64 *vmed_t; -typedef u64 *fddi_t; -typedef u64 *scsi_t; -typedef u64 *mio_t; -typedef u64 *graphics_t; -typedef u64 *router_t; +/* Get port NASID */ +#define XBOW_PORT_NASID(_x, _o) \ + (XBOW_PORT_INFO(_x, _o).nasid) + + +#define MAX_PCI_DEVS 8 +/** + * struct klc_pdev - stores info about a PCI device + * @dev_id: 32-bits vendor/device ID + * @__pad: 32-bits padding + */ +struct klc_pdev { + u32 dev_id; + u32 __pad; +}; + +/** + * struct klc_pcibr - stores info about a PCI [X]BRIDGE + * @kl_info: common info + * @io6prom_info: IO6prom connected to bridge + * @bustype: PCI/VME BUS bridge/GIO + * @specific: PCI Board config info + * @devices: PCI IDs + * @mfg_nic: BRIDGE MFG NIC + */ +struct klc_pcibr { + struct klc_info kl_info; + u8 io6prom_info; + u8 bustype; + u64 *specific; + struct klc_pdev devices[MAX_PCI_DEVS]; + s32 mfg_nic; +}; + +#define MAX_IOC3_TTY 2 +/** + * struct klc_ioc3 - stores info about an IOC3 device + * @kl_info: common info + * @ssram: Info about SSRAM + * @nvram: Info about NVRAM + * @kl_sio_info: struct klc_info for SuperIO device + * @tty_off: offset to tty info (?) + * @kl_eth_info: struct klc_info for ethernet device + * @eth_off: offset to ethernet info (?) + * @kbd_off: offset to keyboard/mouse info (?) + */ +struct klc_ioc3 { + struct klc_info kl_info; + u8 ssram; + u8 nvram; + struct klc_info kl_sio_info; + s32 tty_off; + struct klc_info kl_eth_info; + s32 eth_off; + s32 kbd_off; +}; + +/* Get the widget ID of a bridge component. */ +#define KLCF_BRIDGE_W_ID(_c) ((_c)->physid) + + +#define MAX_VME_SLOTS 8 +/** + * struct klc_vme - stores info about a VME BRIDGE Ctlr + * @kl_info: common info + * @specific: VME-specific info + * @slots: VME slot/board info + */ +struct klc_vme { + struct klc_info kl_info; + u64 *specific; + s32 slots[MAX_VME_SLOTS]; +}; + + +#define MAX_ROUTER_PORTS 6 /* Max num of ports on a router */ +/** + * struct klc_router - stores info about a ROUTER that links nodes together + * @kl_info: common info + * @flags: PCFG_ROUTER_xxx flags + * @box_nic: NIC of the containing module + * @port: struct klc_port for each ROUTER port + * @mfg_nic: MFG NIC string + * @vector: vector from master node + */ +struct klc_router { + struct klc_info kl_info; + u32 flags; + u64 box_nic; + struct klc_port port[MAX_ROUTER_PORTS + 1]; + s32 mfg_nic; + u64 vector; +}; -/* - * The port info in ip27_cfg area translates to a lboart_t in the - * KLCONFIG area. But since KLCONFIG does not use pointers, lboart_t - * is stored in terms of a nasid and a offset from start of KLCONFIG - * area on that nasid. - */ -typedef struct klport_s { - nasid_t port_nasid; - unsigned char port_flag; - klconf_off_t port_offset; -} klport_t; - -typedef struct klcpu_s { /* CPU */ - klinfo_t cpu_info; - unsigned short cpu_prid; /* Processor PRID value */ - unsigned short cpu_fpirr; /* FPU IRR value */ - unsigned short cpu_speed; /* Speed in MHZ */ - unsigned short cpu_scachesz; /* secondary cache size in MB */ - unsigned short cpu_scachespeed;/* secondary cache speed in MHz */ -} klcpu_t ; - -#define CPU_STRUCT_VERSION 2 - -typedef struct klhub_s { /* HUB */ - klinfo_t hub_info; - unsigned int hub_flags; /* PCFG_HUB_xxx flags */ - klport_t hub_port; /* hub is connected to this */ - nic_t hub_box_nic; /* nic of containing box */ - klconf_off_t hub_mfg_nic; /* MFG NIC string */ - u64 hub_speed; /* Speed of hub in HZ */ -} klhub_t ; - -typedef struct klhub_uart_s { /* HUB */ - klinfo_t hubuart_info; - unsigned int hubuart_flags; /* PCFG_HUB_xxx flags */ - nic_t hubuart_box_nic; /* nic of containing box */ -} klhub_uart_t ; - -#define MEMORY_STRUCT_VERSION 2 - -typedef struct klmembnk_s { /* MEMORY BANK */ - klinfo_t membnk_info; - short membnk_memsz; /* Total memory in megabytes */ - short membnk_dimm_select; /* bank to physical addr mapping*/ - short membnk_bnksz[MD_MEM_BANKS]; /* Memory bank sizes */ - short membnk_attr; -} klmembnk_t ; - -#define KLCONFIG_MEMBNK_SIZE(_info, _bank) \ - ((_info)->membnk_bnksz[(_bank)]) - - -#define MEMBNK_PREMIUM 1 -#define KLCONFIG_MEMBNK_PREMIUM(_info, _bank) \ - ((_info)->membnk_attr & (MEMBNK_PREMIUM << (_bank))) - -#define MAX_SERIAL_NUM_SIZE 10 - -typedef struct klmod_serial_num_s { - klinfo_t snum_info; - union { - char snum_str[MAX_SERIAL_NUM_SIZE]; - unsigned long long snum_int; - } snum; -} klmod_serial_num_t; - -/* Macros needed to access serial number structure in lboard_t. - Hard coded values are necessary since we cannot treat - serial number struct as a component without losing compatibility - between prom versions. */ - -#define GET_SNUM_COMP(_l) ((klmod_serial_num_t *)\ - KLCF_COMP(_l, _l->brd_numcompts)) - -#define MAX_XBOW_LINKS 16 - -typedef struct klxbow_s { /* XBOW */ - klinfo_t xbow_info ; - klport_t xbow_port_info[MAX_XBOW_LINKS] ; /* Module number */ - int xbow_master_hub_link; - /* type of brd connected+component struct ptr+flags */ -} klxbow_t ; - -#define MAX_PCI_SLOTS 8 - -typedef struct klpci_device_s { - s32 pci_device_id; /* 32 bits of vendor/device ID. */ - s32 pci_device_pad; /* 32 bits of padding. */ -} klpci_device_t; - -#define BRIDGE_STRUCT_VERSION 2 - -typedef struct klbri_s { /* BRIDGE */ - klinfo_t bri_info ; - unsigned char bri_eprominfo ; /* IO6prom connected to bridge */ - unsigned char bri_bustype ; /* PCI/VME BUS bridge/GIO */ - pci_t pci_specific ; /* PCI Board config info */ - klpci_device_t bri_devices[MAX_PCI_DEVS] ; /* PCI IDs */ - klconf_off_t bri_mfg_nic ; -} klbri_t ; - -#define MAX_IOC3_TTY 2 - -typedef struct klioc3_s { /* IOC3 */ - klinfo_t ioc3_info ; - unsigned char ioc3_ssram ; /* Info about ssram */ - unsigned char ioc3_nvram ; /* Info about nvram */ - klinfo_t ioc3_superio ; /* Info about superio */ - klconf_off_t ioc3_tty_off ; - klinfo_t ioc3_enet ; - klconf_off_t ioc3_enet_off ; - klconf_off_t ioc3_kbd_off ; -} klioc3_t ; - -#define MAX_VME_SLOTS 8 - -typedef struct klvmeb_s { /* VME BRIDGE - PCI CTLR */ - klinfo_t vmeb_info ; - vmeb_t vmeb_specific ; - klconf_off_t vmeb_brdinfo[MAX_VME_SLOTS] ; /* VME Board config info */ -} klvmeb_t ; - -typedef struct klvmed_s { /* VME DEVICE - VME BOARD */ - klinfo_t vmed_info ; - vmed_t vmed_specific ; - klconf_off_t vmed_brdinfo[MAX_VME_SLOTS] ; /* VME Board config info */ -} klvmed_t ; - -#define ROUTER_VECTOR_VERS 2 - -/* XXX - Don't we need the number of ports here?!? */ -typedef struct klrou_s { /* ROUTER */ - klinfo_t rou_info ; - unsigned int rou_flags ; /* PCFG_ROUTER_xxx flags */ - nic_t rou_box_nic ; /* nic of the containing module */ - klport_t rou_port[MAX_ROUTER_PORTS + 1] ; /* array index 1 to 6 */ - klconf_off_t rou_mfg_nic ; /* MFG NIC string */ - u64 rou_vector; /* vector from master node */ -} klrou_t ; /* - * Graphics Controller/Device + * XXX: Linux note: The below is IRIX apocrypha. * - * (IP27/IO6) Prom versions 6.13 (and 6.5.1 kernels) and earlier - * used a couple different structures to store graphics information. - * For compatibility reasons, the newer data structure preserves some - * of the layout so that fields that are used in the old versions remain - * in the same place (with the same info). Determination of what version - * of this structure we have is done by checking the cookie field. - */ -#define KLGFX_COOKIE 0x0c0de000 - -typedef struct klgfx_s { /* GRAPHICS Device */ - klinfo_t gfx_info; - klconf_off_t old_gndevs; /* for compatibility with older proms */ - klconf_off_t old_gdoff0; /* for compatibility with older proms */ - unsigned int cookie; /* for compatibility with older proms */ - unsigned int moduleslot; - struct klgfx_s *gfx_next_pipe; - graphics_t gfx_specific; - klconf_off_t pad0; /* for compatibility with older proms */ - klconf_off_t gfx_mfg_nic; -} klgfx_t; - -typedef struct klxthd_s { - klinfo_t xthd_info ; - klconf_off_t xthd_mfg_nic ; /* MFG NIC string */ -} klxthd_t ; - -typedef struct kltpu_s { /* TPU board */ - klinfo_t tpu_info ; - klconf_off_t tpu_mfg_nic ; /* MFG NIC string */ -} kltpu_t ; - -typedef struct klgsn_s { /* GSN board */ - klinfo_t gsn_info ; - klconf_off_t gsn_mfg_nic ; /* MFG NIC string */ -} klgsn_t ; + * (IP27/IO6) Prom versions 6.13 (and 6.5.1 kernels) and earlier used a + * couple different structures to store graphics information. + * For compatibility reasons, the newer data structure preserves some of + * the layout so that fields that are used in the old versions remain in + * the same place (with the same info). Determination of what version of + * this structure we have is done by checking the cookie field. + */ + +#define KLGFX_COOKIE 0x0c0de000 +/** + * struct klc_gfx - stores info about a GRAPHICS device (Kona/Mgras) + * @kl_info: common info + * @old_gndevs: compatibility w/ older PROMs + * @old_gdoff0: compatibility w/ older PROMs + * @cookie: compatibility w/ older PROMs + * @module_slot: slot of the containing module + * @next_pipe: pointer to next gfx pipe + * @specific: pointer to gfx-specific info + * @__pad: padding (compat w/ older PROMs) + * @mfg_nic: MFG NIC string + */ +struct klc_gfx { + struct klc_info kl_info; + s32 old_gndevs; + s32 old_gdoff0; + u32 cookie; + u32 module_slot; + struct klc_gfx *next_pipe; + u64 *specific; + s32 __pad; + s32 mfg_nic; +}; + +/** + * struct klc_hdtv - stores info about a pseudo-gfx device (HDTV board) + * @kl_info: common info + * @mfg_nic: MFG NIC string + */ +struct klc_hdtv { + struct klc_info kl_info; + s32 mfg_nic; +}; + + +/** + * struct klc_tpu - stores info about a tensor processing unit (rare hw) + * @kl_info: common info + * @mfg_nic: MFG NIC string + */ +struct klc_tpu { + struct klc_info kl_info; + s32 mfg_nic; +}; + +/** + * struct klc_gsn - stores info about a GSN board (?) (rare hw) + * @kl_info: common info + * @mfg_nic: MFG NIC string + */ +struct klc_gsn { + struct klc_info kl_info; + s32 mfg_nic; +}; + #define MAX_SCSI_DEVS 16 +/** + * struct klc_scsi - stores info about a SCSI controller + * @kl_info: common info + * @specific: pointer to SCSI-specific info + * @num_devs: number of attached devices + * @dev_info: per-device info + */ +struct klc_scsi { + struct klc_info kl_info; + u64 *specific; + u8 num_devs; + s32 dev_info[MAX_SCSI_DEVS]; +}; + + +#define MAX_FDDI_DEVS 10 /* XXX: Is this correct? */ +/** + * struct klc_fddi - stores info about an FDDI controller + * @kl_info: common info + * @specific: pointer to FDDI-specific info + * @dev_info: per-device info + */ +struct klc_fddi { + struct klc_info kl_info; + u64 *specific; + s32 dev_info[MAX_FDDI_DEVS]; +}; -/* - * NOTE: THis is the max sized kl* structure and is used in klmalloc.c - * to allocate space of type COMPONENT. Make sure that if the size of - * any other component struct becomes more than this, then redefine - * that as the size to be klmalloced. - */ - -typedef struct klscsi_s { /* SCSI Controller */ - klinfo_t scsi_info ; - scsi_t scsi_specific ; - unsigned char scsi_numdevs ; - klconf_off_t scsi_devinfo[MAX_SCSI_DEVS] ; -} klscsi_t ; - -typedef struct klscdev_s { /* SCSI device */ - klinfo_t scdev_info ; - struct scsidisk_data *scdev_cfg ; /* driver fills up this */ -} klscdev_t ; - -typedef struct klttydev_s { /* TTY device */ - klinfo_t ttydev_info ; - struct terminal_data *ttydev_cfg ; /* driver fills up this */ -} klttydev_t ; - -typedef struct klenetdev_s { /* ENET device */ - klinfo_t enetdev_info ; - struct net_data *enetdev_cfg ; /* driver fills up this */ -} klenetdev_t ; - -typedef struct klkbddev_s { /* KBD device */ - klinfo_t kbddev_info ; - struct keyboard_data *kbddev_cfg ; /* driver fills up this */ -} klkbddev_t ; - -typedef struct klmsdev_s { /* mouse device */ - klinfo_t msdev_info ; - void *msdev_cfg ; -} klmsdev_t ; - -#define MAX_FDDI_DEVS 10 /* XXX Is this true */ - -typedef struct klfddi_s { /* FDDI */ - klinfo_t fddi_info ; - fddi_t fddi_specific ; - klconf_off_t fddi_devinfo[MAX_FDDI_DEVS] ; -} klfddi_t ; - -typedef struct klmio_s { /* MIO */ - klinfo_t mio_info ; - mio_t mio_specific ; -} klmio_t ; - - -typedef union klcomp_s { - klcpu_t kc_cpu; - klhub_t kc_hub; - klmembnk_t kc_mem; - klxbow_t kc_xbow; - klbri_t kc_bri; - klioc3_t kc_ioc3; - klvmeb_t kc_vmeb; - klvmed_t kc_vmed; - klrou_t kc_rou; - klgfx_t kc_gfx; - klscsi_t kc_scsi; - klscdev_t kc_scsi_dev; - klfddi_t kc_fddi; - klmio_t kc_mio; - klmod_serial_num_t kc_snum ; -} klcomp_t; - -typedef union kldev_s { /* for device structure allocation */ - klscdev_t kc_scsi_dev ; - klttydev_t kc_tty_dev ; - klenetdev_t kc_enet_dev ; - klkbddev_t kc_kbd_dev ; -} kldev_t ; - -/* Data structure interface routines. TBD */ - -/* Include launch info in this file itself? TBD */ -/* - * TBD - Can the ARCS and device driver related info also be included in the - * KLCONFIG area. On the IO4PROM, prom device driver info is part of cfgnode_t - * structure, viz private to the IO4prom. +/** + * struct klc_mio - stores info about a MIO device (?) + * @kl_info: common info + * @specific: pointer to MIO-specific info + */ +struct klc_mio { + struct klc_info kl_info; + u64 *specific; +}; + +#define IS_MIO_PRESENT(_b) \ + ((_b->type == KLTYPE_BASEIO) && \ + (_b->flags & SECOND_NIC_PRESENT)) + +#define IS_MIO_IOC3(_b, _n) \ + (IS_MIO_PRESENT(_b) && ((_n) > 2)) + + +/** + * struct klc_scdev - stores info about a SCSI device + * @kl_info: common info + * @dev_cfg: void pointer to driver-specific info */ +struct klc_scdev { + struct klc_info kl_info; + void *dev_cfg; +}; + +/** + * struct klc_tty - stores info about a TTY device + * @kl_info: common info + * @dev_cfg: void pointer to driver-specific info + */ +struct klc_tty { + struct klc_info kl_info; + void *dev_cfg; +}; + +/** + * struct klc_eth - stores info about an ethernet device + * @kl_info: common info + * @dev_cfg: void pointer to driver-specific info + */ +struct klc_eth { + struct klc_info kl_info; + void *dev_cfg; +}; + +/** + * struct klc_kbd - stores info about a keyboard device + * @kl_info: common info + * @dev_cfg: void pointer to driver-specific info + */ +struct klc_kbd { + struct klc_info kl_info; + void *dev_cfg; +}; + +/** + * struct klc_mouse - stores info about a mouse device + * @kl_info: common info + * @dev_cfg: void pointer to driver-specific info + */ +struct klc_mouse { + struct klc_info kl_info; + void *dev_cfg; +}; + + +/** + * union klc_components - union to access component data + * @cpu: CPU + * @hub: HUB ASIC + * @membank: memory bank + * @xbow: XBOW ASIC + * @pcibr: PCI [X]BRIDGE + * @ioc3: IOC3 device + * @vmebr: VME BRIDGE + * @vdev: VME device + * @router: ROUTER board + * @gfx: GRAPHICS pipe + * @hdtv: pseudo-GFX device/HDTV + * @tpu: tensor processing unit + * @gsn: GSN device/board + * @scsi: SCSI controller + * @scdev: SCSI device + * @fddi: FDDI controller + * @mio: MIO device + * @serial_num: serial number + */ +union klc_components { + struct klc_cpu cpu; + struct klc_hub hub; + struct klc_membank membank; + struct klc_xbow xbow; + struct klc_pcibr pcibr; + struct klc_ioc3 ioc3; + struct klc_vme vmebr; + struct klc_vme vdev; + struct klc_router router; + struct klc_gfx gfx; + struct klc_hdtv hdtv; + struct klc_tpu tpu; + struct klc_gsn gsn; + struct klc_scsi scsi; + struct klc_scdev scdev; + struct klc_fddi fddi; + struct klc_mio mio; + struct klc_mod_sn serial_num; +}; + +/** + * union klc_components - union to access component data + * @scdev: SCSI device + * @tty: TTY device + * @eth: ethernet device + * @kbd: keyboard + * @mouse: mouse + */ +union klc_devices { + struct klc_scdev scdev; + struct klc_tty tty; + struct klc_eth eth; + struct klc_kbd kbd; + struct klc_mouse mouse; +}; + + +/* ----------------------------------------------------------------------- */ +/* Macros that assist in casting to various struct klc_* instances */ + +/* struct klc_* via KLCF_NODE_OFFSET_K(0|1) */ +#define KLCF_NODE_OFFSET(_k, _b, _o) \ + (NODE_OFFSET_TO_##_k(NASID_GET(_b), (_o))) + +/* klc_info via K1 */ +#define KLCF_INFO_K1(_b, _o) \ + (KLCF_CAST_INFO(KLCF_NODE_OFFSET(K1, (_b), (_o)))) + +/* klc_lboard via K0 */ +#define KLCF_LBOARD_K0(_b, _o) \ + (KLCF_CAST_LBOARD(KLCF_NODE_OFFSET(K0, (_b), (_o)))) + +/* klc_lboard via K1 */ +#define KLCF_LBOARD_K1(_b, _o) \ + (KLCF_CAST_LBOARD(KLCF_NODE_OFFSET(K1, (_b), (_o)))) + +/* klc_router via K0 */ +#define KLCF_ROUTER_K0(_b, _o) \ + (KLCF_CAST_ROUTER(KLCF_NODE_OFFSET(K0, (_b), (_o)))) + +/* struct klc_lboard via KL_CONFIG_INFO() */ +#define KLCF_LBOARD_INFO(_n) \ + KLCF_CAST_LBOARD(KL_CONFIG_INFO(_n)) + +/* Get a pointer to the next board. */ +#define KLCF_NEXT(_b) \ + ((_b)->next ? \ + KLCF_LBOARD_K1((_b), (_b)->next) : NULL) + +/* Get a pointer to a component on a board. */ +#define KLCF_COMP(_b, _o) \ + (KLCF_INFO_K1((_b), (_b)->components[(_o)])) + +/* Get a pointer to a component's errinfo data. */ +#define KLCF_COMP_ERROR(_b, _c) \ + (KLCF_NODE_OFFSET(K1, (_b), (_c)->errinfo)) + +/* Get the component's structure type. */ +#define KLCF_COMP_TYPE(_c) \ + ((_c)->struct_type) + + +/* ----------------------------------------------------------------------- */ +/* External function declarations */ + +extern struct klc_lboard *kl_find_lboard(struct klc_lboard *start, u8 type); +extern struct klc_info *kl_find_component(struct klc_lboard *brd, + struct klc_info *kli, u8 type); +extern struct klc_info *kl_find_first_component(struct klc_lboard *brd, + u8 type); +extern struct klc_cpu *nasid_slice_to_cpuinfo(nasid_t, int); +extern struct klc_lboard *kl_find_lboard_class(struct klc_lboard *start, + u8 brd_class); + + +/* ----------------------------------------------------------------------- */ +/* Virtual dipswitch values (starting from switch "7") */ + +#define VDS_NOGFX 0x8000 /* Don't enable gfx and autoboot */ +#define VDS_NOMP 0x0100 /* Don't start slave processors */ +#define VDS_MANUMODE 0x0080 /* Manufacturing mode */ +#define VDS_NOARB 0x0040 /* No bootmaster arbitration */ +#define VDS_PODMODE 0x0020 /* Go straight to POD mode */ +#define VDS_NO_DIAGS 0x0010 /* Don't run any diags after BM arb */ +#define VDS_DEFAULTS 0x0008 /* Use default environment values */ +#define VDS_NOMEMCLEAR 0x0004 /* Don't run mem cfg code */ +#define VDS_2ND_IO4 0x0002 /* Boot from the second IO4 */ +#define VDS_DEBUG_PROM 0x0001 /* Print PROM debugging messages */ + + +/* ----------------------------------------------------------------------- */ +/* Miscellania */ + +/* XXX: Data structure interface routines. TBD */ + +/* XXX: Include launch info in this file itself? TBD */ /* - * TBD - Allocation issues. - * - * Do we need to Mark off sepatate heaps for lboard_t, rboard_t, component, - * errinfo and allocate from them, or have a single heap and allocate all - * structures from it. Debug is easier in the former method since we can - * dump all similar structs in one command, but there will be lots of holes, - * in memory and max limits are needed for number of structures. - * Another way to make it organized, is to have a union of all components - * and allocate a aligned chunk of memory greater than the biggest - * component. + * XXX: TBD: Can the ARCS and device driver related info also be included in + * the KLCONFIG area. On the IO4PROM, prom device driver info is part of + * cfgnode_t structure, viz private to the IO4prom. */ -typedef union { - lboard_t *lbinfo ; -} biptr_t ; +/* + * XXX: TBD: Allocation issues. + * Do we need to mark off separate heaps for struct klc_lboard, + * struct klc_rboard, struct klc_components, errinfo and allocate from + * them, or have a single heap and allocate all structures from it. + * Debug is easier in the former method since we can dump all similar + * structs in one command, but there will be lots of holes, in memory + * and max limits are needed for number of structures. + * Another way to make it organized, is to have a union of all components + * and allocate an aligned chunk of memory greater than the biggest + * component. + */ +/* XXX: What is this? */ +union klc_biptr { + struct klc_lboard *lbinfo; +}; +/* XXX: these probably belong elsewhere. */ #define BRI_PER_XBOW 6 #define PCI_PER_BRI 8 #define DEV_PER_PCI 16 -/* Virtual dipswitch values (starting from switch "7"): */ - -#define VDS_NOGFX 0x8000 /* Don't enable gfx and autoboot */ -#define VDS_NOMP 0x100 /* Don't start slave processors */ -#define VDS_MANUMODE 0x80 /* Manufacturing mode */ -#define VDS_NOARB 0x40 /* No bootmaster arbitration */ -#define VDS_PODMODE 0x20 /* Go straight to POD mode */ -#define VDS_NO_DIAGS 0x10 /* Don't run any diags after BM arb */ -#define VDS_DEFAULTS 0x08 /* Use default environment values */ -#define VDS_NOMEMCLEAR 0x04 /* Don't run mem cfg code */ -#define VDS_2ND_IO4 0x02 /* Boot from the second IO4 */ -#define VDS_DEBUG_PROM 0x01 /* Print PROM debugging messages */ - -/* external declarations of Linux kernel functions. */ - -extern lboard_t *find_lboard(lboard_t *start, unsigned char type); -extern klinfo_t *find_component(lboard_t *brd, klinfo_t *kli, unsigned char type); -extern klinfo_t *find_first_component(lboard_t *brd, unsigned char type); -extern klcpu_t *nasid_slice_to_cpuinfo(nasid_t, int); -extern lboard_t *find_lboard_class(lboard_t *start, unsigned char brd_class); - - -extern klcpu_t *sn_get_cpuinfo(cpuid_t cpu); - #endif /* _ASM_SN_KLCONFIG_H */ diff --git a/arch/mips/include/asm/sn/sn0/arch.h b/arch/mips/include/asm/sn/sn0/arch.h index 425a67e..840a44a 100644 --- a/arch/mips/include/asm/sn/sn0/arch.h +++ b/arch/mips/include/asm/sn/sn0/arch.h @@ -11,8 +11,6 @@ #ifndef _ASM_SN_SN0_ARCH_H #define _ASM_SN_SN0_ARCH_H - -#ifndef SN0XXL /* 128 cpu SMP max */ /* * This is the maximum number of nodes that can be part of a kernel. * Effectively, it's the maximum number of compact node ids (cnodeid_t). @@ -25,12 +23,16 @@ */ #define MAXCPUS 128 -#else /* SN0XXL system */ - -#define MAX_COMPACT_NODES 128 -#define MAXCPUS 256 - -#endif /* SN0XXL */ +/* + * XXX: Historical Note regarding SN0XXL: + * + * There used to be an obscure #ifndef check for SN0XXL, which appears to + * have been a much larger IP27 setup that supported a maximum of 128 compact + * nodes and 256 CPUs. SN0XXL was never defined anywhere, though, so those + * defines never got used. In reality, complete SN0XXL systems are not likely + * to exist any longer, so I think it's safe to remove these definitions and + * leave this historical note behind. + */ /* * This is the maximum number of NASIDS that can be present in a system. @@ -63,7 +65,7 @@ #endif /* CONFIG_SGI_SN_M_MODE */ #define SLOT_SHIFT (27) -#define SLOT_MIN_MEM_SIZE (32*1024*1024) +#define SLOT_MIN_MEM_SIZE (32 * 1024 * 1024) #define CPUS_PER_NODE 2 /* CPUs on a single hub */ #define CPUS_PER_NODE_SHFT 1 /* Bits to shift in the node number */ diff --git a/arch/mips/include/asm/sn/sn0/hubmd.h b/arch/mips/include/asm/sn/sn0/hubmd.h index 305d002..d0e48ff 100644 --- a/arch/mips/include/asm/sn/sn0/hubmd.h +++ b/arch/mips/include/asm/sn/sn0/hubmd.h @@ -438,7 +438,7 @@ (HUB_S(CPU_LED_ADDR(_nasid, _slice), (_val))) #define SET_MY_LEDS(_v) \ - SET_CPU_LEDS(get_nasid(), get_slice(), (_v)) + SET_CPU_LEDS(ip27_get_nasid(), get_slice(), (_v)) /* * Operations on Memory/Directory DIMM control register diff --git a/arch/mips/include/asm/sn/sn_private.h b/arch/mips/include/asm/sn/sn_private.h index fdfae43..49f2dc0 100644 --- a/arch/mips/include/asm/sn/sn_private.h +++ b/arch/mips/include/asm/sn/sn_private.h @@ -5,13 +5,10 @@ extern nasid_t master_nasid; -extern void cpu_node_probe(void); -extern cnodeid_t get_compact_nodeid(void); -extern void hub_rtc_init(cnodeid_t); -extern void cpu_time_init(void); -extern void per_cpu_init(void); -extern void install_cpu_nmi_handler(int slice); -extern void install_ipi(void); +extern void ip27_smp_cpu_node_probe(void); +extern void ip27_per_cpu_init(void); +extern void ip27_install_cpu_nmi_handler(int slice); +extern void ip27_install_ipi(void); extern void setup_replication_mask(void); extern void replicate_kernel_text(void); extern unsigned long node_getfirstfree(cnodeid_t); diff --git a/arch/mips/include/asm/sn/types.h b/arch/mips/include/asm/sn/types.h index 6d24d4e..216fcf0 100644 --- a/arch/mips/include/asm/sn/types.h +++ b/arch/mips/include/asm/sn/types.h @@ -13,13 +13,9 @@ typedef unsigned long cpuid_t; typedef unsigned long cnodemask_t; -typedef signed short nasid_t; /* node id in numa-as-id space */ -typedef signed short cnodeid_t; /* node id in compact-id space */ -typedef signed char partid_t; /* partition ID type */ -typedef signed short moduleid_t; /* user-visible module number type */ -typedef signed short cmoduleid_t; /* kernel compact module id type */ -typedef unsigned char clusterid_t; /* Clusterid of the cell */ - -typedef dev_t vertex_hdl_t; /* hardware graph vertex handle */ +typedef s16 nasid_t; /* node id in numa-as-id space */ +typedef s8 cnodeid_t; /* node id in compact-id space */ +typedef s8 partid_t; /* partition ID type */ +typedef s16 moduleid_t; /* user-visible module number type */ #endif /* _ASM_SN_TYPES_H */ diff --git a/arch/mips/include/asm/xtalk/xtalk.h b/arch/mips/include/asm/xtalk/xtalk.h index 26d2ed1..e96f62e 100644 --- a/arch/mips/include/asm/xtalk/xtalk.h +++ b/arch/mips/include/asm/xtalk/xtalk.h @@ -16,25 +16,26 @@ /* * User-level device driver visible types */ -typedef char xwidgetnum_t; /* xtalk widget number (0..15) */ +typedef u8 xwidgetnum_t; /* xtalk widget number (0..15) */ #define XWIDGET_NONE -1 -typedef int xwidget_part_num_t; /* xtalk widget part number */ +typedef s32 xwidget_part_num_t; /* xtalk widget part number */ #define XWIDGET_PART_NUM_NONE -1 -typedef int xwidget_rev_num_t; /* xtalk widget revision number */ +typedef s32 xwidget_rev_num_t; /* xtalk widget revision number */ #define XWIDGET_REV_NUM_NONE -1 -typedef int xwidget_mfg_num_t; /* xtalk widget manufacturing ID */ +typedef s32 xwidget_mfg_num_t; /* xtalk widget manufacturing ID */ #define XWIDGET_MFG_NUM_NONE -1 typedef struct xtalk_piomap_s *xtalk_piomap_t; -/* It is often convenient to fold the XIO target port +/* + * It is often convenient to fold the XIO target port * number into the XIO address. */ #define XIO_NOWHERE (0xFFFFFFFFFFFFFFFFull) @@ -47,15 +48,6 @@ typedef struct xtalk_piomap_s *xtalk_piomap_t; #define XIO_PORT(x) ((xwidgetnum_t)(((x)&XIO_PORT_BITS) >> XIO_PORT_SHIFT)) #define XIO_PACK(p, o) ((((uint64_t)(p))< + + /* Widget bits */ + #define XTALK_NODEV 0xffffffff + #define XTALK_XBOW _AC(0x0, UL) /* XBow is always 0 */ + #define XTALK_LOW_DEV HUB_WIDGET_ID_MIN + #define XTALK_HIGH_DEV HUB_WIDGET_ID_MAX + + /* Xbow bits */ + #define XBOW_REG_LINK_STAT_0 0x114 + #define XBOW_REG_LINK_BLOCK_SIZE 0x40 + #define XBOW_REG_LINK_ALIVE 0x80000000 +#endif + +/** + * xwidget_platform_data - platform data for xtalk widgets. + * @nasid: kinda like the node id for a multinode system. + * @master_wid: master xtalk widget for this xwidget (HUB, HEART, BEDROCK) + */ +struct xwidget_platform_data { + nasid_t nasid; + xwidgetnum_t master_wid; +}; + /* * according to the crosstalk spec, only 32-bits access to the widget * configuration registers is allowed. some widgets may allow 64-bits diff --git a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c index 0f09eaf..084088a 100644 --- a/arch/mips/pci/pci-ip27.c +++ b/arch/mips/pci/pci-ip27.c @@ -10,81 +10,77 @@ #include #include #include -#include -#include +#include + #include #include + +#include #include #include -/* - * Max #PCI busses we can handle; ie, max #PCI bridges. - */ -#define MAX_PCI_BUSSES 40 +#include -/* - * Max #PCI devices (like scsi controllers) we handle on a bus. - */ -#define MAX_DEVICES_PER_PCIBUS 8 - -/* - * XXX: No kmalloc available when we do our crosstalk scan, - * we should try to move it later in the boot process. - */ -static struct bridge_controller bridges[MAX_PCI_BUSSES]; - -/* - * Translate from irq to software PCI bus number and PCI slot. - */ -struct bridge_controller *irq_to_bridge[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS]; -int irq_to_slot[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS]; +/* Defined in ip27-irq-pci.c. */ +extern int ip27_request_irq(void); extern struct pci_ops bridge_pci_ops; -int bridge_probe(nasid_t nasid, int widget_id, int masterwid) +/* Increments for each additional bridge. */ +static int num_bridges = 0; + +static int +bridge_probe(nasid_t nasid, xwidgetnum_t widget_id, xwidgetnum_t masterwid) { + int slot; + u32 wid_ctrl; /* BRIDGE WAR */ + unsigned long flags; unsigned long offset = NODE_OFFSET(nasid); - struct bridge_controller *bc; - static int num_bridges = 0; bridge_t *bridge; - int slot; + struct bridge_controller *bc; pci_set_flags(PCI_PROBE_ONLY); - printk("a bridge\n"); - - /* XXX: kludge alert.. */ - if (!num_bridges) - ioport_resource.end = ~0UL; - - bc = &bridges[num_bridges]; + /* Alloc & zero some memory for the bridge_controller. */ + bc = kzalloc(sizeof(struct bridge_controller), GFP_KERNEL); + + /* Init a spinlock. */ + spin_lock_init(&bc->lock); + spin_lock_irqsave(&bc->lock, flags); + + /* Set bridge_controller parameters. */ + bc->pc.pci_ops = &bridge_pci_ops; + bc->pc.mem_resource = &bc->mem; + bc->pc.mem_offset = offset; + bc->pc.io_resource = &bc->io; + bc->pc.io_offset = offset; + bc->pc.busn_resource = &bc->busn; + bc->pc.busn_offset = offset; + bc->pc.index = num_bridges; + bc->pc.io_map_base = NODE_SWIN_BASE(nasid, widget_id); + + bc->mem.name = "Bridge MEM"; + bc->mem.start = (NODE_SWIN_BASE(nasid, widget_id) + PCIBR_OFFSET_MEM); + bc->mem.end = (NODE_SWIN_BASE(nasid, widget_id) + PCIBR_OFFSET_IO - 1); + bc->mem.flags = IORESOURCE_MEM; + + bc->io.name = "Bridge IO"; + bc->io.start = (NODE_SWIN_BASE(nasid, widget_id) + PCIBR_OFFSET_IO); + bc->io.end = (NODE_SWIN_BASE(nasid, widget_id) + PCIBR_OFFSET_END - 1); + bc->io.flags = IORESOURCE_IO; + + bc->busn.name = "Bridge BUSN"; + bc->busn.start = num_bridges; + bc->busn.end = 255; + bc->busn.flags = IORESOURCE_BUS; - bc->pc.pci_ops = &bridge_pci_ops; - bc->pc.mem_resource = &bc->mem; - bc->pc.io_resource = &bc->io; - - bc->pc.index = num_bridges; - - bc->mem.name = "Bridge PCI MEM"; - bc->pc.mem_offset = offset; - bc->mem.start = 0; - bc->mem.end = ~0UL; - bc->mem.flags = IORESOURCE_MEM; - - bc->io.name = "Bridge IO MEM"; - bc->pc.io_offset = offset; - bc->io.start = 0UL; - bc->io.end = ~0UL; - bc->io.flags = IORESOURCE_IO; - - bc->irq_cpu = smp_processor_id(); bc->widget_id = widget_id; bc->nasid = nasid; - bc->baddr = (u64)masterwid << 60 | PCI64_ATTR_BAR; + bc->baddr = ((u64)masterwid << PCI64_ATTR_TARG_SHFT); /* - * point to this bridge + * Point to this bridge */ bridge = (bridge_t *) RAW_NODE_SWIN_BASE(nasid, widget_id); @@ -99,36 +95,53 @@ int bridge_probe(nasid_t nasid, int widget_id, int masterwid) bridge->b_int_device = 0x0; /* - * swap pio's to pci mem and io space (big windows) + * Swap pio's to pci mem and io space (big windows) */ - bridge->b_wid_control |= BRIDGE_CTRL_IO_SWAP | - BRIDGE_CTRL_MEM_SWAP; + wid_ctrl = bridge->b_wid_control; + wid_ctrl |= (BRIDGE_CTRL_IO_SWAP | BRIDGE_CTRL_MEM_SWAP); + + /* Set the BRIDGE PAGE_SIZE */ #ifdef CONFIG_PAGE_SIZE_4KB - bridge->b_wid_control &= ~BRIDGE_CTRL_PAGE_SIZE; + wid_ctrl &= ~BRIDGE_CTRL_PAGE_SIZE; #else /* 16kB or larger */ - bridge->b_wid_control |= BRIDGE_CTRL_PAGE_SIZE; + wid_ctrl |= BRIDGE_CTRL_PAGE_SIZE; #endif /* + * Another BRIDGE WAR, read the BRIDGE widget control register + * back after writing it to avoid an invalid address bug. + */ + bridge->b_wid_control = wid_ctrl; + wid_ctrl = bridge->b_wid_control; + + /* * Hmm... IRIX sets additional bits in the address which * are documented as reserved in the bridge docs. */ - bridge->b_wid_int_upper = 0x8000 | (masterwid << 16); + bridge->b_wid_int_upper = 0x8000 | (masterwid << WIDGET_TARGET_ID_SHFT); bridge->b_wid_int_lower = 0x01800090; /* PI_INT_PEND_MOD off*/ - bridge->b_dir_map = (masterwid << 20); /* DMA */ - bridge->b_int_enable = 0; - for (slot = 0; slot < 8; slot ++) { - bridge->b_device[slot].reg |= BRIDGE_DEV_SWAP_DIR; + for (slot = 0; slot < BRIDGE_DEV_CNT; slot++) { +// bridge->b_device[slot].reg |= (BRIDGE_DEV_SWAP_DIR | + bridge->b_device[slot].reg |= (BRIDGE_DEV_ERR_LOCK_EN | + BRIDGE_DEV_D64_BITS); bc->pci_int[slot] = -1; } - bridge->b_wid_tflush; /* wait until Bridge PIO complete */ - bc->base = bridge; + /* Configure direct-mapped DMA */ + bridge->b_dir_map = (masterwid << BRIDGE_DIRMAP_W_ID_SHFT); - register_pci_controller(&bc->pc); + bridge->b_int_enable = BRIDGE_ISR_ERRORS; + + /* Wait until Bridge PIO complete */ + while(bridge->b_wid_tflush) + cpu_relax(); + bc->base = bridge; num_bridges++; + spin_unlock_irqrestore(&bc->lock, flags); + + register_pci_controller(&bc->pc); return 0; } @@ -142,23 +155,24 @@ int bridge_probe(nasid_t nasid, int widget_id, int masterwid) * 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. */ -int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +int __init +pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { return 0; } static inline struct pci_dev *bridge_root_dev(struct pci_dev *dev) { - while (dev->bus->parent) { - /* Move up the chain of bridges. */ + /* Move up the chain of bridges. */ + while (dev->bus->parent) 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) +int +pcibios_plat_dev_init(struct pci_dev *dev) { struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus); struct pci_dev *rdev = bridge_root_dev(dev); @@ -167,15 +181,15 @@ int pcibios_plat_dev_init(struct pci_dev *dev) irq = bc->pci_int[slot]; if (irq == -1) { - irq = request_bridge_irq(bc); + irq = ip27_request_irq(); if (irq < 0) return irq; bc->pci_int[slot] = irq; } - irq_to_bridge[irq] = bc; - irq_to_slot[irq] = slot; + ip27_irq_to_bridge[irq] = bc; + ip27_irq_to_slot[irq] = slot; dev->irq = irq; @@ -189,7 +203,8 @@ int pcibios_plat_dev_init(struct pci_dev *dev) * settings. */ -static inline void pci_disable_swapping(struct pci_dev *dev) +static inline void +pci_disable_swapping(struct pci_dev *dev) { struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus); bridge_t *bridge = bc->base; @@ -200,7 +215,8 @@ static inline void pci_disable_swapping(struct pci_dev *dev) bridge->b_widget.w_tflush; /* Flush */ } -static inline void pci_enable_swapping(struct pci_dev *dev) +static inline void +pci_enable_swapping(struct pci_dev *dev) { struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus); bridge_t *bridge = bc->base; @@ -211,13 +227,15 @@ static inline void pci_enable_swapping(struct pci_dev *dev) bridge->b_widget.w_tflush; /* Flush */ } -static void pci_fixup_ioc3(struct pci_dev *d) +static void +pci_fixup_ioc3(struct pci_dev *d) { pci_disable_swapping(d); } #ifdef CONFIG_NUMA -int pcibus_to_node(struct pci_bus *bus) +int +pcibus_to_node(struct pci_bus *bus) { struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); @@ -228,3 +246,26 @@ EXPORT_SYMBOL(pcibus_to_node); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, pci_fixup_ioc3); + +static int +ip27_bridge_probe(struct platform_device *pdev) +{ + struct xwidget_platform_data *pdata; + + /* Get the platform data. */ + pdata = (struct xwidget_platform_data *) pdev->dev.platform_data; + if (!pdata) + return -ENODEV; + + return bridge_probe(pdata->nasid, pdev->id, pdata->master_wid); +} + +static struct platform_driver +ip27_bridge_driver = { + .probe = ip27_bridge_probe, + /* BRIDGE cannot be dynamically removed. */ + .driver = { + .name = "bridge", + }, +}; +builtin_platform_driver(ip27_bridge_driver) diff --git a/arch/mips/sgi-ip27/Makefile b/arch/mips/sgi-ip27/Makefile index ab4affa..3283a30 100644 --- a/arch/mips/sgi-ip27/Makefile +++ b/arch/mips/sgi-ip27/Makefile @@ -9,3 +9,4 @@ obj-y := ip27-berr.o ip27-irq.o ip27-irqno.o ip27-init.o ip27-klconfig.o \ obj-$(CONFIG_EARLY_PRINTK) += ip27-console.o obj-$(CONFIG_PCI) += ip27-irq-pci.o obj-$(CONFIG_SMP) += ip27-smp.o +obj-$(CONFIG_RTC_DRV_M48T35) += ip27-rtc.o diff --git a/arch/mips/sgi-ip27/ip27-console.c b/arch/mips/sgi-ip27/ip27-console.c index 225a13e..5bcac4a 100644 --- a/arch/mips/sgi-ip27/ip27-console.c +++ b/arch/mips/sgi-ip27/ip27-console.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -19,21 +20,26 @@ #define IOC3_CLK (22000000 / 3) #define IOC3_FLAGS (0) -static inline struct ioc3_uartregs *console_uart(void) +static inline struct ioc3_uartregs * +console_uart(void) { struct ioc3 *ioc3; nasid_t nasid; - nasid = (master_nasid == INVALID_NASID) ? get_nasid() : master_nasid; - ioc3 = (struct ioc3 *)KL_CONFIG_CH_CONS_INFO(nasid)->memory_base; + nasid = ((master_nasid == INVALID_NASID) ? ip27_get_nasid() : + master_nasid); + ioc3 = (struct ioc3 *)KL_CONFIG_CONS_INFO(nasid)->memory_base; return &ioc3->sregs.uarta; } -void prom_putchar(char c) +void +prom_putchar(char c) { struct ioc3_uartregs *uart = console_uart(); - while ((uart->iu_lsr & 0x20) == 0); + while ((((u8 __iomem)uart->iu_lsr) & 0x20) == 0) + cpu_relax(); + uart->iu_thr = c; } diff --git a/arch/mips/sgi-ip27/ip27-hubio.c b/arch/mips/sgi-ip27/ip27-hubio.c index 328ceb3..f2d86ef 100644 --- a/arch/mips/sgi-ip27/ip27-hubio.c +++ b/arch/mips/sgi-ip27/ip27-hubio.c @@ -14,35 +14,40 @@ #include -static int force_fire_and_forget = 1; +static int __initdata force_fire_and_forget = 1; + +#if 0 +/* + * XXX: Requires porting from 2.4 arch/ia64/sn/io/io.c the various HUB + * PIO/DMA mapping stuff and setting up generic Xtalk bus support. + */ /** - * hub_pio_map - establish a HUB PIO mapping - * - * @hub: hub to perform PIO mapping on - * @widget: widget ID to perform PIO mapping for + * ip27_hub_pio_map - establish a HUB PIO mapping + * @hub: hub to perform PIO mapping on + * @widget: widget ID to perform PIO mapping for * @xtalk_addr: xtalk_address that needs to be mapped - * @size: size of the PIO mapping - * - **/ -unsigned long hub_pio_map(cnodeid_t cnode, xwidgetnum_t widget, - unsigned long xtalk_addr, size_t size) + * @size: size of the PIO mapping + */ +u64 +ip27_hub_pio_map(cnodeid_t cnode, xwidgetnum_t widget, + unsigned long xtalk_addr, size_t size) { - nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode); + nasid_t nasid = sn_cnodeid_to_nasid[cnode]; unsigned i; /* use small-window mapping if possible */ if ((xtalk_addr % SWIN_SIZE) + size <= SWIN_SIZE) - return NODE_SWIN_BASE(nasid, widget) + (xtalk_addr % SWIN_SIZE); + return (NODE_SWIN_BASE(nasid, widget) + + (xtalk_addr % SWIN_SIZE)); if ((xtalk_addr % BWIN_SIZE) + size > BWIN_SIZE) { - printk(KERN_WARNING "PIO mapping at hub %d widget %d addr 0x%lx" - " too big (%ld)\n", - nasid, widget, xtalk_addr, size); + pr_warn("PIO mapping at hub %d, widget %d, addr 0x%lx too big " + "(%ld)\n", nasid, widget, xtalk_addr, size); return 0; } - xtalk_addr &= ~(BWIN_SIZE-1); + xtalk_addr &= ~(BWIN_SIZE - 1); for (i = 0; i < HUB_NUM_BIG_WINDOW; i++) { if (test_and_set_bit(i, hub_data(cnode)->h_bigwin_used)) continue; @@ -65,23 +70,24 @@ unsigned long hub_pio_map(cnodeid_t cnode, xwidgetnum_t widget, IIO_ITTE_PUT(nasid, i, HUB_PIO_MAP_TO_MEM, widget, xtalk_addr); (void) HUB_L(IIO_ITTE_GET(nasid, i)); - return NODE_BWIN_BASE(nasid, widget) + (xtalk_addr % BWIN_SIZE); + return (NODE_BWIN_BASE(nasid, widget) + + (xtalk_addr % BWIN_SIZE)); } - printk(KERN_WARNING "unable to establish PIO mapping for at" - " hub %d widget %d addr 0x%lx\n", - nasid, widget, xtalk_addr); + pr_warn("IP27: Unable to establish PIO mapping for at hub %d, " + "widget %d, addr 0x%lx\n", nasid, widget, xtalk_addr); return 0; } - +#endif /* - * hub_setup_prb(nasid, prbnum, credits, conveyor) + * ip27_hub_setup_prb(nasid, prbnum, credits, conveyor) * - * Put a PRB into fire-and-forget mode if conveyor isn't set. Otherwise, - * put it into conveyor belt mode with the specified number of credits. + * Put a PRB into fire-and-forget mode if conveyor isn't set. Otherwise, + * put it into conveyor belt mode with the specified number of credits. */ -static void hub_setup_prb(nasid_t nasid, int prbnum, int credits) +static void __init +ip27_hub_setup_prb(nasid_t nasid, int prbnum, int credits) { iprb_t prb; int prb_offset; @@ -116,24 +122,24 @@ static void hub_setup_prb(nasid_t nasid, int prbnum, int credits) } /** - * hub_set_piomode - set pio mode for a given hub - * - * @nasid: physical node ID for the hub in question + * ip27_hub_set_piomode - set pio mode for a given hub + * @nasid: physical node ID for the hub in question * * Put the hub into either "PIO conveyor belt" mode or "fire-and-forget" mode. * To do this, we have to make absolutely sure that no PIOs are in progress * so we turn off access to all widgets for the duration of the function. * - * XXX - This code should really check what kind of widget we're talking + * XXX: This code should really check what kind of widget we're talking * to. Bridges can only handle three requests, but XG will do more. * How many can crossbow handle to widget 0? We're assuming 1. * - * XXX - There is a bug in the crossbow that link reset PIOs do not + * XXX: There is a bug in the crossbow that link reset PIOs do not * return write responses. The easiest solution to this problem is to * leave widget 0 (xbow) in fire-and-forget mode at all times. This * only affects pio's to xbow registers, which should be rare. **/ -static void hub_set_piomode(nasid_t nasid) +static void __init +ip27_hub_set_piomode(nasid_t nasid) { hubreg_t ii_iowa; hubii_wcr_t ii_wcr; @@ -148,12 +154,12 @@ static void hub_set_piomode(nasid_t nasid) /* * Assume a bridge here. */ - hub_setup_prb(nasid, 0, 3); + ip27_hub_setup_prb(nasid, 0, 3); } else { /* * Assume a crossbow here. */ - hub_setup_prb(nasid, 0, 1); + ip27_hub_setup_prb(nasid, 0, 1); } /* @@ -161,19 +167,19 @@ static void hub_set_piomode(nasid_t nasid) * when account assigning credits. */ for (i = HUB_WIDGET_ID_MIN; i <= HUB_WIDGET_ID_MAX; i++) - hub_setup_prb(nasid, i, 3); + ip27_hub_setup_prb(nasid, i, 3); REMOTE_HUB_S(nasid, IIO_OUTWIDGET_ACCESS, ii_iowa); } -/* - * hub_pio_init - PIO-related hub initialization - * - * @hub: hubinfo structure for our hub +/** + * ip27_hub_pio_init - PIO-related hub initialization. + * @cnode: cnodeid_t value for the cnode to init. */ -void hub_pio_init(cnodeid_t cnode) +void __init +ip27_hub_pio_init(cnodeid_t cnode) { - nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode); + nasid_t nasid = sn_cnodeid_to_nasid[cnode]; unsigned i; /* initialize big window piomaps for this hub */ @@ -181,5 +187,5 @@ void hub_pio_init(cnodeid_t cnode) for (i = 0; i < HUB_NUM_BIG_WINDOW; i++) IIO_ITTE_DISABLE(nasid, i); - hub_set_piomode(nasid); + ip27_hub_set_piomode(nasid); } diff --git a/arch/mips/sgi-ip27/ip27-init.c b/arch/mips/sgi-ip27/ip27-init.c index 6997b1e..eec905e 100644 --- a/arch/mips/sgi-ip27/ip27-init.c +++ b/arch/mips/sgi-ip27/ip27-init.c @@ -6,79 +6,153 @@ * Copyright (C) 2000 - 2001 by Kanoj Sarcar (kanoj@sgi.com) * Copyright (C) 2000 - 2001 by Silicon Graphics, Inc. */ -#include +#include #include -#include -#include +#include #include #include -#include +#include +#include + +#include #include +#include #include +#include +#include #include +#include +#include #include -#include -#include -#include -#include -#include -#include -#include + +#include #include #include #include -#include -#include -#include -#include +#include #include +#include #include +#include +#include +#include +#include #include -#include -#define CPU_NONE (cpuid_t)-1 +#include static DECLARE_BITMAP(hub_init_mask, MAX_COMPACT_NODES); 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]; +DEFINE_PER_CPU(cnodeid_t, __sn_cnodeid_to_nasid[MAX_COMPACT_NODES]); +EXPORT_PER_CPU_SYMBOL(__sn_cnodeid_to_nasid); + +DEFINE_PER_CPU(nasid_t, __sn_nasid_to_cnodeid[MAX_NASIDS]); +EXPORT_PER_CPU_SYMBOL(__sn_nasid_to_cnodeid); + +DEFINE_PER_CPU(cnodeid_t, __sn_cpuid_to_cnodeid[MAXCPUS]); +EXPORT_PER_CPU_SYMBOL(__sn_cpuid_to_cnodeid); + +DEFINE_PER_CPU(struct ip27_percpu_data, ip27_cpu); +EXPORT_PER_CPU_SYMBOL(ip27_cpu); -EXPORT_SYMBOL(nasid_to_compact_node); +/* XXX: Found in 2.4 arch/ia64/sn/io/ml_SN_init.c */ +static DEFINE_SPINLOCK(ip27_hub_lock); +/* XXX: Kill */ struct cpuinfo_ip27 sn_cpu_info[NR_CPUS]; EXPORT_SYMBOL_GPL(sn_cpu_info); -extern void pcibr_setup(cnodeid_t); -extern void xtalk_probe_node(cnodeid_t nid); -static void per_hub_init(cnodeid_t cnode) +/* ----------------------------------------------------------------------- */ +/* IP27 Initialization routines. */ + +/* + * ip27_get_nasid() returns the physical node id number of the caller. + */ +nasid_t +ip27_get_nasid(void) +{ + return (nasid_t)((LOCAL_HUB_L(NI_STATUS_REV_ID) & NSRI_NODEID_MASK) >> + NSRI_NODEID_SHFT); +} + +/* + * Map the physical node id to a virtual node id (virtual node ids are + * contiguous). + * + * XXX: Can be replaced with a macro. + */ +static inline cnodeid_t +ip27_get_compact_nodeid(void) +{ + return sn_nasid_to_cnodeid[ip27_get_nasid()]; +} + +/** + * ip27_hub_clock_init - enable/set the various clocks on a HUB. + * @cnode: compact nodeid of the current node. + * + * We only need to initialize the current node. If this is not the current + * node, then it is a cpuless (headless) node and timeouts will not happen + * there. + */ +static void __init +ip27_hub_clock_init(cnodeid_t cnode) +{ + if (ip27_get_compact_nodeid() == cnode) { + LOCAL_HUB_S(PI_RT_EN_A, 1); + LOCAL_HUB_S(PI_RT_EN_B, 1); + LOCAL_HUB_S(PI_PROF_EN_A, 0); + LOCAL_HUB_S(PI_PROF_EN_B, 0); + LOCAL_HUB_S(PI_RT_COUNT, 0); + LOCAL_HUB_S(PI_RT_PEND_A, 0); + LOCAL_HUB_S(PI_RT_PEND_B, 0); + } +} + +/** + * ip27_per_hub_init - initialize each HUB on a node. + * @cnode: compact nodeid of the current node. + */ +static void +ip27_per_hub_init(cnodeid_t cnode) { struct hub_data *hub = hub_data(cnode); - nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode); + nasid_t nasid = sn_cnodeid_to_nasid[cnode]; int i; + spin_lock(&ip27_hub_lock); cpumask_set_cpu(smp_processor_id(), &hub->h_cpus); - if (test_and_set_bit(cnode, hub_init_mask)) + if (test_and_set_bit(cnode, hub_init_mask)) { + spin_unlock(&ip27_hub_lock); return; + } + spin_unlock(&ip27_hub_lock); + /* - * Set CRB timeout at 5ms, (< PI timeout of 10ms) + * XXX: Set CRB timeout to be 10ms. + * Found in old arch/ia64 2.4 code. It works for + * SN1, so why not SN0? */ - REMOTE_HUB_S(nasid, IIO_ICTP, 0x800); + REMOTE_HUB_S(nasid, IIO_ICTP, 0x1000 ); +// /* +// * Set CRB timeout at 5ms, (< PI timeout of 10ms) +// */ +// REMOTE_HUB_S(nasid, IIO_ICTP, 0x800); REMOTE_HUB_S(nasid, IIO_ICTO, 0xff); - hub_rtc_init(cnode); - xtalk_probe_node(cnode); + ip27_hub_clock_init(cnode); + ip27_hub_pio_init(cnode); #ifdef CONFIG_REPLICATE_EXHANDLERS /* * If this is not a headless node initialization, * copy over the caliased exception handlers. */ - if (get_compact_nodeid() == cnode) { + if (ip27_get_compact_nodeid() == cnode) { extern char except_vec2_generic, except_vec3_generic; extern void build_tlb_refill_handler(void); @@ -110,72 +184,113 @@ static void per_hub_init(cnodeid_t cnode) } } -void per_cpu_init(void) +/** + * ip27_cpu_time_init - platform time initialization. + */ +static void __init +ip27_cpu_time_init(void) +{ + struct klc_lboard *brd; + struct klc_cpu *cpu; + int cpuid; + + /* Don't use ARCS. ARCS is fragile. Klconfig is simple and sane. */ + brd = kl_find_lboard(KLCF_LBOARD_INFO(ip27_get_nasid()), KLTYPE_IP27); + if (!brd) + panic("IP27: Can't find board info for myself?"); + + cpuid = (LOCAL_HUB_L(PI_CPU_NUM) ? IP27_CPU0_INDEX : IP27_CPU1_INDEX); + cpu = KLCF_CAST_CPU(KLCF_COMP(brd, cpuid)); + if (!cpu) + panic("IP27: No information about myself?"); + + mips_hpt_frequency = (read_c0_count() * 10); + pr_info("IP27: CPU%d: %d MHz CPU detected.\n", smp_processor_id(), + cpu->speed); + + set_c0_status(STATUSF_IP4); /* SRB_TIMOCLK */ +} + +void __init +ip27_per_cpu_init(void) { int cpu = smp_processor_id(); int slice = LOCAL_HUB_L(PI_CPU_NUM); - cnodeid_t cnode = get_compact_nodeid(); + cnodeid_t cnode = ip27_get_compact_nodeid(); struct hub_data *hub = hub_data(cnode); - struct slice_data *si = hub->slice + slice; + struct ip27_percpu_data *cpud = this_cpu_ptr(&ip27_cpu); int i; if (test_and_set_bit(slice, &hub->slice_map)) return; + /* Disable all interrupts. */ clear_c0_status(ST0_IM); - per_hub_init(cnode); + /* Populate the percpu struct for IP27 CPU data. */ + cpud->id = cpu; + cpud->nasid = ip27_get_nasid(); + cpud->cnodeid = cnode; + cpud->slice = slice; + + /* Initialize the array tracking which CPU owns what IRQ number. */ + for (i = 0; i < BITS_PER_SLICE; i++) { + cpud->irq_owner[i] = false; + cpud->irq_to_bit[i] = -1; + cpud->bit_to_irq[i] = -1; + __clear_bit(i, cpud->irq_mask); + } - for (i = 0; i < LEVELS_PER_SLICE; i++) - si->level_to_irq[i] = -1; + /* Run necessary HUB init code if not already done. */ + ip27_per_hub_init(cnode); - /* - * We use this so we can find the local hub's data as fast as only - * possible. - */ - cpu_data[cpu].data = si; + if (cpu != 0) { + /* Copy CPU0's sn_cnodeid_to_nasid table to this cpu. */ + memcpy(sn_cnodeid_to_nasid, + (&per_cpu(__sn_cnodeid_to_nasid, 0)), + sizeof(this_cpu_ptr(__sn_cnodeid_to_nasid))); - cpu_time_init(); - install_ipi(); + /* Copy CPU0's sn_nasid_to_cnodeid table to this cpu. */ + memcpy(sn_nasid_to_cnodeid, + (&per_cpu(__sn_nasid_to_cnodeid, 0)), + sizeof(this_cpu_ptr(__sn_nasid_to_cnodeid))); - /* Install our NMI handler if symmon hasn't installed one. */ - install_cpu_nmi_handler(cputoslice(cpu)); + /* Copy CPU0's sn_cpuid_to_cnodeid table to this cpu. */ + memcpy(sn_cpuid_to_cnodeid, + (&per_cpu(__sn_cpuid_to_cnodeid, 0)), + sizeof(this_cpu_ptr(__sn_cpuid_to_cnodeid))); + } - set_c0_status(SRB_DEV0 | SRB_DEV1); -} + /* Done with ip27_percpu_data. */ + cpud->hub = hub; + smp_wmb(); -/* - * get_nasid() returns the physical node id number of the caller. - */ -nasid_t -get_nasid(void) -{ - return (nasid_t)((LOCAL_HUB_L(NI_STATUS_REV_ID) & NSRI_NODEID_MASK) - >> NSRI_NODEID_SHFT); -} + ip27_cpu_time_init(); + ip27_install_ipi(); -/* - * Map the physical node id to a virtual node id (virtual node ids are contiguous). - */ -cnodeid_t get_compact_nodeid(void) -{ - return NASID_TO_COMPACT_NODEID(get_nasid()); + /* Install our NMI handler if symmon hasn't installed one. */ + ip27_install_cpu_nmi_handler(slice); + + set_c0_status((STATUSF_IP2)); // | STATUSF_IP6)); // | STATUSF_IP3)); } -static inline void ioc3_eth_init(void) +static inline void +ip27_ioc3_eth_init(void) { struct ioc3 *ioc3; nasid_t nid; - nid = get_nasid(); - ioc3 = (struct ioc3 *) KL_CONFIG_CH_CONS_INFO(nid)->memory_base; + nid = ip27_get_nasid(); + ioc3 = (struct ioc3 *)KL_CONFIG_CONS_INFO(nid)->memory_base; ioc3->eier = 0; } extern void ip27_reboot_setup(void); +extern void ip27_be_init(void); -void __init plat_mem_setup(void) +void __init +plat_mem_setup(void) { hubreg_t p, e, n_mode; nasid_t nid; @@ -185,27 +300,27 @@ void __init plat_mem_setup(void) /* * hub_rtc init and cpu clock intr enabled for later calibrate_delay. */ - nid = get_nasid(); - printk("IP27: Running on node %d.\n", nid); + nid = ip27_get_nasid(); + pr_info("IP27: Running on node %d.\n", nid); - p = LOCAL_HUB_L(PI_CPU_PRESENT_A) & 1; - e = LOCAL_HUB_L(PI_CPU_ENABLE_A) & 1; - printk("Node %d has %s primary CPU%s.\n", nid, - p ? "a" : "no", - e ? ", CPU is running" : ""); + p = (LOCAL_HUB_L(PI_CPU_PRESENT_A) & 1); + e = (LOCAL_HUB_L(PI_CPU_ENABLE_A) & 1); + pr_info("IP27: Node %d has %s primary CPU%s.\n", nid, + p ? "a" : "no", + e ? ", CPU is running" : ""); - p = LOCAL_HUB_L(PI_CPU_PRESENT_B) & 1; - e = LOCAL_HUB_L(PI_CPU_ENABLE_B) & 1; - printk("Node %d has %s secondary CPU%s.\n", nid, - p ? "a" : "no", - e ? ", CPU is running" : ""); + p = (LOCAL_HUB_L(PI_CPU_PRESENT_B) & 1); + e = (LOCAL_HUB_L(PI_CPU_ENABLE_B) & 1); + pr_info("IP27: Node %d has %s secondary CPU%s.\n", nid, + p ? "a" : "no", + e ? ", CPU is running" : ""); /* * Try to catch kernel missconfigurations and give user an * indication what option to select. */ n_mode = LOCAL_HUB_L(NI_STATUS_REV_ID) & NSRI_MORENODES_MASK; - printk("Machine is in %c mode.\n", n_mode ? 'N' : 'M'); + pr_info("IP27: Machine is in %c mode.\n", n_mode ? 'N' : 'M'); #ifdef CONFIG_SGI_SN_N_MODE if (!n_mode) panic("Kernel compiled for M mode."); @@ -214,8 +329,9 @@ void __init plat_mem_setup(void) panic("Kernel compiled for N mode."); #endif - ioc3_eth_init(); - per_cpu_init(); + ip27_ioc3_eth_init(); + ip27_per_cpu_init(); + ip27_be_init(); set_io_port_base(IO_BASE); } diff --git a/arch/mips/sgi-ip27/ip27-irq-pci.c b/arch/mips/sgi-ip27/ip27-irq-pci.c index 2a1c407..9274575 100644 --- a/arch/mips/sgi-ip27/ip27-irq-pci.c +++ b/arch/mips/sgi-ip27/ip27-irq-pci.c @@ -10,256 +10,386 @@ #include #include -#include -#include #include #include -#include -#include -#include -#include -#include -#include -#include #include +#include #include #include #include -#include #include #include #include #include #include #include +#include -/* - * Linux has a controller-independent x86 interrupt architecture. - * every controller has a 'controller-template', that is used - * by the main code to do the right thing. Each driver-visible - * interrupt source is transparently wired to the appropriate - * controller. Thus drivers need not be aware of the - * interrupt-controller. - * - * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC, - * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC. - * (IO-APICs assumed to be messaging to Pentium local-APICs) - * - * the code is designed to be easily extended with new/different - * interrupt controllers, without having to do assembly magic. - */ +#include -extern struct bridge_controller *irq_to_bridge[]; -extern int irq_to_slot[]; +#undef IP27_DEBUG_IRQ -/* - * use these macros to get the encoded nasid and widget id - * from the irq value - */ -#define IRQ_TO_BRIDGE(i) irq_to_bridge[(i)] -#define SLOT_FROM_PCI_IRQ(i) irq_to_slot[i] +/* Defined in ip27-init.c */ +DECLARE_PER_CPU(struct ip27_percpu_data, ip27_cpu); -static inline int alloc_level(int cpu, int irq) -{ - struct hub_data *hub = hub_data(cpu_to_node(cpu)); - struct slice_data *si = cpu_data[cpu].data; - int level; +/* Defined in ip27-irq.c */ +extern struct bridge_controller *ip27_irq_to_bridge[PCIBR_MAX_BUS_X_DEV]; +extern u32 ip27_irq_to_slot[PCIBR_MAX_BUS_X_DEV]; - level = find_first_zero_bit(hub->irq_alloc_mask, LEVELS_PER_SLICE); - if (level >= LEVELS_PER_SLICE) - panic("Cpu %d flooded with devices", cpu); - __set_bit(level, hub->irq_alloc_mask); - si->level_to_irq[level] = irq; +/* ----------------------------------------------------------------------- */ +/* HUB Interrupt Bit Ops */ - return level; +/** + * ip27_assign_hub_bit - assigns a free interrupt bit in the HUB to an irq. + * @cpu: int value of cpu to handle the irq. + * @irq: int value of irq to assign. + * + * Returns the assigned bit. + * + * Interrupt mapping on IP27 is not straight-forward. An IRQ number can be + * assigned to any CPU attached to a given HUB chip in any node of the machine. + * This function finds the first free bit in HUB's irq_enable_mask and assigns + * that bit to the requested IRQ number on the specified cpu. + * + * Previously, a "bit" was known as a "level", as IRIX refers to it. But + * this is Linux, not IRIX. + */ +static int +ip27_assign_hub_bit(u32 cpu, int irq) +{ + struct ip27_percpu_data *cpud = &per_cpu(ip27_cpu, cpu); + struct hub_data *hub = cpud->hub; + u32 bit; + + bit = find_first_zero_bit(hub->irq_alloc_mask, LEVELS_PER_SLICE); + if (bit >= LEVELS_PER_SLICE) + panic("IP27: Cpu %d flooded with devices", cpu); + + smp_mb__before_atomic(); + set_bit(bit, hub->irq_alloc_mask); + cpud->irq_owner[irq] = true; + cpud->irq_to_bit[irq] = bit; + cpud->bit_to_irq[bit] = irq; + smp_mb__after_atomic(); + + return bit; } -static inline int find_level(cpuid_t *cpunum, int irq) +/** + * ip27_update_hub_irq_mask - updates irq_enable_mask on a specific HUB/CPU. + * @cpud: const pointer to the percpu ip27_percpu_data structure. + */ +static inline void +ip27_update_hub_irq_mask(const struct ip27_percpu_data __percpu *cpud) { - int cpu, i; + if (!cpud->slice) { + REMOTE_HUB_S(cpud->nasid, PI_INT_MASK0_A, cpud->irq_mask[0]); + REMOTE_HUB_S(cpud->nasid, PI_INT_MASK1_A, cpud->irq_mask[1]); + } else { + REMOTE_HUB_S(cpud->nasid, PI_INT_MASK0_B, cpud->irq_mask[0]); + REMOTE_HUB_S(cpud->nasid, PI_INT_MASK1_B, cpud->irq_mask[1]); + } +} - for_each_online_cpu(cpu) { - struct slice_data *si = cpu_data[cpu].data; +/** + * ip27_set_hub_bit - sets a bit in irq_enable_mask for a specific HUB/CPU. + * @bit: int value of the interrupt bit to set. + */ +static inline void +ip27_set_hub_bit(int bit) +{ + struct ip27_percpu_data *cpud = this_cpu_ptr(&ip27_cpu); - for (i = BASE_PCI_IRQ; i < LEVELS_PER_SLICE; i++) - if (si->level_to_irq[i] == irq) { - *cpunum = cpu; + set_bit(bit, cpud->irq_mask); + ip27_update_hub_irq_mask(cpud); +} - return i; - } - } +/** + * ip27_clear_hub_bit - clears a bit in irq_enable_mask for a specific HUB/CPU. + * @bit: int value of the interrupt bit to clear. + */ +static inline void +ip27_clear_hub_bit(int bit) +{ + struct ip27_percpu_data *cpud = this_cpu_ptr(&ip27_cpu); - panic("Could not identify cpu/level for irq %d", irq); + clear_bit(bit, cpud->irq_mask); + ip27_update_hub_irq_mask(cpud); } -static int intr_connect_level(int cpu, int bit) +/** + * ip27_find_irq_owner - find which cpu owns an IRQ number. + * @irq: int value of irq number to find the owner of. + * + * Returns the CPU number whose percpu 'irq_owner' field is set to + * 'true' for the specified IRQ number, else returns -1. + */ +static inline int +ip27_find_irq_owner(int irq) { - nasid_t nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu)); - struct slice_data *si = cpu_data[cpu].data; - - set_bit(bit, si->irq_enable_mask); + u32 cpu; - if (!cputoslice(cpu)) { - REMOTE_HUB_S(nasid, PI_INT_MASK0_A, si->irq_enable_mask[0]); - REMOTE_HUB_S(nasid, PI_INT_MASK1_A, si->irq_enable_mask[1]); - } else { - REMOTE_HUB_S(nasid, PI_INT_MASK0_B, si->irq_enable_mask[0]); - REMOTE_HUB_S(nasid, PI_INT_MASK1_B, si->irq_enable_mask[1]); - } + for_each_possible_cpu(cpu) + if (per_cpu(ip27_cpu, cpu).irq_owner[irq]) + return cpu; - return 0; + return -1; } -static int intr_disconnect_level(int cpu, int bit) +/** + * ip27_which_cpu - which CPU slice a given CPU is in. + * @slice: u32 value of CPU slice number. + * + * Returns char 'A' if CPU is in first slice, else 'B'. + */ +static inline char +ip27_which_cpu(u8 slice) { - nasid_t nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu)); - struct slice_data *si = cpu_data[cpu].data; + return (!slice ? 'A' : 'B'); +} - clear_bit(bit, si->irq_enable_mask); +/* ----------------------------------------------------------------------- */ - if (!cputoslice(cpu)) { - REMOTE_HUB_S(nasid, PI_INT_MASK0_A, si->irq_enable_mask[0]); - REMOTE_HUB_S(nasid, PI_INT_MASK1_A, si->irq_enable_mask[1]); - } else { - REMOTE_HUB_S(nasid, PI_INT_MASK0_B, si->irq_enable_mask[0]); - REMOTE_HUB_S(nasid, PI_INT_MASK1_B, si->irq_enable_mask[1]); - } - return 0; -} +/* ----------------------------------------------------------------------- */ +/* HUB IRQ Ops */ -/* Startup one of the (PCI ...) IRQs routes over a bridge. */ -static unsigned int startup_bridge_irq(struct irq_data *d) +/** + * ip27_startup_hub_irq - assigns a HUB IRQ to a CPU and/or Bridge slot. + * @d: struct irq_data containing IRQ information. + * + * Returns 0. + */ +static unsigned int +ip27_startup_hub_irq(struct irq_data *d) { - struct bridge_controller *bc; + u32 slot; + int hub_bit, irq_owner; bridgereg_t device; bridge_t *bridge; - int pin, swlevel; - cpuid_t cpu; + struct bridge_controller *bc; + const struct ip27_percpu_data *cpud = this_cpu_ptr(&ip27_cpu); + + irq_owner = ip27_find_irq_owner(d->irq); + if (irq_owner != -1 && irq_owner != cpud->id) { + pr_err("IP27: %s: bad IRQ startup request " + "for duplicate IRQ %d on CPU %d%c (already assigned " + "to CPU %d%c)!\n", __func__, d->irq, (cpud->nasid + 1), + ip27_which_cpu(cpud->slice), + (per_cpu(ip27_cpu, irq_owner).nasid + 1), + ip27_which_cpu(per_cpu(ip27_cpu, irq_owner).slice)); + return 0; + } - pin = SLOT_FROM_PCI_IRQ(d->irq); - bc = IRQ_TO_BRIDGE(d->irq); - bridge = bc->base; +#ifdef IP27_DEBUG_IRQ + pr_debug("IP27: %s: IRQ %d on CPU %d%c!\n", __func__, d->irq, + nasid, ip27_which_cpu(cpud->slice)); +#endif - pr_debug("bridge_startup(): irq= 0x%x pin=%d\n", d->irq, pin); - /* - * "map" irq to a swlevel greater than 6 since the first 6 bits - * of INT_PEND0 are taken - */ - swlevel = find_level(&cpu, d->irq); - bridge->b_int_addr[pin].addr = (0x20000 | swlevel | (bc->nasid << 8)); - bridge->b_int_enable |= (1 << pin); - bridge->b_int_enable |= 0x7ffffe00; /* more stuff in int_enable */ + hub_bit = cpud->irq_to_bit[d->irq]; /* - * Enable sending of an interrupt clear packt to the hub on a high to - * low transition of the interrupt pin. + * Handle BRIDGE IRQs. * - * IRIX sets additional bits in the address which are documented as - * reserved in the bridge docs. - */ - bridge->b_int_mode |= (1UL << pin); - - /* - * We assume the bridge to have a 1:1 mapping between devices - * (slots) and intr pins. + * bridge->b_int_addr[slot].addr - Points to the HUB that this BRIDGE + * is assigned to, so that BRIDGE can frob the PI_INT_PEND_MOD + * register directly, without having to know which nasid the + * specific HUB is on. + * + * bridge->b_int_mode - IRIX supposedly sets additional bits in this + * register that are marked as reserved by the BRIDGE spec. But + * we don't do this in Linux because we have no idea why IRIX + * is doing it. + * + * bridge->b_int_device - We assume the bridge to have a 1:1 mapping + * between devices (slots) and interrupt numbers. */ - device = bridge->b_int_device; - device &= ~(7 << (pin*3)); - device |= (pin << (pin*3)); - bridge->b_int_device = device; + bc = ip27_irq_to_bridge[d->irq]; + if (bc) { + bridge = bc->base; + if (bridge) { + slot = ip27_irq_to_slot[d->irq]; + bridge->b_int_addr[slot].addr = + (0x20000 | hub_bit | (bc->nasid << 8)); + bridge->b_int_enable |= ((1 << slot) | 0x7ffffe00); + bridge->b_int_mode |= (1UL << slot); + device = bridge->b_int_device; + device &= ~BRIDGE_INT_DEV_MASK(slot); + device |= BRIDGE_INT_DEV_SET(slot, slot); + bridge->b_int_device = device; + bridge->b_wid_tflush; + } + } - bridge->b_wid_tflush; + pr_debug("IP27: %s: irq=%d startup on CPU%d\n", __func__, + d->irq, cpud->id); - intr_connect_level(cpu, swlevel); + /* Unmask IRQ */ + ip27_set_hub_bit(hub_bit); - return 0; /* Never anything pending. */ + /* Never anything pending. */ + return 0; } -/* Shutdown one of the (PCI ...) IRQs routes over a bridge. */ -static void shutdown_bridge_irq(struct irq_data *d) +/** + * ip27_shutdown_hub_irq - removes a HUB IRQ from a CPU and/or Bridge slot. + * @d: struct irq_data containing IRQ information. + */ +static void +ip27_shutdown_hub_irq(struct irq_data *d) { - struct bridge_controller *bc = IRQ_TO_BRIDGE(d->irq); - bridge_t *bridge = bc->base; - int pin, swlevel; - cpuid_t cpu; + struct bridge_controller *bc; + bridge_t *bridge; - pr_debug("bridge_shutdown: irq 0x%x\n", d->irq); - pin = SLOT_FROM_PCI_IRQ(d->irq); + /* Mask the IRQ on HUB */ + ip27_clear_hub_bit(d->irq); - /* - * map irq to a swlevel greater than 6 since the first 6 bits - * of INT_PEND0 are taken - */ - swlevel = find_level(&cpu, d->irq); - intr_disconnect_level(cpu, swlevel); + /* Ditto for BRIDGE */ + bc = ip27_irq_to_bridge[d->irq]; + bridge = bc->base; + if (bridge) { + bridge->b_int_enable &= ~(BIT(ip27_irq_to_slot[d->irq])); + bridge->b_wid_tflush; + } - bridge->b_int_enable &= ~(1 << pin); - bridge->b_wid_tflush; + pr_debug("IP27: %s: irq=%d shutdown on CPU%d\n", __func__, + d->irq, this_cpu_read(ip27_cpu.id)); } -static inline void enable_bridge_irq(struct irq_data *d) +/** + * ip27_ack_hub_irq - acks a HUB IRQ. + * @d: struct irq_data containing IRQ information. + */ +static void +ip27_ack_hub_irq(struct irq_data *d) { - cpuid_t cpu; - int swlevel; + /* Ack */ + LOCAL_HUB_CLR_INTR(this_cpu_read(ip27_cpu.irq_to_bit[d->irq])) +} - swlevel = find_level(&cpu, d->irq); /* Criminal offence */ - intr_connect_level(cpu, swlevel); +/** + * ip27_mask_hub_irq - masks a HUB IRQ. + * @d: struct irq_data containing IRQ information. + */ +static void +ip27_mask_hub_irq(struct irq_data *d) +{ + /* Mask */ + ip27_clear_hub_bit(this_cpu_read(ip27_cpu.irq_to_bit[d->irq])); } -static inline void disable_bridge_irq(struct irq_data *d) +/** + * ip27_mask_and_ack_hub_irq - masks and acks a HUB IRQ. + * @d: struct irq_data containing IRQ information. + */ +static void +ip27_mask_and_ack_hub_irq(struct irq_data *d) { - cpuid_t cpu; - int swlevel; + s8 bit = this_cpu_read(ip27_cpu.irq_to_bit[d->irq]); - swlevel = find_level(&cpu, d->irq); /* Criminal offence */ - intr_disconnect_level(cpu, swlevel); -} + /* Mask */ + ip27_clear_hub_bit(bit); -static struct irq_chip bridge_irq_type = { - .name = "bridge", - .irq_startup = startup_bridge_irq, - .irq_shutdown = shutdown_bridge_irq, - .irq_mask = disable_bridge_irq, - .irq_unmask = enable_bridge_irq, -}; + /* Ack */ + LOCAL_HUB_CLR_INTR(bit) +} -void register_bridge_irq(unsigned int irq) +/** + * ip27_unmask_hub_irq - unmasks a HUB IRQ. + * @d: struct irq_data containing IRQ information. + */ +static void +ip27_unmask_hub_irq(struct irq_data *d) { - irq_set_chip_and_handler(irq, &bridge_irq_type, handle_level_irq); + /* Unmask */ + ip27_set_hub_bit(this_cpu_read(ip27_cpu.irq_to_bit[d->irq])); } -int request_bridge_irq(struct bridge_controller *bc) +/** + * struct ip27_hub_irq - HUB struct irq_chip ops. + * @irq_startup: startup function. + * @irq_shutdown: shutdown function. + * @irq_ack: ack function. + * @irq_mask: mask function. + * @irq_mask_ack: mask & ack function. + * @irq_unmask: unmask function. + * @irq_disable: disable (mask) function. + * @irq_enable: enable (unmask) function. + */ +struct irq_chip +ip27_hub_irq = { + .name = "HUB", + .irq_startup = ip27_startup_hub_irq, + .irq_shutdown = ip27_shutdown_hub_irq, + .irq_ack = ip27_ack_hub_irq, + .irq_mask = ip27_mask_hub_irq, + .irq_mask_ack = ip27_mask_and_ack_hub_irq, + .irq_unmask = ip27_unmask_hub_irq, + .irq_disable = ip27_mask_hub_irq, + .irq_enable = ip27_unmask_hub_irq, +}; + +/* ----------------------------------------------------------------------- */ + + +/* ----------------------------------------------------------------------- */ + +/** + * ip27_request_irq - requests an irq number. + * + * Returns allocated IRQ number assigned to a specific HUB interrupt bit. + */ +int +ip27_request_irq(void) { - int irq = allocate_irqno(); - int swlevel, cpu; - nasid_t nasid; + int hub_bit; + int irq = ip27_alloc_irq_num(); + u32 cpu = this_cpu_read(ip27_cpu.id); + /* Bail if ip27_alloc_irq_num() failed. */ if (irq < 0) return irq; - /* - * "map" irq to a swlevel greater than 6 since the first 6 bits - * of INT_PEND0 are taken - */ - cpu = bc->irq_cpu; - swlevel = alloc_level(cpu, irq); - if (unlikely(swlevel < 0)) { - free_irqno(irq); + /* Assign the IRQ to a free HUB interrupt bit. */ + hub_bit = ip27_assign_hub_bit(cpu, irq); - return -EAGAIN; - } + /* Assign the irq_chip handler. */ + irq_set_chip_and_handler(irq, &ip27_hub_irq, handle_level_irq); /* Make sure it's not already pending when we connect it. */ - nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu)); - REMOTE_HUB_CLR_INTR(nasid, swlevel); - - intr_connect_level(cpu, swlevel); + REMOTE_HUB_CLR_INTR(this_cpu_read(ip27_cpu.cnodeid), hub_bit); - register_bridge_irq(irq); + /* Set the bit in HUB. */ + ip27_set_hub_bit(hub_bit); return irq; } + +/* ----------------------------------------------------------------------- */ + + +/* ----------------------------------------------------------------------- */ +/* Arch IRQ initialization - runs on CPU0 only. */ + +/** + * arch_init_irq - arch initialization function. + */ +void __init +arch_init_irq(void) +{ +#ifdef CONFIG_SMP + irq_set_chip_and_handler(CPU_RESCHED_A_IRQ, &ip27_hub_irq, + handle_percpu_irq); + irq_set_chip_and_handler(CPU_RESCHED_B_IRQ, &ip27_hub_irq, + handle_percpu_irq); + irq_set_chip_and_handler(CPU_CALL_A_IRQ, &ip27_hub_irq, + handle_percpu_irq); + irq_set_chip_and_handler(CPU_CALL_B_IRQ, &ip27_hub_irq, + handle_percpu_irq); +#endif +} + +/* ----------------------------------------------------------------------- */ diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c index 16ec4e1..f2a5e33 100644 --- a/arch/mips/sgi-ip27/ip27-irq.c +++ b/arch/mips/sgi-ip27/ip27-irq.c @@ -8,205 +8,230 @@ #undef DEBUG -#include -#include +#include #include -#include -#include -#include #include -#include -#include +#include #include -#include -#include -#include -#include -#include +#include +#include #include #include #include -#include #include #include #include #include #include -/* - * Linux has a controller-independent x86 interrupt architecture. - * every controller has a 'controller-template', that is used - * by the main code to do the right thing. Each driver-visible - * interrupt source is transparently wired to the appropriate - * controller. Thus drivers need not be aware of the - * interrupt-controller. - * - * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC, - * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC. - * (IO-APICs assumed to be messaging to Pentium local-APICs) - * - * the code is designed to be easily extended with new/different - * interrupt controllers, without having to do assembly magic. - */ +#include -extern asmlinkage void ip27_irq(void); +struct bridge_controller *ip27_irq_to_bridge[PCIBR_MAX_BUS_X_DEV]; +u32 ip27_irq_to_slot[PCIBR_MAX_BUS_X_DEV]; -/* - * Find first bit set +/* Defined in ip27-init.c */ +DECLARE_PER_CPU(struct ip27_percpu_data, ip27_cpu); + +/* ----------------------------------------------------------------------- */ +/* HUB Interrupt Handlers */ + +/** + * ip27_find_first_set_msb - finds the first most significant bit set. + * @dword: u64 value in which to find the first bit set. */ -static int ms1bit(unsigned long x) +static inline u32 +ip27_find_first_set_msb(u64 dword) { - int b = 0, s; + /* b: bit, s: shift */ + u32 b = 0, s; - s = 16; if (x >> 16 == 0) s = 0; b += s; x >>= s; - s = 8; if (x >> 8 == 0) s = 0; b += s; x >>= s; - s = 4; if (x >> 4 == 0) s = 0; b += s; x >>= s; - s = 2; if (x >> 2 == 0) s = 0; b += s; x >>= s; - s = 1; if (x >> 1 == 0) s = 0; b += s; + s = 32; if (dword >> s == 0) s = 0; b += s; dword >>= s; + s = 16; if (dword >> s == 0) s = 0; b += s; dword >>= s; + s = 8; if (dword >> s == 0) s = 0; b += s; dword >>= s; + s = 4; if (dword >> s == 0) s = 0; b += s; dword >>= s; + s = 2; if (dword >> s == 0) s = 0; b += s; dword >>= s; + s = 1; if (dword >> s == 0) s = 0; b += s; return b; } -/* - * This code is unnecessarily complex, because we do - * intr enabling. Basically, once we grab the set of intrs we need - * to service, we must mask _all_ these interrupts; firstly, to make - * sure the same intr does not intr again, causing recursion that - * can lead to stack overflow. Secondly, we can not just mask the - * one intr we are do_IRQing, because the non-masked intrs in the - * first set might intr again, causing multiple servicings of the - * same intr. This effect is mostly seen for intercpu intrs. - * Kanoj 05.13.00 +/** + * ip27_do_hub_irq - main interrupt servicing routine for IP27. + * @cpu: u32 value of the cpu processing the interrupt. + * @pend_reg: u32 value of the PEND0/PEND1 register offset. + * @mask_reg: u32 value of the MASK0/MASK1 register offset for a cpu. */ - -static void ip27_do_irq_mask0(void) +static void +ip27_do_hub_irq(u32 pend_reg, u32 mask_reg) { - int irq, swlevel; - hubreg_t pend0, mask0; - cpuid_t cpu = smp_processor_id(); - int pi_int_mask0 = - (cputoslice(cpu) == 0) ? PI_INT_MASK0_A : PI_INT_MASK0_B; - - /* copied from Irix intpend0() */ - pend0 = LOCAL_HUB_L(PI_INT_PEND0); - mask0 = LOCAL_HUB_L(pi_int_mask0); - - pend0 &= mask0; /* Pick intrs we should look at */ - if (!pend0) - return; - - swlevel = ms1bit(pend0); -#ifdef CONFIG_SMP - if (pend0 & (1UL << CPU_RESCHED_A_IRQ)) { - LOCAL_HUB_CLR_INTR(CPU_RESCHED_A_IRQ); - scheduler_ipi(); - } else if (pend0 & (1UL << CPU_RESCHED_B_IRQ)) { - LOCAL_HUB_CLR_INTR(CPU_RESCHED_B_IRQ); - scheduler_ipi(); - } else if (pend0 & (1UL << CPU_CALL_A_IRQ)) { - LOCAL_HUB_CLR_INTR(CPU_CALL_A_IRQ); - irq_enter(); - generic_smp_call_function_interrupt(); - irq_exit(); - } else if (pend0 & (1UL << CPU_CALL_B_IRQ)) { - LOCAL_HUB_CLR_INTR(CPU_CALL_B_IRQ); - irq_enter(); - generic_smp_call_function_interrupt(); - irq_exit(); - } else -#endif - { - /* "map" swlevel to irq */ - struct slice_data *si = cpu_data[cpu].data; - - irq = si->level_to_irq[swlevel]; - do_IRQ(irq); + int irq; + u32 hub_bit; + hubreg_t pend, mask; + + pend = LOCAL_HUB_L(pend_reg); + mask = LOCAL_HUB_L(mask_reg); + while ((pend & mask) != 0) { + pend &= mask; + if (unlikely(!pend)) + continue; + + /* Prevent any of the picked IRQs from recursing */ + LOCAL_HUB_S(mask_reg, mask & ~(pend)); + do { + hub_bit = ip27_find_first_set_msb(pend); + irq = this_cpu_read(ip27_cpu.bit_to_irq[hub_bit]); + do_IRQ(irq); + pend ^= BIT_ULL(hub_bit); + } while (pend); + + /* Now allow the set of serviced IRQs to fire again */ + LOCAL_HUB_S(mask_reg, mask); + pend = LOCAL_HUB_L(pend_reg); } +} - LOCAL_HUB_L(PI_INT_PEND0); +/** + * ip27_do_hub_pend0 - services an interrupt from PEND0. + * @cpu: u32 value of the cpu processing the interrupt. + */ +static void +ip27_do_hub_pend0(void) +{ + int pi_int_mask0 = (!this_cpu_read(ip27_cpu.slice) ? + PI_INT_MASK0_A : PI_INT_MASK0_B); + + ip27_do_hub_irq(PI_INT_PEND0, pi_int_mask0); } -static void ip27_do_irq_mask1(void) +/** + * ip27_do_hub_pend1 - services an interrupt from PEND1. + * @cpu: u32 value of the cpu processing the interrupt. + */ +static void +ip27_do_hub_pend1(void) { - int irq, swlevel; - hubreg_t pend1, mask1; - cpuid_t cpu = smp_processor_id(); - int pi_int_mask1 = (cputoslice(cpu) == 0) ? PI_INT_MASK1_A : PI_INT_MASK1_B; - struct slice_data *si = cpu_data[cpu].data; - - /* copied from Irix intpend0() */ - pend1 = LOCAL_HUB_L(PI_INT_PEND1); - mask1 = LOCAL_HUB_L(pi_int_mask1); - - pend1 &= mask1; /* Pick intrs we should look at */ - if (!pend1) - return; - - swlevel = ms1bit(pend1); - /* "map" swlevel to irq */ - irq = si->level_to_irq[swlevel]; - LOCAL_HUB_CLR_INTR(swlevel); - do_IRQ(irq); - - LOCAL_HUB_L(PI_INT_PEND1); + int pi_int_mask1 = (!this_cpu_read(ip27_cpu.slice) ? + PI_INT_MASK1_A : PI_INT_MASK1_B); + + ip27_do_hub_irq(PI_INT_PEND1, pi_int_mask1); } -static void ip27_prof_timer(void) +/** + * ip27_prof_timer - stub function to handle CAUSEF_IP5 interrupts. + * + * XXX: Currently calls panic() - can we do anything useful instead + * with this interrupt? + */ +static void +ip27_prof_timer(void) { panic("CPU %d got a profiling interrupt", smp_processor_id()); } -static void ip27_hub_error(void) +/** + * ip27_hub_error - stub function to handle HUB error interrupts. + * + * XXX: Currently calls panic() - need to rip HUB error reporting code from + * the old arch/ia64 code in 2.4.x and late 2.5.x kernels, in which SGI + * GPL'ed and imported a large amount of IP27 code straight from IRIX + * during their bringup of the Altix/IA64 platform by using existing + * hardware. + */ +static void +ip27_hub_error(void) { panic("CPU %d got a hub error interrupt", smp_processor_id()); } -asmlinkage void plat_irq_dispatch(void) +/* ----------------------------------------------------------------------- */ + + +/* ----------------------------------------------------------------------- */ + +/** + * plat_irq_dispatch - platform IRQ dispatch. + * + * Interrupts are disabled. + */ +asmlinkage void +plat_irq_dispatch(void) { - unsigned long pending = read_c0_cause() & read_c0_status(); - extern unsigned int rt_timer_irq; - - if (pending & CAUSEF_IP4) - do_IRQ(rt_timer_irq); - else if (pending & CAUSEF_IP2) /* PI_INT_PEND_0 or CC_PEND_{A|B} */ - ip27_do_irq_mask0(); - else if (pending & CAUSEF_IP3) /* PI_INT_PEND_1 */ - ip27_do_irq_mask1(); - else if (pending & CAUSEF_IP5) + unsigned long pending = (read_c0_cause() & read_c0_status()); + extern int ip27_hub_rt_irq_num; /* Defined in ip27-timer.c. */ + + /* IP4, HUB Counter/Compare */ + if (likely(pending & CAUSEF_IP4)) + do_IRQ(ip27_hub_rt_irq_num); + /* IP2, HUB INT_PEND0 (also IPI/SMP IRQs) */ + else if (likely(pending & CAUSEF_IP2)) + ip27_do_hub_pend0(); + /* IP3, HUB INT_PEND1 (Error IRQs) */ + else if (unlikely(pending & CAUSEF_IP3)) + ip27_do_hub_pend1(); + /* IP5, Profiling Clock? (SRB_PROFCLK) */ + else if (unlikely(pending & CAUSEF_IP5)) ip27_prof_timer(); - else if (pending & CAUSEF_IP6) + /* IP6, HUB Errors */ + else if (unlikely(pending & CAUSEF_IP6)) ip27_hub_error(); + +// /* All other interrupt sources */ +// if (unlikely(pending & (CAUSEF_IP0 | CAUSEF_IP1 | CAUSEF_IP7))) { +// pr_err("IP27: %s: spurious interrupt\n", __func__); +// spurious_interrupt(); +// } } -void __init arch_init_irq(void) +/* ----------------------------------------------------------------------- */ + + +/* ----------------------------------------------------------------------- */ + +/** + * __ip27_install_ipi - sets up interprocessor interrupts on each CPU. + * + * XXX: To be moved to ip27-irq.c. + */ +static void __init +__ip27_install_ipi(u32 irq) { + struct ip27_percpu_data *cpud = this_cpu_ptr(&ip27_cpu); + struct hub_data *hub = cpud->hub; + + smp_mb__before_atomic(); + set_bit(irq, hub->irq_alloc_mask); + set_bit(irq, cpud->irq_mask); + cpud->irq_owner[irq] = true; + cpud->irq_to_bit[irq] = irq; + cpud->bit_to_irq[irq] = irq; + smp_mb__after_atomic(); + ip27_force_irq_num(irq); + LOCAL_HUB_CLR_INTR(irq); } -void install_ipi(void) +/** + * ip27_install_ipi - extern func called from either ip27-init or ip27-smp. + * + * XXX: To be moved to ip27-irq.c. + */ +void __init +ip27_install_ipi(void) { - int slice = LOCAL_HUB_L(PI_CPU_NUM); - int cpu = smp_processor_id(); - struct slice_data *si = cpu_data[cpu].data; - struct hub_data *hub = hub_data(cpu_to_node(cpu)); - int resched, call; - - resched = CPU_RESCHED_A_IRQ + slice; - __set_bit(resched, hub->irq_alloc_mask); - __set_bit(resched, si->irq_enable_mask); - LOCAL_HUB_CLR_INTR(resched); - - call = CPU_CALL_A_IRQ + slice; - __set_bit(call, hub->irq_alloc_mask); - __set_bit(call, si->irq_enable_mask); - LOCAL_HUB_CLR_INTR(call); - - if (slice == 0) { - LOCAL_HUB_S(PI_INT_MASK0_A, si->irq_enable_mask[0]); - LOCAL_HUB_S(PI_INT_MASK1_A, si->irq_enable_mask[1]); + const struct ip27_percpu_data *cpud = this_cpu_ptr(&ip27_cpu); + u8 slice = cpud->slice; + + __ip27_install_ipi(CPU_RESCHED_A_IRQ + slice); + __ip27_install_ipi(CPU_CALL_A_IRQ + slice); + + if (!slice) { + LOCAL_HUB_S(PI_INT_MASK0_A, cpud->irq_mask[0]); + LOCAL_HUB_S(PI_INT_MASK1_A, cpud->irq_mask[1]); } else { - LOCAL_HUB_S(PI_INT_MASK0_B, si->irq_enable_mask[0]); - LOCAL_HUB_S(PI_INT_MASK1_B, si->irq_enable_mask[1]); + LOCAL_HUB_S(PI_INT_MASK0_B, cpud->irq_mask[0]); + LOCAL_HUB_S(PI_INT_MASK1_B, cpud->irq_mask[1]); } } + +/* ----------------------------------------------------------------------- */ diff --git a/arch/mips/sgi-ip27/ip27-irqno.c b/arch/mips/sgi-ip27/ip27-irqno.c index 957ab58..9feab33 100644 --- a/arch/mips/sgi-ip27/ip27-irqno.c +++ b/arch/mips/sgi-ip27/ip27-irqno.c @@ -11,14 +11,24 @@ static DECLARE_BITMAP(irq_map, NR_IRQS); -int allocate_irqno(void) + +/* ----------------------------------------------------------------------- */ + +/** + * ip27_alloc_irq_num - finds a free irq in the irq_map. + * + * Returns the first free IRQ number in irq_map. This IRQ will later be + * linked to a specific HUB interrupt bit. + */ +int +ip27_alloc_irq_num(void) { int irq; again: irq = find_first_zero_bit(irq_map, NR_IRQS); - if (irq >= NR_IRQS) + if (unlikely(irq >= NR_IRQS)) return -ENOSPC; if (test_and_set_bit(irq, irq_map)) @@ -27,22 +37,28 @@ again: return irq; } -/* - * Allocate the 16 legacy interrupts for i8259 devices. This happens early - * in the kernel initialization so treating allocation failure as BUG() is - * ok. +/** + * ip27_force_irq_num - manually assign an irq in the irq_map. + * @irq: unsigned int of irq to free. */ -void __init alloc_legacy_irqno(void) +void +ip27_force_irq_num(int irq) { - int i; - - for (i = 0; i <= 16; i++) - BUG_ON(test_and_set_bit(i, irq_map)); + smp_mb__before_atomic(); + set_bit(irq, irq_map); + smp_mb__after_atomic(); } -void free_irqno(unsigned int irq) +/** + * ip27_free_irq_num - free an irq in the irq_map and make it available again. + * @irq: unsigned int of irq to free. + */ +void +ip27_free_irq_num(int irq) { smp_mb__before_atomic(); clear_bit(irq, irq_map); smp_mb__after_atomic(); } + +/* ----------------------------------------------------------------------- */ diff --git a/arch/mips/sgi-ip27/ip27-klconfig.c b/arch/mips/sgi-ip27/ip27-klconfig.c index c873d62..23f4a32 100644 --- a/arch/mips/sgi-ip27/ip27-klconfig.c +++ b/arch/mips/sgi-ip27/ip27-klconfig.c @@ -14,11 +14,20 @@ #include #include -klinfo_t *find_component(lboard_t *brd, klinfo_t *kli, unsigned char struct_type) +/** + * kl_find_component - navigate the available components on an lboard/rboard. + * @brd: + * @kli: + * @struct_type: + * + * Returns the next component from the KLCONFIG structure on SGI SN systems. + */ +struct klc_info * +kl_find_component(struct klc_lboard *brd, struct klc_info *kli, u8 struct_type) { int index, j; - if (kli == (klinfo_t *)NULL) { + if (kli == KLCF_CAST_INFO(NULL)) { index = 0; } else { for (j = 0; j < KLCF_NUM_COMPS(brd); j++) @@ -26,8 +35,8 @@ klinfo_t *find_component(lboard_t *brd, klinfo_t *kli, unsigned char struct_type break; index = j; if (index == KLCF_NUM_COMPS(brd)) { - printk("find_component: Bad pointer: 0x%p\n", kli); - return (klinfo_t *)NULL; + pr_err("%s: Bad pointer: 0x%p\n", __func__, kli); + return KLCF_CAST_INFO(NULL); } index++; /* next component */ } @@ -39,73 +48,80 @@ klinfo_t *find_component(lboard_t *brd, klinfo_t *kli, unsigned char struct_type } /* Didn't find it. */ - return (klinfo_t *)NULL; + return KLCF_CAST_INFO(NULL); } -klinfo_t *find_first_component(lboard_t *brd, unsigned char struct_type) +struct klc_info * +kl_find_first_component(struct klc_lboard *brd, u8 struct_type) { - return find_component(brd, (klinfo_t *)NULL, struct_type); + return kl_find_component(brd, KLCF_CAST_INFO(NULL), struct_type); } -lboard_t *find_lboard(lboard_t *start, unsigned char brd_type) +struct klc_lboard * +kl_find_lboard(struct klc_lboard *start, u8 brd_type) { /* Search all boards stored on this node. */ while (start) { - if (start->brd_type == brd_type) + if (start->type == brd_type) return start; start = KLCF_NEXT(start); } /* Didn't find it. */ - return (lboard_t *)NULL; + return KLCF_CAST_LBOARD(NULL); } -lboard_t *find_lboard_class(lboard_t *start, unsigned char brd_type) +struct klc_lboard * +kl_find_lboard_class(struct klc_lboard *start, u8 brd_type) { /* Search all boards stored on this node. */ while (start) { - if (KLCLASS(start->brd_type) == KLCLASS(brd_type)) + if (KLCLASS(start->type) == KLCLASS(brd_type)) return start; start = KLCF_NEXT(start); } /* Didn't find it. */ - return (lboard_t *)NULL; + return KLCF_CAST_LBOARD(NULL); } -cnodeid_t get_cpu_cnode(cpuid_t cpu) +cnodeid_t +get_cpu_cnode(cpuid_t cpu) { - return CPUID_TO_COMPACT_NODEID(cpu); + return sn_cpuid_to_cnodeid[cpu]; } -klcpu_t *nasid_slice_to_cpuinfo(nasid_t nasid, int slice) +struct klc_cpu * +nasid_slice_to_cpuinfo(nasid_t nasid, int slice) { - lboard_t *brd; - klcpu_t *acpu; + struct klc_lboard *brd; + struct klc_cpu *acpu; - if (!(brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27))) - return (klcpu_t *)NULL; + if (!(brd = kl_find_lboard(KLCF_LBOARD_INFO(nasid), KLTYPE_IP27))) + return KLCF_CAST_CPU(NULL); - if (!(acpu = (klcpu_t *)find_first_component(brd, KLSTRUCT_CPU))) - return (klcpu_t *)NULL; + if (!(acpu = KLCF_CAST_CPU(kl_find_first_component(brd, KLSTRUCT_CPU)))) + return KLCF_CAST_CPU(NULL); do { - if ((acpu->cpu_info.physid) == slice) + if ((acpu->kl_info.physid) == slice) return acpu; - } while ((acpu = (klcpu_t *)find_component(brd, (klinfo_t *)acpu, - KLSTRUCT_CPU))); - return (klcpu_t *)NULL; + } while ((acpu = KLCF_CAST_CPU(kl_find_component(brd, + KLCF_CAST_INFO(acpu), + KLSTRUCT_CPU)))); + return KLCF_CAST_CPU(NULL); } -klcpu_t *sn_get_cpuinfo(cpuid_t cpu) +static struct klc_cpu * +sn_get_cpuinfo(cpuid_t cpu) { nasid_t nasid; int slice; - klcpu_t *acpu; + struct klc_cpu *acpu; gda_t *gdap = GDA; cnodeid_t cnode; - if (!(cpu < MAXCPUS)) { - printk("sn_get_cpuinfo: illegal cpuid 0x%lx\n", cpu); + if (cpu > MAXCPUS) { + pr_err("%s: illegal cpuid 0x%lx\n", __func__, cpu); return NULL; } @@ -118,17 +134,20 @@ klcpu_t *sn_get_cpuinfo(cpuid_t cpu) for (slice = 0; slice < CPUS_PER_NODE; slice++) { acpu = nasid_slice_to_cpuinfo(nasid, slice); - if (acpu && acpu->cpu_info.virtid == cpu) + if (acpu && acpu->kl_info.virtid == cpu) return acpu; } - return NULL; + + return KLCF_CAST_CPU(NULL); } -int get_cpu_slice(cpuid_t cpu) +int +get_cpu_slice(cpuid_t cpu) { - klcpu_t *acpu; + struct klc_cpu *acpu; if ((acpu = sn_get_cpuinfo(cpu)) == NULL) return -1; - return acpu->cpu_info.physid; + + return acpu->kl_info.physid; } diff --git a/arch/mips/sgi-ip27/ip27-klnuma.c b/arch/mips/sgi-ip27/ip27-klnuma.c index bda90cf..3702c74 100644 --- a/arch/mips/sgi-ip27/ip27-klnuma.c +++ b/arch/mips/sgi-ip27/ip27-klnuma.c @@ -26,7 +26,8 @@ static cpumask_t ktext_repmask; * kernel. For example, we should never put a copy on a headless node, * and we should respect the topology of the machine. */ -void __init setup_replication_mask(void) +void __init +setup_replication_mask(void) { /* Set only the master cnode's bit. The master cnode is always 0. */ cpumask_clear(&ktext_repmask); @@ -52,7 +53,8 @@ void __init setup_replication_mask(void) } -static __init void set_ktext_source(nasid_t client_nasid, nasid_t server_nasid) +static __init void +set_ktext_source(nasid_t client_nasid, nasid_t server_nasid) { kern_vars_t *kvp; @@ -69,7 +71,8 @@ static __init void set_ktext_source(nasid_t client_nasid, nasid_t server_nasid) } /* XXX - When the BTE works, we should use it instead of this. */ -static __init void copy_kernel(nasid_t dest_nasid) +static __init void +copy_kernel(nasid_t dest_nasid) { unsigned long dest_kern_start, source_start, source_end, kern_size; @@ -82,7 +85,8 @@ static __init void copy_kernel(nasid_t dest_nasid) memcpy((void *)dest_kern_start, (void *)source_start, kern_size); } -void __init replicate_kernel_text() +void __init +replicate_kernel_text() { cnodeid_t cnode; nasid_t client_nasid; @@ -96,7 +100,7 @@ void __init replicate_kernel_text() for_each_online_node(cnode) { if (cnode == 0) continue; - client_nasid = COMPACT_TO_NASID_NODEID(cnode); + client_nasid = sn_cnodeid_to_nasid[cnode]; /* Check if this node should get a copy of the kernel */ if (cpumask_test_cpu(cnode, &ktext_repmask)) { @@ -114,10 +118,11 @@ void __init replicate_kernel_text() * data structures on the first couple of pages of the first slot of each * node. If this is the case, getfirstfree(node) > getslotstart(node, 0). */ -unsigned long node_getfirstfree(cnodeid_t cnode) +unsigned long +node_getfirstfree(cnodeid_t cnode) { unsigned long loadbase = REP_BASE; - nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode); + nasid_t nasid = sn_cnodeid_to_nasid[cnode]; unsigned long offset; #ifdef CONFIG_MAPPED_KERNEL diff --git a/arch/mips/sgi-ip27/ip27-memory.c b/arch/mips/sgi-ip27/ip27-memory.c index 8d0eb26..0d33a96 100644 --- a/arch/mips/sgi-ip27/ip27-memory.c +++ b/arch/mips/sgi-ip27/ip27-memory.c @@ -31,8 +31,8 @@ #include -#define SLOT_PFNSHIFT (SLOT_SHIFT - PAGE_SHIFT) -#define PFN_NASIDSHFT (NASID_SHFT - PAGE_SHIFT) +#define SLOT_PFNSHIFT (SLOT_SHIFT - PAGE_SHIFT) +#define PFN_NASIDSHFT (NASID_SHFT - PAGE_SHIFT) struct node_data *__node_data[MAX_COMPACT_NODES]; @@ -40,22 +40,29 @@ EXPORT_SYMBOL(__node_data); static int fine_mode; -static int is_fine_dirmode(void) + +static int +is_fine_dirmode(void) { - return ((LOCAL_HUB_L(NI_STATUS_REV_ID) & NSRI_REGIONSIZE_MASK) >> NSRI_REGIONSIZE_SHFT) & REGIONSIZE_FINE; + return ((LOCAL_HUB_L(NI_STATUS_REV_ID) & NSRI_REGIONSIZE_MASK) + >> NSRI_REGIONSIZE_SHFT) & REGIONSIZE_FINE; } -static hubreg_t get_region(cnodeid_t cnode) +static hubreg_t +get_region(cnodeid_t cnode) { if (fine_mode) - return COMPACT_TO_NASID_NODEID(cnode) >> NASID_TO_FINEREG_SHFT; + return (sn_cnodeid_to_nasid[cnode] + >> NASID_TO_FINEREG_SHFT); else - return COMPACT_TO_NASID_NODEID(cnode) >> NASID_TO_COARSEREG_SHFT; + return (sn_cnodeid_to_nasid[cnode] + >> NASID_TO_COARSEREG_SHFT); } static hubreg_t region_mask; -static void gen_region_mask(hubreg_t *region_mask) +static void +gen_region_mask(hubreg_t *region_mask) { cnodeid_t cnode; @@ -65,101 +72,109 @@ static void gen_region_mask(hubreg_t *region_mask) } } -#define rou_rflag rou_flags static int router_distance; -static void router_recurse(klrou_t *router_a, klrou_t *router_b, int depth) +static void +router_recurse(struct klc_router *router_a, struct klc_router *router_b, + int depth) { - klrou_t *router; - lboard_t *brd; - int port; + int port; + struct klc_router *router; + struct klc_lboard *brd; + struct klc_port *rport; - if (router_a->rou_rflag == 1) + if (router_a->flags == 1) return; if (depth >= router_distance) return; - router_a->rou_rflag = 1; + router_a->flags = 1; for (port = 1; port <= MAX_ROUTER_PORTS; port++) { - if (router_a->rou_port[port].port_nasid == INVALID_NASID) + rport = &router_a->port[port]; + if (rport->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); + brd = KLCF_LBOARD_K0(rport->nasid, rport->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); + if (KLCF_TYPE(brd) != KLTYPE_ROUTER) + continue; + + router = KLCF_ROUTER_K0(brd, brd->components[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; + router_a->flags = 0; } unsigned char __node_distances[MAX_COMPACT_NODES][MAX_COMPACT_NODES]; EXPORT_SYMBOL(__node_distances); -static int __init compute_node_distance(nasid_t nasid_a, nasid_t nasid_b) +static int __init +compute_node_distance(nasid_t nasid_a, nasid_t nasid_b) { - klrou_t *router, *router_a = NULL, *router_b = NULL; - lboard_t *brd, *dest_brd; + int port; cnodeid_t cnode; nasid_t nasid; - int port; + struct klc_port *rport; + struct klc_lboard *brd, *dest_brd; + struct klc_router *router, *router_a = NULL, *router_b = NULL; /* Figure out which routers nodes in question are connected to */ for_each_online_node(cnode) { - nasid = COMPACT_TO_NASID_NODEID(cnode); + nasid = sn_cnodeid_to_nasid[cnode]; if (nasid == -1) continue; - brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid), - KLTYPE_ROUTER); + brd = kl_find_lboard_class(KLCF_LBOARD_INFO(nasid), + KLTYPE_ROUTER); if (!brd) continue; do { - if (brd->brd_flags & DUPLICATE_BOARD) + if (KL_CONFIG_DUPLICATE_BOARD(brd)) continue; - router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd), brd->brd_compts[0]); - router->rou_rflag = 0; + router = KLCF_ROUTER_K0(brd, brd->components[0]); + router->flags = 0; for (port = 1; port <= MAX_ROUTER_PORTS; port++) { - if (router->rou_port[port].port_nasid == INVALID_NASID) + rport = &router->port[port]; + if (rport->nasid == INVALID_NASID) + continue; + + dest_brd = KLCF_LBOARD_K0(rport->nasid, + rport->offset); + + if (KLCF_TYPE(dest_brd) != KLTYPE_IP27) continue; - dest_brd = (lboard_t *)NODE_OFFSET_TO_K0( - router->rou_port[port].port_nasid, - router->rou_port[port].port_offset); + if (KLCF_BOARD_NASID(dest_brd) == nasid_a) + router_a = router; - 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; - } + if (KLCF_BOARD_NASID(dest_brd) == nasid_b) + router_b = router; } - } while ((brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER))); + } while ((brd = kl_find_lboard_class(KLCF_NEXT(brd), + KLTYPE_ROUTER))); } if (router_a == NULL) { - printk("node_distance: router_a NULL\n"); + pr_info("%s: router_a NULL\n", __func__); return -1; } + if (router_b == NULL) { - printk("node_distance: router_b NULL\n"); + pr_info("%s: router_b NULL\n", __func__); return -1; } @@ -175,7 +190,8 @@ static int __init compute_node_distance(nasid_t nasid_a, nasid_t nasid_b) return router_distance; } -static void __init init_topology_matrix(void) +static void __init +init_topology_matrix(void) { nasid_t nasid, nasid2; cnodeid_t row, col; @@ -185,123 +201,132 @@ static void __init init_topology_matrix(void) __node_distances[row][col] = -1; for_each_online_node(row) { - nasid = COMPACT_TO_NASID_NODEID(row); + nasid = sn_cnodeid_to_nasid[row]; for_each_online_node(col) { - nasid2 = COMPACT_TO_NASID_NODEID(col); + nasid2 = sn_cnodeid_to_nasid[col]; __node_distances[row][col] = compute_node_distance(nasid, nasid2); } } } -static void __init dump_topology(void) +static void __init +dump_topology(void) { + int port, router_num = 0; nasid_t nasid; - cnodeid_t cnode; - lboard_t *brd, *dest_brd; - int port; - int router_num = 0; - klrou_t *router; - cnodeid_t row, col; + cnodeid_t cnode, row, col; + struct klc_router *router; + struct klc_port *rport; + struct klc_lboard *brd, *dest_brd; - printk("************** Topology ********************\n"); + pr_info("************** Topology ********************\n"); - printk(" "); + pr_cont(" "); for_each_online_node(col) - printk("%02d ", col); - printk("\n"); + pr_cont("%02d ", col); + pr_cont("\n"); for_each_online_node(row) { - printk("%02d ", row); + pr_cont("%02d ", row); for_each_online_node(col) - printk("%2d ", node_distance(row, col)); - printk("\n"); + pr_cont("%2d ", node_distance(row, col)); + pr_cont("\n"); } for_each_online_node(cnode) { - nasid = COMPACT_TO_NASID_NODEID(cnode); + nasid = sn_cnodeid_to_nasid[cnode]; if (nasid == -1) continue; - brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid), - KLTYPE_ROUTER); + brd = kl_find_lboard_class(KLCF_LBOARD_INFO(nasid), + KLTYPE_ROUTER); if (!brd) continue; do { - if (brd->brd_flags & DUPLICATE_BOARD) + if (KL_CONFIG_DUPLICATE_BOARD(brd)) continue; - printk("Router %d:", router_num); + pr_cont("Router %d:", router_num); router_num++; - router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd), brd->brd_compts[0]); + router = KLCF_ROUTER_K0(brd, brd->components[0]); for (port = 1; port <= MAX_ROUTER_PORTS; port++) { - if (router->rou_port[port].port_nasid == INVALID_NASID) + rport = &router->port[port]; + if (rport->nasid == INVALID_NASID) continue; - dest_brd = (lboard_t *)NODE_OFFSET_TO_K0( - router->rou_port[port].port_nasid, - router->rou_port[port].port_offset); + dest_brd = KLCF_LBOARD_K0(rport->nasid, + rport->offset); - if (dest_brd->brd_type == KLTYPE_IP27) - printk(" %d", dest_brd->brd_nasid); - if (dest_brd->brd_type == KLTYPE_ROUTER) - printk(" r"); + if (KLCF_TYPE(dest_brd) == KLTYPE_IP27) + pr_cont(" %d", KLCF_BOARD_NASID(dest_brd)); + + if (KLCF_TYPE(dest_brd) == KLTYPE_ROUTER) + pr_cont(" r"); } - printk("\n"); + pr_cont("\n"); - } while ( (brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER)) ); + } while ((brd = kl_find_lboard_class(KLCF_NEXT(brd), + KLTYPE_ROUTER))); } } -static unsigned long __init slot_getbasepfn(cnodeid_t cnode, int slot) +static unsigned long __init +slot_getbasepfn(cnodeid_t cnode, int slot) { - nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode); + nasid_t nasid = sn_cnodeid_to_nasid[cnode]; - return ((unsigned long)nasid << PFN_NASIDSHFT) | (slot << SLOT_PFNSHIFT); + return (((unsigned long)nasid << PFN_NASIDSHFT) | + (slot << SLOT_PFNSHIFT)); } -static unsigned long __init slot_psize_compute(cnodeid_t node, int slot) +static unsigned long +__init slot_psize_compute(cnodeid_t node, int slot) { nasid_t nasid; - lboard_t *brd; - klmembnk_t *banks; + struct klc_lboard *brd; + struct klc_membank *banks; unsigned long size; - nasid = COMPACT_TO_NASID_NODEID(node); + nasid = sn_cnodeid_to_nasid[node]; /* Find the node board */ - brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27); + brd = kl_find_lboard(KLCF_LBOARD_INFO(nasid), KLTYPE_IP27); if (!brd) return 0; /* Get the memory bank structure */ - banks = (klmembnk_t *) find_first_component(brd, KLSTRUCT_MEMBNK); + banks = KLCF_CAST_MEMBANK(kl_find_first_component(brd, + KLSTRUCT_MEMBNK)); if (!banks) return 0; /* Size in _Megabytes_ */ - size = (unsigned long)banks->membnk_bnksz[slot/4]; + size = (unsigned long)banks->bank_sz[slot / 4]; /* hack for 128 dimm banks */ if (size <= 128) { if (slot % 4 == 0) { - size <<= 20; /* size in bytes */ - return size >> PAGE_SHIFT; - } else + /* Size in bytes */ + size <<= 20; + return (size >> PAGE_SHIFT); + } else { return 0; + } } else { size /= 4; size <<= 20; - return size >> PAGE_SHIFT; + return (size >> PAGE_SHIFT); } } -static void __init mlreset(void) +static void __init +mlreset(void) { int i; - master_nasid = get_nasid(); + master_nasid = ip27_get_nasid(); fine_mode = is_fine_dirmode(); /* @@ -309,7 +334,7 @@ static void __init mlreset(void) * mapping tables. We need to do this as early as possible. */ #ifdef CONFIG_SMP - cpu_node_probe(); + ip27_smp_cpu_node_probe(); #endif init_topology_matrix(); @@ -325,7 +350,7 @@ static void __init mlreset(void) for_each_online_node(i) { nasid_t nasid; - nasid = COMPACT_TO_NASID_NODEID(i); + nasid = sn_cnodeid_to_nasid[i]; /* * Always have node 0 in the region mask, otherwise @@ -351,9 +376,11 @@ static void __init mlreset(void) } } -static void __init szmem(void) +static void __init +szmem(void) { - unsigned long slot_psize, slot0sz = 0, nodebytes; /* Hack to detect problem configs */ + /* Hack to detect problem configs */ + unsigned long slot_psize, slot0sz = 0, nodebytes; int slot; cnodeid_t node; @@ -374,8 +401,8 @@ static void __init szmem(void) if ((nodebytes >> PAGE_SHIFT) * (sizeof(struct page)) > (slot0sz << PAGE_SHIFT)) { - printk("Ignoring slot %d onwards on node %d\n", - slot, node); + pr_notice("Ignoring slot %d onwards on node " + "%d\n", slot, node); slot = MAX_MEM_SLOTS; continue; } @@ -385,7 +412,8 @@ static void __init szmem(void) } } -static void __init node_mem_init(cnodeid_t node) +static void __init +node_mem_init(cnodeid_t node) { unsigned long slot_firstpfn = slot_getbasepfn(node, 0); unsigned long slot_freepfn = node_getfirstfree(node); @@ -422,7 +450,8 @@ static void __init node_mem_init(cnodeid_t node) * A node with nothing. We use it to avoid any special casing in * cpumask_of_node */ -static struct node_data null_node = { +static struct node_data +null_node = { .hub = { .h_cpus = CPU_MASK_NONE } @@ -433,7 +462,8 @@ static struct node_data null_node = { * contains at least 32 MBytes of memory. We assume all bootmem data * fits on the first slot. */ -void __init prom_meminit(void) +void __init +prom_meminit(void) { cnodeid_t node; @@ -449,14 +479,16 @@ void __init prom_meminit(void) } } -void __init prom_free_prom_memory(void) +void __init +prom_free_prom_memory(void) { /* We got nothing to free here ... */ } extern void setup_zero_pages(void); -void __init paging_init(void) +void __init +paging_init(void) { unsigned long zones_size[MAX_NR_ZONES] = {0, }; unsigned node; @@ -475,7 +507,8 @@ void __init paging_init(void) free_area_init_nodes(zones_size); } -void __init mem_init(void) +void __init +mem_init(void) { high_memory = (void *) __va(get_num_physpages() << PAGE_SHIFT); free_all_bootmem(); diff --git a/arch/mips/sgi-ip27/ip27-nmi.c b/arch/mips/sgi-ip27/ip27-nmi.c index a2358b4..dcc523d 100644 --- a/arch/mips/sgi-ip27/ip27-nmi.c +++ b/arch/mips/sgi-ip27/ip27-nmi.c @@ -25,18 +25,20 @@ static arch_spinlock_t nmi_lock = __ARCH_SPIN_LOCK_UNLOCKED; /* * Lets see what else we need to do here. Set up sp, gp? */ -void nmi_dump(void) +void +nmi_dump(void) { void cont_nmi_dump(void); cont_nmi_dump(); } -void install_cpu_nmi_handler(int slice) +void __init +ip27_install_cpu_nmi_handler(int slice) { nmi_t *nmi_addr; - nmi_addr = (nmi_t *)NMI_ADDR(get_nasid(), slice); + nmi_addr = (nmi_t *)NMI_ADDR(ip27_get_nasid(), slice); if (nmi_addr->call_addr) return; nmi_addr->magic = NMI_MAGIC; @@ -51,7 +53,8 @@ void install_cpu_nmi_handler(int slice) * into the eframe format for the node under consideration. */ -void nmi_cpu_eframe_save(nasid_t nasid, int slice) +void +nmi_cpu_eframe_save(nasid_t nasid, int slice) { struct reg_struct *nr; int i; @@ -127,7 +130,8 @@ void nmi_cpu_eframe_save(nasid_t nasid, int slice) printk("\n"); } -void nmi_dump_hub_irq(nasid_t nasid, int slice) +void +nmi_dump_hub_irq(nasid_t nasid, int slice) { hubreg_t mask0, mask1, pend0, pend1; @@ -151,7 +155,8 @@ void nmi_dump_hub_irq(nasid_t nasid, int slice) * Copy the cpu registers which have been saved in the IP27prom format * into the eframe format for the node under consideration. */ -void nmi_node_eframe_save(cnodeid_t cnode) +void +nmi_node_eframe_save(cnodeid_t cnode) { nasid_t nasid; int slice; @@ -160,7 +165,7 @@ void nmi_node_eframe_save(cnodeid_t cnode) if (cnode == CNODEID_NONE) return; - nasid = COMPACT_TO_NASID_NODEID(cnode); + nasid = sn_cnodeid_to_nasid[cnode]; if (nasid == INVALID_NASID) return; @@ -206,29 +211,30 @@ cont_nmi_dump(void) * half the cpus. Unfortunately, we don't know which cpus may be * NMIed - it depends on how the site chooses to configure. * - * Note: it has been measure that it takes the MMSC up to 2.3 secs to + * Note: it has been measured that it takes the MMSC up to 2.3 secs to * send NMIs to all cpus on a 256p system. */ - for (i=0; i < 1500; i++) { + for (i = 0; i < 1500; i++) { for_each_online_node(node) if (NODEPDA(node)->dump_count == 0) break; if (node == MAX_NUMNODES) break; if (i == 1000) { - for_each_online_node(node) - if (NODEPDA(node)->dump_count == 0) { - cpu = cpumask_first(cpumask_of_node(node)); - for (n=0; n < CNODE_NUM_CPUS(node); cpu++, n++) { - CPUMASK_SETB(nmied_cpus, cpu); - /* - * cputonasid, cputoslice - * needs kernel cpuid - */ - SEND_NMI((cputonasid(cpu)), (cputoslice(cpu))); - } + for_each_online_node(node) { + if (NODEPDA(node)->dump_count != 0) + continue; + + cpu = cpumask_first(cpumask_of_node(node)); + for (n = 0; n < CNODE_NUM_CPUS(node); cpu++, n++) { + CPUMASK_SETB(nmied_cpus, cpu); + /* + * cpu_to_nasid, cpu_to_slice + * needs kernel cpuid + */ + SEND_NMI((cpu_to_nasid(cpu)), (cpu_to_slice(cpu))); } - + } } udelay(10000); } diff --git a/arch/mips/sgi-ip27/ip27-reset.c b/arch/mips/sgi-ip27/ip27-reset.c index e44a15d..578363a 100644 --- a/arch/mips/sgi-ip27/ip27-reset.c +++ b/arch/mips/sgi-ip27/ip27-reset.c @@ -33,7 +33,8 @@ void machine_power_off(void) __noreturn; #define noreturn while(1); /* Silence gcc. */ /* XXX How to pass the reboot command to the firmware??? */ -static void ip27_machine_restart(char *command) +static void +ip27_machine_restart(char *command) { #if 0 int i; @@ -45,15 +46,16 @@ static void ip27_machine_restart(char *command) #endif #if 0 for_each_online_node(i) - REMOTE_HUB_S(COMPACT_TO_NASID_NODEID(i), PROMOP_REG, - PROMOP_REBOOT); + REMOTE_HUB_S(sn_cnodeid_to_nasid[i], PROMOP_REG, + PROMOP_REBOOT); #else LOCAL_HUB_S(NI_PORT_RESET, NPR_PORTRESET | NPR_LOCALRESET); #endif noreturn; } -static void ip27_machine_halt(void) +static void +ip27_machine_halt(void) { int i; @@ -61,19 +63,21 @@ static void ip27_machine_halt(void) smp_send_stop(); #endif for_each_online_node(i) - REMOTE_HUB_S(COMPACT_TO_NASID_NODEID(i), PROMOP_REG, - PROMOP_RESTART); + REMOTE_HUB_S(sn_cnodeid_to_nasid[i], PROMOP_REG, + PROMOP_RESTART); LOCAL_HUB_S(NI_PORT_RESET, NPR_PORTRESET | NPR_LOCALRESET); noreturn; } -static void ip27_machine_power_off(void) +static void +ip27_machine_power_off(void) { /* To do ... */ noreturn; } -void ip27_reboot_setup(void) +void +ip27_reboot_setup(void) { _machine_restart = ip27_machine_restart; _machine_halt = ip27_machine_halt; diff --git a/arch/mips/sgi-ip27/ip27-rtc.c b/arch/mips/sgi-ip27/ip27-rtc.c new file mode 100644 index 0000000..e9b9af4 --- /dev/null +++ b/arch/mips/sgi-ip27/ip27-rtc.c @@ -0,0 +1,140 @@ +/* + * 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. + * + * ip27-rtc.c: RTC submodule for the IOC3 metadriver for IP27. + * + * Copyright (C) 2014, 2016 Joshua Kinard + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * On IP27, the RTC is hidden behind the IOC3 device, attached to a generic + * ByteBus. Use klconfig routines to safely map to the start address of the + * RTC area in ByteBus DEV0. + */ +#define IP27_RTC_RES_START \ + (XPHYSADDR(KL_CONFIG_CONS_INFO(master_nasid)->memory_base + \ + IOC3_BYTEBUS_DEV0)) +#define IP27_RTC_RES_END (IP27_RTC_RES_START + 32767) + +static struct ioc3_driver_data *ioc3; +static struct resource ip27_rtc_resources[1]; +static int ip27_rtc_probed = 0; + +/** + * ip27_rtc_read - read a value from an rtc register. + * @rtc: pointer to the m48t35 rtc structure. + * @reg: the register address to read. + */ +u8 +ip27_rtc_read(struct m48t35_priv *rtc, int reg) +{ + return readb(((u8 __iomem *)(((u64)(rtc->regs + reg)) ^ 3))); +} + +/** + * ip27_rtc_write - write a value to an rtc register. + * @rtc: pointer to the m48t35 rtc structure. + * @reg: the register address to write. + * @value: value to write to the register. + */ +void +ip27_rtc_write(struct m48t35_priv *rtc, int reg, u8 value) +{ + writeb(value, ((u8 __iomem *)(((u64)(rtc->regs + reg)) ^ 3))); +} + +static struct m48t35_rtc_platform_data +ip27_rtc_platform_data[] = { + { + /* + * XXX: set req_mem_region to true after ioc3 resource + * conflicts are resolved. + */ + .req_mem_region = false, + .plat_read = ip27_rtc_read, + .plat_write = ip27_rtc_write, + }, +}; + +static struct platform_device +ip27_rtc_device = { + .name = "rtc-m48t35", + .id = -1, + .dev = { + .platform_data = ip27_rtc_platform_data, + }, + .num_resources = ARRAY_SIZE(ip27_rtc_resources), + .resource = ip27_rtc_resources, +}; + + +/* IOC3 Metadriver probe/remove */ +static int +ip27_ioc3_rtc_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd) +{ + int ret; + + /* This code only applies to an Origin/Onyx2 */ + if (ioc3 || (idd->class != IOC3_CLASS_BASE_IP27)) + return 1; + + ioc3 = idd; + + if (ip27_rtc_probed) + return 0; + + ip27_rtc_resources[0].start = IP27_RTC_RES_START, + ip27_rtc_resources[0].end = IP27_RTC_RES_END, + ip27_rtc_resources[0].flags = IORESOURCE_MEM, + + ret = platform_device_register(&ip27_rtc_device); + ip27_rtc_probed = 1; + + return ret; +} + + +static int +ip27_ioc3_rtc_remove(struct ioc3_submodule *is, struct ioc3_driver_data *idd) +{ + if (ioc3 != idd) + return 1; + + platform_device_unregister(&ip27_rtc_device); + ioc3 = NULL; + + return 0; +} + + +/* entry/exit functions */ +static struct ioc3_submodule +ip27_ioc3_rtc_submodule = { + .name = "rtc", + .probe = ip27_ioc3_rtc_probe, + .remove = ip27_ioc3_rtc_remove, + .owner = THIS_MODULE, +}; + +ioc3_submodule_driver(ip27_ioc3_rtc_submodule); + +MODULE_AUTHOR("Joshua Kinard "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("IP27 RTC Submodule for IOC3"); diff --git a/arch/mips/sgi-ip27/ip27-smp.c b/arch/mips/sgi-ip27/ip27-smp.c index f9ae6a8..6b1fce1 100644 --- a/arch/mips/sgi-ip27/ip27-smp.c +++ b/arch/mips/sgi-ip27/ip27-smp.c @@ -7,10 +7,18 @@ * Copyright (C) 2000 - 2001 by Silicon Graphics, Inc. */ #include -#include +#include +#include #include +#include +#include + +#include +#include #include #include +#include + #include #include #include @@ -19,128 +27,30 @@ #include #include #include + #include #include #include -/* - * Takes as first input the PROM assigned cpu id, and the kernel - * assigned cpu id as the second. - */ -static void alloc_cpupda(cpuid_t cpu, int cpunum) -{ - cnodeid_t node = get_cpu_cnode(cpu); - nasid_t nasid = COMPACT_TO_NASID_NODEID(node); - - cputonasid(cpunum) = nasid; - sn_cpu_info[cpunum].p_nodeid = node; - cputoslice(cpunum) = get_cpu_slice(cpu); -} - -static nasid_t get_actual_nasid(lboard_t *brd) -{ - klhub_t *hub; - - if (!brd) - return INVALID_NASID; +extern void generic_smp_call_function_interrupt(void); +extern void scheduler_ipi(void); - /* find out if we are a completely disabled brd. */ - hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB); - if (!hub) - return INVALID_NASID; - if (!(hub->hub_info.flags & KLINFO_ENABLE)) /* disabled node brd */ - return hub->hub_info.physid; - else - return brd->brd_nasid; -} +/* Defined in ip27-init.c */ +DECLARE_PER_CPU(struct ip27_percpu_data, ip27_cpu); -static int do_cpumask(cnodeid_t cnode, nasid_t nasid, int highest) -{ - static int tot_cpus_found = 0; - lboard_t *brd; - klcpu_t *acpu; - int cpus_found = 0; - cpuid_t cpuid; - brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27); +/* ----------------------------------------------------------------------- */ +/* SMP IPI Ops */ - do { - acpu = (klcpu_t *)find_first_component(brd, KLSTRUCT_CPU); - while (acpu) { - cpuid = acpu->cpu_info.virtid; - /* cnode is not valid for completely disabled brds */ - if (get_actual_nasid(brd) == brd->brd_nasid) - cpuid_to_compact_node[cpuid] = cnode; - if (cpuid > highest) - highest = cpuid; - /* Only let it join in if it's marked enabled */ - if ((acpu->cpu_info.flags & KLINFO_ENABLE) && - (tot_cpus_found != NR_CPUS)) { - set_cpu_possible(cpuid, true); - alloc_cpupda(cpuid, tot_cpus_found); - cpus_found++; - tot_cpus_found++; - } - acpu = (klcpu_t *)find_component(brd, (klinfo_t *)acpu, - KLSTRUCT_CPU); - } - brd = KLCF_NEXT(brd); - if (!brd) - break; - - brd = find_lboard(brd, KLTYPE_IP27); - } while (brd); - - return highest; -} - -void cpu_node_probe(void) -{ - int i, highest = 0; - gda_t *gdap = GDA; - - /* - * Initialize the arrays to invalid nodeid (-1) - */ - for (i = 0; i < MAX_COMPACT_NODES; i++) - compact_to_nasid_node[i] = INVALID_NASID; - for (i = 0; i < MAX_NASIDS; i++) - nasid_to_compact_node[i] = INVALID_CNODEID; - for (i = 0; i < MAXCPUS; i++) - cpuid_to_compact_node[i] = INVALID_CNODEID; - - /* - * MCD - this whole "compact node" stuff can probably be dropped, - * as we can handle sparse numbering now - */ - nodes_clear(node_online_map); - for (i = 0; i < MAX_COMPACT_NODES; i++) { - nasid_t nasid = gdap->g_nasidtable[i]; - if (nasid == INVALID_NASID) - break; - compact_to_nasid_node[i] = nasid; - nasid_to_compact_node[nasid] = i; - node_set_online(num_online_nodes()); - highest = do_cpumask(i, nasid, highest); - } - - printk("Discovered %d cpus on %d nodes\n", highest + 1, num_online_nodes()); -} - -static __init void intr_clear_all(nasid_t nasid) -{ - int i; - - REMOTE_HUB_S(nasid, PI_INT_MASK0_A, 0); - REMOTE_HUB_S(nasid, PI_INT_MASK0_B, 0); - REMOTE_HUB_S(nasid, PI_INT_MASK1_A, 0); - REMOTE_HUB_S(nasid, PI_INT_MASK1_B, 0); - - for (i = 0; i < 128; i++) - REMOTE_HUB_CLR_INTR(nasid, i); -} - -static void ip27_send_ipi_single(int destid, unsigned int action) +/** + * ip27_smp_send_ipi_single - Send an action to another CPU via IPI. + * @cpu: integer CPU to send IPI to with action. + * @action: u32 integer containing list of actions to take OR'ed together. + * + * Runs on CPUx and sends an IPI to CPUy. + */ +static void +ip27_smp_send_ipi_single(int cpu, u32 action) { int irq; @@ -152,87 +62,392 @@ static void ip27_send_ipi_single(int destid, unsigned int action) irq = CPU_CALL_A_IRQ; break; default: - panic("sendintr"); + panic("IP27: Unknown action value in ip27_send_ipi_single!\n"); } - irq += cputoslice(destid); + irq += per_cpu(ip27_cpu, cpu).slice; /* * Convert the compact hub number to the NASID to get the correct * part of the address space. Then set the interrupt bit associated * with the CPU we want to send the interrupt to. */ - REMOTE_HUB_SEND_INTR(COMPACT_TO_NASID_NODEID(cpu_to_node(destid)), irq); + REMOTE_HUB_SEND_INTR(per_cpu(ip27_cpu, cpu).cnodeid, irq); } -static void ip27_send_ipi_mask(const struct cpumask *mask, unsigned int action) +/** + * ip27_smp_send_ipi_mask - Send an action to many CPUs via IPI. + * @mask: cpumask of CPUs to send IPI to with action. + * @action: u32 integer containing list of actions to take OR'ed together. + */ +static void +ip27_smp_send_ipi_mask(const struct cpumask *mask, u32 action) { unsigned int i; for_each_cpu(i, mask) - ip27_send_ipi_single(i, action); + ip27_smp_send_ipi_single(i, action); } -static void ip27_init_secondary(void) +/** + * ip27_smp_ipi_irq - IRQ handler that runs on CPUy and services the IPI. + * @irq: integer of IRQ# for IPI being serviced. + * @dev_id: void pointer to dev_id data. + */ +static irqreturn_t +ip27_smp_ipi_irq(int irq, void *dev_id) { - per_cpu_init(); -} + int hub_bit; + const struct ip27_percpu_data *cpud = this_cpu_ptr(&ip27_cpu); -static void ip27_smp_finish(void) -{ - extern void hub_rt_clock_event_init(void); + if (!cpud->irq_owner[irq]) + return IRQ_NONE; + else + hub_bit = cpud->irq_to_bit[irq]; - hub_rt_clock_event_init(); - local_irq_enable(); + /* Kernel statistics. */ + kstat_incr_irq_this_cpu(irq); + + switch (hub_bit) { + case CPU_RESCHED_A_IRQ: + case CPU_RESCHED_B_IRQ: + scheduler_ipi(); + break; + case CPU_CALL_A_IRQ: + case CPU_CALL_B_IRQ: + generic_smp_call_function_interrupt(); + break; + default: + panic("IP27: Received unknown SMP IPI IRQ %d on CPU %d!", + irq, smp_processor_id()); + } + + return IRQ_HANDLED; } -/* - * 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_thread_info() will work. +/* ----------------------------------------------------------------------- */ + + +/* ----------------------------------------------------------------------- */ +/* SMP CPU Bringup - CPU0 Code */ + +/** + * ip27_smp_alloc_cpupda - configures various cpuid mappings. + * @prom_cpuid: cpuid_t value of the PROM-assigned cpuid. + * @kern_cpuid: int value of the kernel-assigned cpuid. */ -static void ip27_boot_secondary(int cpu, struct task_struct *idle) +static inline void __init +ip27_smp_alloc_cpupda(cpuid_t prom_cpuid, int kern_cpuid) { - unsigned long gp = (unsigned long)task_thread_info(idle); - unsigned long sp = __KSTK_TOS(idle); + cnodeid_t node = get_cpu_cnode(prom_cpuid); + nasid_t nasid = sn_cnodeid_to_nasid[node]; - LAUNCH_SLAVE(cputonasid(cpu), cputoslice(cpu), - (launch_proc_t)MAPPED_KERN_RW_TO_K0(smp_bootstrap), - 0, (void *) sp, (void *) gp); + cpu_to_nasid(kern_cpuid) = nasid; + sn_cpu_info[kern_cpuid].p_nodeid = node; + cpu_to_slice(kern_cpuid) = get_cpu_slice(prom_cpuid); } -static void __init ip27_smp_setup(void) +/** + * ip27_smp_setup - performs housekeeping on each CPU as it comes online. + */ +static void __init +ip27_smp_setup(void) { - cnodeid_t cnode; + cnodeid_t cnode; + nasid_t nasid; + int i; for_each_online_node(cnode) { if (cnode == 0) continue; - intr_clear_all(COMPACT_TO_NASID_NODEID(cnode)); + + nasid = sn_cnodeid_to_nasid[cnode]; + + REMOTE_HUB_S(nasid, PI_INT_MASK0_A, 0); + REMOTE_HUB_S(nasid, PI_INT_MASK0_B, 0); + REMOTE_HUB_S(nasid, PI_INT_MASK1_A, 0); + REMOTE_HUB_S(nasid, PI_INT_MASK1_B, 0); + + for (i = 0; i < LEVELS_PER_SLICE; i++) + REMOTE_HUB_CLR_INTR(nasid, i); } replicate_kernel_text(); /* - * Assumption to be fixed: we're always booted on logical / physical + * XXX: Assumption to be fixed: we're always booted on logical/physical * processor 0. While we're always running on logical processor 0 * this still means this is physical processor zero; it might for * example be disabled in the firmware. */ - alloc_cpupda(0, 0); + ip27_smp_alloc_cpupda(0, 0); +} + +/** + * Used to request IRQs. + */ +DEFINE_PER_CPU(char [9], ip27_ipi_r_name); +DEFINE_PER_CPU(char [9], ip27_ipi_c_name); + +/** + * ip27_smp_prepare_cpus - requests CPU0 IPI interrupt. + * @max_cpus: unused by IP27 SMP code. + * + * Runs on CPU0 + */ +static void __init +ip27_smp_prepare_cpus(unsigned int max_cpus) +{ + const struct ip27_percpu_data *cpud = this_cpu_ptr(&ip27_cpu); + unsigned long irq_flags = (IRQF_PERCPU | IRQF_SHARED); + u8 *ipi_r_name = per_cpu(ip27_ipi_r_name, cpud->id); + u8 *ipi_c_name = per_cpu(ip27_ipi_c_name, cpud->id); + + /* Request IRQ numbers for the CPU IPI bits. */ + sprintf(ipi_r_name, "%dA-rsch", (cpud->nasid + 1)); + sprintf(ipi_c_name, "%dA-call", (cpud->nasid + 1)); + if (request_irq(CPU_RESCHED_A_IRQ, ip27_smp_ipi_irq, irq_flags, + ipi_r_name, ip27_smp_ipi_irq)) + panic("IP27: Can't request CPU%d " + "CPU_RESCHED_A_IRQ IPI", cpud->id); + if (request_irq(CPU_CALL_A_IRQ, ip27_smp_ipi_irq, irq_flags, + ipi_c_name, ip27_smp_ipi_irq)) + panic("IP27: Can't request CPU%d " + "CPU_CALL_A_IRQ IPI", cpud->id); } -static void __init ip27_prepare_cpus(unsigned int max_cpus) +/** + * ip27_smp_boot_secondary - boots remaining CPUs into smp_bootstrap. + * @cpu: integer of CPUx to prepare before booting. + * @idle: struct task_struct containing idle task for CPUx. + * + * Runs on CPU0 and boots CPUx, where x > 0 + */ +static void __init +ip27_smp_boot_secondary(int cpu, struct task_struct *idle) { - /* We already did everything necessary earlier */ + unsigned long gp = (unsigned long)task_thread_info(idle); + unsigned long sp = __KSTK_TOS(idle); + + LAUNCH_SLAVE(cpu_to_nasid(cpu), cpu_to_slice(cpu), + (launch_proc_t)MAPPED_KERN_RW_TO_K0(smp_bootstrap), + 0, (void *) sp, (void *) gp); + + /* Kick the CPU awake. */ + mb(); + } -struct plat_smp_ops ip27_smp_ops = { - .send_ipi_single = ip27_send_ipi_single, - .send_ipi_mask = ip27_send_ipi_mask, - .init_secondary = ip27_init_secondary, - .smp_finish = ip27_smp_finish, - .boot_secondary = ip27_boot_secondary, +/* ----------------------------------------------------------------------- */ + + +/* ----------------------------------------------------------------------- */ +/* SMP CPU Bringup - CPUx Code */ + +/** + * ip27_smp_init_secondary - requests CPUs's IPI IRQ and unmasks interrupts. + * + * Runs on CPUx, where x > 0, after cache probe. + */ +static void __init +ip27_smp_init_secondary(void) +{ + const struct ip27_percpu_data *cpud; + unsigned long irq_flags = (IRQF_PERCPU | IRQF_SHARED); + u8 *ipi_r_name, *ipi_c_name; + + ip27_per_cpu_init(); + cpud = this_cpu_ptr(&ip27_cpu); + ipi_r_name = per_cpu(ip27_ipi_r_name, cpud->id); + ipi_c_name = per_cpu(ip27_ipi_c_name, cpud->id); + + /* Request IRQ numbers for the CPU IPI bits. */ + if (!cpud->slice) { + sprintf(ipi_r_name, "%dA-rsch", (cpud->nasid + 1)); + sprintf(ipi_c_name, "%dA-call", (cpud->nasid + 1)); + if (request_irq(CPU_RESCHED_A_IRQ, ip27_smp_ipi_irq, irq_flags, + ipi_r_name, ip27_smp_ipi_irq)) + panic("IP27: Can't request CPU%d " + "CPU_RESCHED_A_IRQ IPI", cpud->id); + if (request_irq(CPU_CALL_A_IRQ, ip27_smp_ipi_irq, irq_flags, + ipi_c_name, ip27_smp_ipi_irq)) + panic("IP27: Can't request CPU%d " + "CPU_CALL_A_IRQ IPI", cpud->id); + } else { + sprintf(ipi_r_name, "%dB-rsch", (cpud->nasid + 1)); + sprintf(ipi_c_name, "%dB-call", (cpud->nasid + 1)); + if (request_irq(CPU_RESCHED_B_IRQ, ip27_smp_ipi_irq, irq_flags, + ipi_r_name, ip27_smp_ipi_irq)) + panic("IP27: Can't request CPU%d " + "CPU_RESCHED_B_IRQ IPI", cpud->id); + if (request_irq(CPU_CALL_B_IRQ, ip27_smp_ipi_irq, irq_flags, + ipi_c_name, ip27_smp_ipi_irq)) + panic("IP27: Can't request CPU%d " + "CPU_CALL_B_IRQ IPI", cpud->id); + } +} + +/** + * ip27_smp_finish - Sets CPU1 counter and enables interrupts. + * + * Runs on CPUx, where x > 0, before entering the idle loop. + */ +static void __init +ip27_smp_finish(void) +{ + extern void ip27_hub_clockevent_init(void); + + /* + * HUB has two compare registers, one for each CPU, so need to setup + * the clock_event stuff on each CPU before enabling interrupts. + */ + ip27_hub_clockevent_init(); + + /* + * Make sure an interrupt won't happen for a little bit. + */ + write_c0_compare(read_c0_count() + mips_hpt_frequency / HZ); + local_irq_enable(); +} + +/** + * struct ip27_smp_ops - IP27 SMP ops. + * @send_ipi_single: send one interprocessor interrupt. + * @send_ipi_mask: send interprocessor interrup to each CPU. + * @smp_setup: probe for additional CPUs. + * @prepare_cpus: setup CPU0 IPI interrupt. + * @boot_secondary: boot additional CPUs. + * @init_secondary: setup CPUx IPI interrupts. + * @smp_finish: setup CPUx counter, enable IRQs. + */ +struct plat_smp_ops +ip27_smp_ops = { + .send_ipi_single = ip27_smp_send_ipi_single, + .send_ipi_mask = ip27_smp_send_ipi_mask, .smp_setup = ip27_smp_setup, - .prepare_cpus = ip27_prepare_cpus, + .prepare_cpus = ip27_smp_prepare_cpus, + .boot_secondary = ip27_smp_boot_secondary, + .init_secondary = ip27_smp_init_secondary, + .smp_finish = ip27_smp_finish, }; + +/* ----------------------------------------------------------------------- */ + + +/* ----------------------------------------------------------------------- */ +/* Misc SMP code used during init. */ + +/** + * ip27_smp_kl_nasid - gets the nasid of a nodeboard via klconfig. + * @brd: struct klc_lboard pointer of a nodeboard to get the nasid from. + */ +static nasid_t __init +ip27_smp_kl_nasid(struct klc_lboard *brd) +{ + struct klc_hub *hub; + + if (!brd) + return INVALID_NASID; + + /* Find out if we are a completely disabled board */ + hub = KLCF_CAST_HUB(kl_find_first_component(brd, KLSTRUCT_HUB)); + if (!hub) + return INVALID_NASID; + if (!(KLCF_INFO_ENABLED(hub->kl_info))) + return hub->kl_info.physid; + else + return KLCF_BOARD_NASID(brd); +} + +/** + * ip27_smp_do_cpumask - update the smp cpumask for enabled cpus in a nasid. + * @cnode: cnodeid_t value of the compact node id. + * @nasid: nasid_t of the node id (physical node). + * @highest: int value of the highest CPU number discovered. + * + * Returns value of 'highest' back to the caller. + */ +static int __init +ip27_smp_do_cpumask(cnodeid_t cnode, nasid_t nasid, int highest) +{ + static int tot_cpus_found = 0; + struct klc_lboard *brd; + struct klc_cpu *acpu; + int cpus_found = 0; + cpuid_t cpuid; + + brd = kl_find_lboard(KLCF_LBOARD_INFO(nasid), KLTYPE_IP27); + + do { + acpu = KLCF_CAST_CPU(kl_find_first_component(brd, + KLSTRUCT_CPU)); + while (acpu) { + cpuid = acpu->kl_info.virtid; + /* cnode is not valid for completely disabled brds */ + if (ip27_smp_kl_nasid(brd) == KLCF_BOARD_NASID(brd)) + sn_cpuid_to_cnodeid[cpuid] = cnode; + if (cpuid > highest) + highest = cpuid; + /* Only let it join in if it's marked enabled */ + if ((KLCF_INFO_ENABLED(acpu->kl_info)) && + (tot_cpus_found != NR_CPUS)) { + set_cpu_possible(cpuid, true); + ip27_smp_alloc_cpupda(cpuid, tot_cpus_found); + cpus_found++; + tot_cpus_found++; + } + acpu = KLCF_CAST_CPU(kl_find_component(brd, + KLCF_CAST_INFO(acpu), + KLSTRUCT_CPU)); + } + brd = KLCF_NEXT(brd); + if (!brd) + break; + + brd = kl_find_lboard(brd, KLTYPE_IP27); + } while (brd); + + return highest; +} + +/** + * ip27_smp_cpu_node_probe - probe nodeboards for available CPUs via klconfig. + */ +void __init +ip27_smp_cpu_node_probe(void) +{ + int i, highest = 0; + gda_t *gdap = GDA; + + /* + * Initialize the arrays to invalid nodeid (-1) + */ + memset(sn_cnodeid_to_nasid, -1, + sizeof(this_cpu_ptr(__sn_cnodeid_to_nasid))); + memset(sn_nasid_to_cnodeid, -1, + sizeof(this_cpu_ptr(__sn_nasid_to_cnodeid))); + memset(sn_cpuid_to_cnodeid, -1, + sizeof(this_cpu_ptr(__sn_cpuid_to_cnodeid))); + + /* + * XXX: MCD - this whole "compact node" stuff can probably be dropped, + * as we can handle sparse numbering now + */ + nodes_clear(node_possible_map); + nodes_clear(node_online_map); + for (i = 0; i < MAX_COMPACT_NODES; i++) { + nasid_t nasid = gdap->g_nasidtable[i]; + if (nasid == INVALID_NASID) + break; + sn_nasid_to_cnodeid[nasid] = i; + sn_cnodeid_to_nasid[i] = nasid; + node_set_state(num_online_nodes(), N_POSSIBLE); + node_set_online(num_online_nodes()); + highest = ip27_smp_do_cpumask(i, nasid, highest); + } + + pr_info("SMP: Discovered %d cpus on %d nodes\n", (highest + 1), + num_online_nodes()); +} + +/* ----------------------------------------------------------------------- */ diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c index d3b995e..327d594 100644 --- a/arch/mips/sgi-ip27/ip27-timer.c +++ b/arch/mips/sgi-ip27/ip27-timer.c @@ -37,199 +37,266 @@ #include #include -static void enable_rt_irq(struct irq_data *d) -{ -} - -static void disable_rt_irq(struct irq_data *d) -{ -} - -static struct irq_chip rt_irq_type = { - .name = "SN HUB RT timer", - .irq_mask = disable_rt_irq, - .irq_unmask = enable_rt_irq, -}; - -static int rt_next_event(unsigned long delta, struct clock_event_device *evt) -{ - unsigned int cpu = smp_processor_id(); - int slice = cputoslice(cpu); - unsigned long cnt; - - cnt = LOCAL_HUB_L(PI_RT_COUNT); - cnt += delta; - LOCAL_HUB_S(PI_RT_COMPARE_A + PI_COUNT_OFFSET * slice, cnt); +/* Defined in ip27-init.c */ +DECLARE_PER_CPU(struct ip27_percpu_data, ip27_cpu); - return LOCAL_HUB_L(PI_RT_COUNT) >= cnt ? -ETIME : 0; -} - -unsigned int rt_timer_irq; +int ip27_hub_rt_irq_num; -static DEFINE_PER_CPU(struct clock_event_device, hub_rt_clockevent); -static DEFINE_PER_CPU(char [11], hub_rt_name); -static irqreturn_t hub_rt_counter_handler(int irq, void *dev_id) -{ - unsigned int cpu = smp_processor_id(); - struct clock_event_device *cd = &per_cpu(hub_rt_clockevent, cpu); - int slice = cputoslice(cpu); - - /* - * Ack - */ - LOCAL_HUB_S(PI_RT_PEND_A + PI_COUNT_OFFSET * slice, 0); - cd->event_handler(cd); - - return IRQ_HANDLED; -} - -struct irqaction hub_rt_irqaction = { - .handler = hub_rt_counter_handler, - .flags = IRQF_PERCPU | IRQF_TIMER, - .name = "hub-rt", -}; +/* ----------------------------------------------------------------------- */ +/* HUB Clocksource setup. */ /* - * This is a hack; we really need to figure these values out dynamically + * XXX: This is a hack; we really need to figure these values out dynamically * * Since 800 ns works very well with various HUB frequencies, such as * 360, 380, 390 and 400 MHZ, we use 800 ns rtc cycle time. * * Ralf: which clock rate is used to feed the counter? */ -#define NSEC_PER_CYCLE 800 -#define CYCLES_PER_SEC (NSEC_PER_SEC / NSEC_PER_CYCLE) +#define HUB_NSEC_PER_CYCLE 800 +#define HUB_CYCLES_PER_SEC (NSEC_PER_SEC / HUB_NSEC_PER_CYCLE) -void hub_rt_clock_event_init(void) +/** + * ip27_hub_csrc_counter_read - read HUB counter register (52-bit). + * @clocksource: pointer to clocksource struct. (unused) + * + * Returns cycle_t value of the HUB count register. + */ +static cycle_t +ip27_hub_csrc_counter_read(struct clocksource *cs) { - unsigned int cpu = smp_processor_id(); - struct clock_event_device *cd = &per_cpu(hub_rt_clockevent, cpu); - unsigned char *name = per_cpu(hub_rt_name, cpu); - int irq = rt_timer_irq; - - sprintf(name, "hub-rt %d", cpu); - cd->name = name; - cd->features = CLOCK_EVT_FEAT_ONESHOT; - clockevent_set_clock(cd, CYCLES_PER_SEC); - cd->max_delta_ns = clockevent_delta2ns(0xfffffffffffff, cd); - cd->min_delta_ns = clockevent_delta2ns(0x300, cd); - cd->rating = 200; - cd->irq = irq; - cd->cpumask = cpumask_of(cpu); - cd->set_next_event = rt_next_event; - clockevents_register_device(cd); + return REMOTE_HUB_L(per_cpu(ip27_cpu, 0).nasid, PI_RT_COUNT); } -static void __init hub_rt_clock_event_global_init(void) +/** + * struct ip27_hub_clocksource - HUB clocksource definition. + * @name: self-explanatory. + * @rating: quality of this clocksource (HUB has 80ns cycle time). + * @read: pointer to function to read the counter register. + * @mask: bitmask for the counter (52bit counter/24bit compare). + * @flags: clocksource flags. + */ +struct clocksource +ip27_hub_clocksource = { + .name = "HUB", + .rating = 400, + .read = ip27_hub_csrc_counter_read, + .mask = CLOCKSOURCE_MASK(52), + .flags = (CLOCK_SOURCE_IS_CONTINUOUS | CLOCK_SOURCE_VALID_FOR_HRES), +}; + +/** + * ip27_hub_read_sched_clock - make the HUB counter the sched_clock() source. + * + * Returns u64 value of the HUB count register. + */ +static u64 notrace +ip27_hub_csrc_read_sched_clock(void) { - int irq; + return REMOTE_HUB_L(per_cpu(ip27_cpu, 0).nasid, PI_RT_COUNT); +} - do { - smp_wmb(); - irq = rt_timer_irq; - if (irq) - break; +/** + * ip27_hub_clocksource_init - init the clocksource for HUB. + */ +static void __init +ip27_hub_clocksource_init(void) +{ + struct clocksource *cs = &ip27_hub_clocksource; - irq = allocate_irqno(); - if (irq < 0) - panic("Allocation of irq number for timer failed"); - } while (xchg(&rt_timer_irq, irq)); + clocksource_register_hz(cs, HUB_CYCLES_PER_SEC); - irq_set_chip_and_handler(irq, &rt_irq_type, handle_percpu_irq); - setup_irq(irq, &hub_rt_irqaction); + sched_clock_register(ip27_hub_csrc_read_sched_clock, 52, + HUB_CYCLES_PER_SEC); } -static cycle_t hub_rt_read(struct clocksource *cs) +/* ----------------------------------------------------------------------- */ + + +/* ----------------------------------------------------------------------- */ +/* HUB Clockevent setup. */ + +/* Should be globally-visible now. */ +DEFINE_PER_CPU(struct clock_event_device, ip27_hub_clockevent); +DEFINE_PER_CPU(char [11], ip27_hub_cevt_name); + +/** + * ip27_hub_rt_next_event - resets the compare bit on HUB for CPUA. + * @delta: difference between count and compare. + * @evt: pointer to clock_event_device struct. + * + * Returns -ETIME if local HUB counter is > cnt, else 0. + * + * HUB has one count register (PI_RT_COUNT) and two compare registers + * (PI_RT_COMPARE_A & PI_RT_COMPARE_B), one for each of the two CPUs attached + * to a HUB. + */ +static int +ip27_hub_rt_next_event(unsigned long delta, struct clock_event_device *evt) { - return REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT); -} + unsigned long cnt; -struct clocksource hub_rt_clocksource = { - .name = "HUB-RT", - .rating = 200, - .read = hub_rt_read, - .mask = CLOCKSOURCE_MASK(52), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; + cnt = (LOCAL_HUB_L(PI_RT_COUNT) + delta); + LOCAL_HUB_S(PI_RT_COMPARE_A + PI_COUNT_OFFSET * + this_cpu_read(ip27_cpu.slice), cnt); -static u64 notrace hub_rt_read_sched_clock(void) + return ((LOCAL_HUB_L(PI_RT_COUNT) >= cnt) ? -ETIME : 0); +} + +/** + * ip27_hub_rt_event_handler - Clock event handler on HUB. + * @cd: pointer to clock_event_device struct. + * + * Not supported on HUB. + */ +static void +ip27_hub_rt_event_handler(struct clock_event_device *cd) { - return REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT); + /* Nothing to do */ } -static void __init hub_rt_clocksource_init(void) +/** + * ip27_hub_rt_compare_irq - IRQ handler for the HUB compare interrupt. + * @irq: IRQ number. + * @dev_id: void pointer to the clock_event_device struct. (unused on IP27) + * + * Always returns IRQ_HANDLED. + */ +static irqreturn_t +ip27_hub_rt_compare_irq(int irq, void *dev_id) { - struct clocksource *cs = &hub_rt_clocksource; + struct clock_event_device *cd = this_cpu_ptr(&ip27_hub_clockevent); - clocksource_register_hz(cs, CYCLES_PER_SEC); + /* Ack */ + LOCAL_HUB_S(PI_RT_PEND_A + PI_COUNT_OFFSET * + this_cpu_read(ip27_cpu.slice), 0); + cd->event_handler(cd); - sched_clock_register(hub_rt_read_sched_clock, 52, CYCLES_PER_SEC); + return IRQ_HANDLED; } -void __init plat_time_init(void) +/** + * struct ip27_hub_rt_irqaction - irqaction block for HUB. + * @name: self-explanatory. + * @flags: HUB counter IRQ flags. + * @handler: pointer to IRQ handler for the counter interrupt. + */ +struct irqaction +ip27_hub_rt_irqaction = { + .name = "hub_timer", + .flags = (IRQF_PERCPU | IRQF_TIMER | IRQF_NOBALANCING), + .handler = ip27_hub_rt_compare_irq, +}; + +/** + * ip27_hub_clockevent_init - per-HUB clockevent initialization. + */ +void +ip27_hub_clockevent_init(void) { - hub_rt_clocksource_init(); - hub_rt_clock_event_global_init(); - hub_rt_clock_event_init(); + const struct ip27_percpu_data *cpud = this_cpu_ptr(&ip27_cpu); + struct clock_event_device *cd = this_cpu_ptr(&ip27_hub_clockevent); + unsigned char *name = per_cpu(ip27_hub_cevt_name, cpud->id); + + sprintf(name, "HUB %d", cpud->id); + cd->name = name; + cd->features = CLOCK_EVT_FEAT_ONESHOT; + clockevent_set_clock(cd, HUB_CYCLES_PER_SEC); + cd->max_delta_ns = clockevent_delta2ns(0xfffffffffffff, cd); + cd->min_delta_ns = clockevent_delta2ns(0x300, cd); + cd->rating = 400; + cd->irq = ip27_hub_rt_irq_num; + cd->cpumask = cpumask_of(cpud->id); + cd->set_next_event = ip27_hub_rt_next_event; + cd->event_handler = ip27_hub_rt_event_handler; + clockevents_register_device(cd); } -void cpu_time_init(void) -{ - lboard_t *board; - klcpu_t *cpu; - int cpuid; +/* ----------------------------------------------------------------------- */ - /* Don't use ARCS. ARCS is fragile. Klconfig is simple and sane. */ - board = find_lboard(KL_CONFIG_INFO(get_nasid()), KLTYPE_IP27); - if (!board) - panic("Can't find board info for myself."); - cpuid = LOCAL_HUB_L(PI_CPU_NUM) ? IP27_CPU0_INDEX : IP27_CPU1_INDEX; - cpu = (klcpu_t *) KLCF_COMP(board, cpuid); - if (!cpu) - panic("No information about myself?"); +/* ----------------------------------------------------------------------- */ +/* HUB "RT" IRQ. */ - printk("CPU %d clock is %dMHz.\n", smp_processor_id(), cpu->cpu_speed); +/* + * HUB has a separate interrupt pending register for its "realtime" (RT) + * counter component, PI_RT_PEND_A or PI_RT_PEND_B. We use dummy irq_chip + * stubs to handle this, because the real ack'ing happens in + * ip27_hub_compare_irq, when invoked by the clockevent subsystem. + */ - set_c0_status(SRB_TIMOCLK); +/** + * ip27_mask_hub_rt_irq - masks a HUB RT IRQ. + * @d: struct irq_data containing IRQ information. + */ +static void +ip27_mask_hub_rt_irq(struct irq_data *d) +{ + /* Nothing */ } -void hub_rtc_init(cnodeid_t cnode) +/** + * ip27_unmask_hub_rt_irq - unmasks a HUB RT IRQ. + * @d: struct irq_data containing IRQ information. + */ +static void +ip27_unmask_hub_rt_irq(struct irq_data *d) { - - /* - * We only need to initialize the current node. - * If this is not the current node then it is a cpuless - * node and timeouts will not happen there. - */ - if (get_compact_nodeid() == cnode) { - LOCAL_HUB_S(PI_RT_EN_A, 1); - LOCAL_HUB_S(PI_RT_EN_B, 1); - LOCAL_HUB_S(PI_PROF_EN_A, 0); - LOCAL_HUB_S(PI_PROF_EN_B, 0); - LOCAL_HUB_S(PI_RT_COUNT, 0); - LOCAL_HUB_S(PI_RT_PEND_A, 0); - LOCAL_HUB_S(PI_RT_PEND_B, 0); - } + /* Nothing */ } -static int __init sgi_ip27_rtc_devinit(void) +/** + * struct ip27_hub_rt_irq - HUB struct irq_chip ops. + * @irq_mask: mask function. + * @irq_unmask: unmask function. + */ +static struct irq_chip +ip27_hub_rt_irq = { + .name = "HUB_RT", + .irq_mask = ip27_mask_hub_rt_irq, + .irq_unmask = ip27_unmask_hub_rt_irq, +}; + +/** + * ip27_hub_clock_event_irq_init - allocates a dynamic IRQ for HUB RT. + * @d: struct irq_data containing IRQ information. + */ +static void __init +ip27_hub_rt_irq_init(void) { - struct resource res; + int irq; - memset(&res, 0, sizeof(res)); - res.start = XPHYSADDR(KL_CONFIG_CH_CONS_INFO(master_nasid)->memory_base + - IOC3_BYTEBUS_DEV0); - res.end = res.start + 32767; - res.flags = IORESOURCE_MEM; + do { + smp_wmb(); + irq = ip27_hub_rt_irq_num; + if (irq) + break; + + irq = ip27_alloc_irq_num(); + if (irq < 0) + panic("Allocation of HUB timer IRQ number failed!"); + } while (xchg(&ip27_hub_rt_irq_num, irq)); - return IS_ERR(platform_device_register_simple("rtc-m48t35", -1, - &res, 1)); + irq_set_chip_and_handler(irq, &ip27_hub_rt_irq, handle_percpu_irq); + setup_irq(ip27_hub_rt_irq_num, &ip27_hub_rt_irqaction); } -/* - * kludge make this a device_initcall after ioc3 resource conflicts - * are resolved +/* ----------------------------------------------------------------------- */ + + +/* ----------------------------------------------------------------------- */ + +/** + * plat_time_init - platform time initialization. */ -late_initcall(sgi_ip27_rtc_devinit); +void __init +plat_time_init(void) +{ + /* Init clocksource and clockevent for HUB on CPU0. */ + ip27_hub_clocksource_init(); + ip27_hub_rt_irq_init(); + ip27_hub_clockevent_init(); +} + +/* ----------------------------------------------------------------------- */ diff --git a/arch/mips/sgi-ip27/ip27-xtalk.c b/arch/mips/sgi-ip27/ip27-xtalk.c index 20f582a..4934d56 100644 --- a/arch/mips/sgi-ip27/ip27-xtalk.c +++ b/arch/mips/sgi-ip27/ip27-xtalk.c @@ -9,60 +9,153 @@ #include #include -#include -#include -#include -#include +#include + #include +#include + +#include + +#include +#include +#include +#include +#define xtalk_read __raw_readl -#define XBOW_WIDGET_PART_NUM 0x0 -#define XXBOW_WIDGET_PART_NUM 0xd000 /* Xbow in Xbridge */ #define BASE_XBOW_PORT 8 /* Lowest external port */ -extern int bridge_probe(nasid_t nasid, int widget, int masterwid); +struct widget_data { + u32 mfgr; + u32 part; + char *name; + char *rev; +}; + +/* XXX: Kill */ +unsigned long inline +xtalk_get_swin(int node, int wid) +{ + return NODE_SWIN_BASE(node, wid); +} -static int probe_one_port(nasid_t nasid, int widget, int masterwid) +static void __init +xtalk_bridge_platform_setup(nasid_t nasid, const struct widget_data *wd, + xwidgetnum_t widget, xwidgetnum_t master_wid) { - widgetreg_t widget_id; - xwidget_part_num_t partnum; + struct platform_device *xw_pdev; + struct xwidget_platform_data *xw_pdata; - widget_id = *(volatile widgetreg_t *) - (RAW_NODE_SWIN_BASE(nasid, widget) + WIDGET_ID); - partnum = XWIDGET_PART_NUM(widget_id); + xw_pdata = kzalloc(sizeof(struct xwidget_platform_data), GFP_KERNEL); + xw_pdata->nasid = nasid; + xw_pdata->master_wid = master_wid; - printk(KERN_INFO "Cpu %d, Nasid 0x%x, widget 0x%x (partnum 0x%x) is ", - smp_processor_id(), nasid, widget, partnum); + xw_pdev = kzalloc(sizeof(struct platform_device), GFP_KERNEL); + xw_pdev->name = wd->name; + xw_pdev->id = widget; + xw_pdev->dev.platform_data = xw_pdata; - switch (partnum) { - case BRIDGE_WIDGET_PART_NUM: - case XBRIDGE_WIDGET_PART_NUM: - bridge_probe(nasid, widget, masterwid); - break; - default: - break; + platform_device_register(xw_pdev); + pr_info("xtalk:n%d/%x %s widget (rev %s) registered as a " + "platform device.\n", nasid, widget, wd->name, wd->rev); +} + +static unsigned int __init +xtalk_get_widget_data(nasid_t nasid, xwidgetnum_t wid) +{ + unsigned int link_stat; + + if (wid != XTALK_XBOW && + (wid < XTALK_LOW_DEV || wid > XTALK_HIGH_DEV)) + return XTALK_NODEV; + + if (wid) { + link_stat = xtalk_read((void *)(RAW_NODE_SWIN_BASE(nasid, 0) + + XBOW_REG_LINK_STAT_0 + + XBOW_REG_LINK_BLOCK_SIZE * + (wid - XTALK_LOW_DEV))); + /* Is the link alive? */ + if (!(link_stat & XBOW_REG_LINK_ALIVE)) + return XTALK_NODEV; } - return 0; + return xtalk_read((void *)(RAW_NODE_SWIN_BASE(nasid, wid) + WIDGET_ID)); } -static int xbow_probe(nasid_t nasid) +static struct widget_data __init * +xtalk_get_widget_info(nasid_t nasid, xwidgetnum_t widget) { - lboard_t *brd; - klxbow_t *xbow_p; - unsigned masterwid, i; + u32 wid_data, rev; + struct widget_data *wd; + const struct widget_ident *wi; + + wd = kzalloc(sizeof(struct widget_data), GFP_KERNEL); + if (!wd) + return NULL; + + wid_data = xtalk_get_widget_data(nasid, widget); + if (wid_data == XTALK_NODEV) + return NULL; + + rev = XWIDGET_REV_NUM(wid_data); + for (wi = widget_idents; wi->name; wi++) + if ((wi->mfgr == XWIDGET_MFG_NUM(wid_data)) && + (wi->part == XWIDGET_PART_NUM(wid_data))) + break; + + if (unlikely(wi->name == NULL)) { + pr_info("xtalk:n%d/%x unknown widget 0x%x\n", nasid, + widget, wid_data); + return NULL; + } + + wd->mfgr = wi->mfgr; + wd->part = wi->part; + wd->name = wi->name; + wd->rev = (wi->revs[rev] ? wi->revs[rev] : "unknown"); - printk("is xbow\n"); + return wd; +} + +static void __init +xtalk_init_widget(nasid_t nasid, xwidgetnum_t widget, xwidgetnum_t masterwid) +{ + struct widget_data *wd; + + wd = xtalk_get_widget_info(nasid, widget); + if (!wd) + return; + + switch (wd->part) { + case WIDGET_BRIDG_PART_NUM: + case WIDGET_XBRDG_PART_NUM: + xtalk_bridge_platform_setup(nasid, wd, widget, masterwid); + break; + default: + if (platform_device_register_simple(wd->name, widget, NULL, 0)) + pr_info("xtalk:n%d/%x %s widget (rev %s) " + "registered as a platform device.\n", nasid, + widget, wd->name, wd->rev); + } + kzfree(wd); +} + +static int __init +xbow_probe(nasid_t nasid) +{ + struct klc_lboard *brd; + struct klc_xbow *xbow_p; + xwidgetnum_t masterwid, i; /* * found xbow, so may have multiple bridges * need to probe xbow */ - brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_MIDPLANE8); + brd = kl_find_lboard(KLCF_LBOARD_INFO(nasid), KLTYPE_MIDPLANE); if (!brd) return -ENODEV; - xbow_p = (klxbow_t *)find_component(brd, NULL, KLSTRUCT_XBOW); + xbow_p = KLCF_CAST_XBOW(kl_find_component(brd, NULL, KLSTRUCT_XBOW)); if (!xbow_p) return -ENODEV; @@ -93,43 +186,62 @@ static int xbow_probe(nasid_t nasid) for (i = HUB_WIDGET_ID_MIN; i <= HUB_WIDGET_ID_MAX; i++) { if (XBOW_PORT_IS_ENABLED(xbow_p, i) && XBOW_PORT_TYPE_IO(xbow_p, i)) - probe_one_port(nasid, i, masterwid); + xtalk_init_widget(nasid, i, masterwid); } return 0; } -void xtalk_probe_node(cnodeid_t nid) +void __init +xtalk_probe_node(cnodeid_t cnodeid) { - volatile u64 hubreg; - nasid_t nasid; - xwidget_part_num_t partnum; - widgetreg_t widget_id; + volatile u64 hubreg; + nasid_t nasid; + struct widget_data *wd; - nasid = COMPACT_TO_NASID_NODEID(nid); + nasid = sn_cnodeid_to_nasid[cnodeid]; hubreg = REMOTE_HUB_L(nasid, IIO_LLP_CSR); /* check whether the link is up */ if (!(hubreg & IIO_LLP_CSR_IS_UP)) return; - widget_id = *(volatile widgetreg_t *) - (RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID); - partnum = XWIDGET_PART_NUM(widget_id); - - printk(KERN_INFO "Cpu %d, Nasid 0x%x: partnum 0x%x is ", - smp_processor_id(), nasid, partnum); + wd = xtalk_get_widget_info(nasid, XTALK_XBOW); + if (!wd) + return; - switch (partnum) { - case BRIDGE_WIDGET_PART_NUM: - bridge_probe(nasid, 0x8, 0xa); + switch (wd->part) { + case WIDGET_BRIDG_PART_NUM: + xtalk_bridge_platform_setup(nasid, wd, 0x8, 0xa); break; - case XBOW_WIDGET_PART_NUM: - case XXBOW_WIDGET_PART_NUM: + case WIDGET_XBOW_PART_NUM: + case WIDGET_XXBOW_PART_NUM: + pr_info("xtalk:n%d/%lx %s widget (rev %s)\n", + nasid, XTALK_XBOW, wd->name, wd->rev); xbow_probe(nasid); break; default: - printk(" unknown widget??\n"); - break; + if (platform_device_register_simple(wd->name, XTALK_XBOW, NULL, 0)) + pr_info("xtalk:n%d/%lx %s widget (rev %s) " + "registered as platform device.\n", nasid, + XTALK_XBOW, wd->name, wd->rev); } + kzfree(wd); } + +static int __init +ip27_xtalk_init(void) +{ + cnodeid_t cnode; + + /* XXX: kludge alert.. */ + ioport_resource.end = ~0UL; + + for_each_online_node(cnode) { + xtalk_probe_node(cnode); + } + + return 0; +} + +arch_initcall(ip27_xtalk_init);