x86, platforms: Remove NUMAQ
The NUMAQ support seems to be unmaintained, remove it. Cc: Paul Gortmaker <paul.gortmaker@windriver.com> Cc: David Rientjes <rientjes@google.com> Acked-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Signed-off-by: H. Peter Anvin <hpa@linux.intel.com> Link: http://lkml.kernel.org/r/n/530CFD6C.7040705@zytor.com
This commit is contained in:
		
					parent
					
						
							
								c5f9ee3d66
							
						
					
				
			
			
				commit
				
					
						b5660ba76b
					
				
			
		
					 11 changed files with 9 additions and 908 deletions
				
			
		|  | @ -346,7 +346,6 @@ config X86_EXTENDED_PLATFORM | |||
| 	  for the following (non-PC) 32 bit x86 platforms: | ||||
| 		Goldfish (Android emulator) | ||||
| 		AMD Elan | ||||
| 		NUMAQ (IBM/Sequent) | ||||
| 		RDC R-321x SoC | ||||
| 		SGI 320/540 (Visual Workstation) | ||||
| 		STA2X11-based (e.g. Northville) | ||||
|  | @ -487,32 +486,18 @@ config X86_32_NON_STANDARD | |||
| 	depends on X86_32 && SMP | ||||
| 	depends on X86_EXTENDED_PLATFORM | ||||
| 	---help--- | ||||
| 	  This option compiles in the NUMAQ, bigsmp, and STA2X11 default | ||||
| 	  subarchitectures.  It is intended for a generic binary kernel. If you | ||||
| 	  select them all, kernel will probe it one by one and will fallback to | ||||
| 	  default. | ||||
| 	  This option compiles in the bigsmp and STA2X11 default | ||||
| 	  subarchitectures.  It is intended for a generic binary | ||||
| 	  kernel. If you select them all, kernel will probe it one by | ||||
| 	  one and will fallback to default. | ||||
| 
 | ||||
| # Alphabetically sorted list of Non standard 32 bit platforms | ||||
| 
 | ||||
| config X86_NUMAQ | ||||
| 	bool "NUMAQ (IBM/Sequent)" | ||||
| 	depends on X86_32_NON_STANDARD | ||||
| 	depends on PCI | ||||
| 	select NUMA | ||||
| 	select X86_MPPARSE | ||||
| 	---help--- | ||||
| 	  This option is used for getting Linux to run on a NUMAQ (IBM/Sequent) | ||||
| 	  NUMA multiquad box. This changes the way that processors are | ||||
| 	  bootstrapped, and uses Clustered Logical APIC addressing mode instead | ||||
| 	  of Flat Logical.  You will need a new lynxer.elf file to flash your | ||||
| 	  firmware with - send email to <Martin.Bligh@us.ibm.com>. | ||||
| 
 | ||||
| config X86_SUPPORTS_MEMORY_FAILURE | ||||
| 	def_bool y | ||||
| 	# MCE code calls memory_failure(): | ||||
| 	depends on X86_MCE | ||||
| 	# On 32-bit this adds too big of NODES_SHIFT and we run out of page flags: | ||||
| 	depends on !X86_NUMAQ | ||||
| 	# On 32-bit SPARSEMEM adds too big of SECTIONS_WIDTH: | ||||
| 	depends on X86_64 || !SPARSEMEM | ||||
| 	select ARCH_SUPPORTS_MEMORY_FAILURE | ||||
|  | @ -783,7 +768,7 @@ config NR_CPUS | |||
| 	range 2 8192 if SMP && !MAXSMP && CPUMASK_OFFSTACK && X86_64 | ||||
| 	default "1" if !SMP | ||||
| 	default "8192" if MAXSMP | ||||
| 	default "32" if SMP && (X86_NUMAQ || X86_BIGSMP) | ||||
| 	default "32" if SMP && X86_BIGSMP | ||||
| 	default "8" if SMP | ||||
| 	---help--- | ||||
| 	  This allows you to specify the maximum number of CPUs which this | ||||
|  | @ -1064,13 +1049,11 @@ config X86_CPUID | |||
| 
 | ||||
| choice | ||||
| 	prompt "High Memory Support" | ||||
| 	default HIGHMEM64G if X86_NUMAQ | ||||
| 	default HIGHMEM4G | ||||
| 	depends on X86_32 | ||||
| 
 | ||||
| config NOHIGHMEM | ||||
| 	bool "off" | ||||
| 	depends on !X86_NUMAQ | ||||
| 	---help--- | ||||
| 	  Linux can use up to 64 Gigabytes of physical memory on x86 systems. | ||||
| 	  However, the address space of 32-bit x86 processors is only 4 | ||||
|  | @ -1107,7 +1090,6 @@ config NOHIGHMEM | |||
| 
 | ||||
| config HIGHMEM4G | ||||
| 	bool "4GB" | ||||
| 	depends on !X86_NUMAQ | ||||
| 	---help--- | ||||
| 	  Select this if you have a 32-bit processor and between 1 and 4 | ||||
| 	  gigabytes of physical RAM. | ||||
|  | @ -1199,8 +1181,8 @@ config DIRECT_GBPAGES | |||
| config NUMA | ||||
| 	bool "Numa Memory Allocation and Scheduler Support" | ||||
| 	depends on SMP | ||||
| 	depends on X86_64 || (X86_32 && HIGHMEM64G && (X86_NUMAQ || X86_BIGSMP)) | ||||
| 	default y if (X86_NUMAQ || X86_BIGSMP) | ||||
| 	depends on X86_64 || (X86_32 && HIGHMEM64G && X86_BIGSMP) | ||||
| 	default y if X86_BIGSMP | ||||
| 	---help--- | ||||
| 	  Enable NUMA (Non Uniform Memory Access) support. | ||||
| 
 | ||||
|  | @ -1211,8 +1193,7 @@ config NUMA | |||
| 	  For 64-bit this is recommended if the system is Intel Core i7 | ||||
| 	  (or later), AMD Opteron, or EM64T NUMA. | ||||
| 
 | ||||
| 	  For 32-bit this is only needed on (rare) 32-bit-only platforms | ||||
| 	  that support NUMA topologies, such as NUMAQ, or if you boot a 32-bit | ||||
| 	  For 32-bit this is only needed if you boot a 32-bit | ||||
| 	  kernel on a 64-bit NUMA platform. | ||||
| 
 | ||||
| 	  Otherwise, you should say N. | ||||
|  | @ -1258,7 +1239,6 @@ config NODES_SHIFT | |||
| 	range 1 10 | ||||
| 	default "10" if MAXSMP | ||||
| 	default "6" if X86_64 | ||||
| 	default "4" if X86_NUMAQ | ||||
| 	default "3" | ||||
| 	depends on NEED_MULTIPLE_NODES | ||||
| 	---help--- | ||||
|  |  | |||
|  | @ -363,7 +363,7 @@ config X86_P6_NOP | |||
| 
 | ||||
| config X86_TSC | ||||
| 	def_bool y | ||||
| 	depends on ((MWINCHIP3D || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MVIAC7 || MGEODEGX1 || MGEODE_LX || MCORE2 || MATOM) && !X86_NUMAQ) || X86_64 | ||||
| 	depends on (MWINCHIP3D || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MVIAC7 || MGEODEGX1 || MGEODE_LX || MCORE2 || MATOM) || X86_64 | ||||
| 
 | ||||
| config X86_CMPXCHG64 | ||||
| 	def_bool y | ||||
|  |  | |||
|  | @ -11,9 +11,6 @@ | |||
| #ifdef CONFIG_NUMA | ||||
| extern struct pglist_data *node_data[]; | ||||
| #define NODE_DATA(nid)	(node_data[nid]) | ||||
| 
 | ||||
| #include <asm/numaq.h> | ||||
| 
 | ||||
| #endif /* CONFIG_NUMA */ | ||||
| 
 | ||||
| #ifdef CONFIG_DISCONTIGMEM | ||||
|  |  | |||
|  | @ -25,12 +25,6 @@ extern int pic_mode; | |||
| 
 | ||||
| extern unsigned int def_to_bigsmp; | ||||
| 
 | ||||
| #ifdef CONFIG_X86_NUMAQ | ||||
| extern int mp_bus_id_to_node[MAX_MP_BUSSES]; | ||||
| extern int mp_bus_id_to_local[MAX_MP_BUSSES]; | ||||
| extern int quad_local_to_mp_bus_id [NR_CPUS/4][4]; | ||||
| #endif | ||||
| 
 | ||||
| #else /* CONFIG_X86_64: */ | ||||
| 
 | ||||
| #define MAX_MP_BUSSES		256 | ||||
|  |  | |||
|  | @ -1,171 +0,0 @@ | |||
| /*
 | ||||
|  * Written by: Patricia Gaughen, IBM Corporation | ||||
|  * | ||||
|  * Copyright (C) 2002, IBM Corp. | ||||
|  * | ||||
|  * All rights reserved. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation; either version 2 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||||
|  * NON INFRINGEMENT.  See the GNU General Public License for more | ||||
|  * details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||||
|  * | ||||
|  * Send feedback to <gone@us.ibm.com> | ||||
|  */ | ||||
| 
 | ||||
| #ifndef _ASM_X86_NUMAQ_H | ||||
| #define _ASM_X86_NUMAQ_H | ||||
| 
 | ||||
| #ifdef CONFIG_X86_NUMAQ | ||||
| 
 | ||||
| extern int found_numaq; | ||||
| extern int numaq_numa_init(void); | ||||
| extern int pci_numaq_init(void); | ||||
| 
 | ||||
| extern void *xquad_portio; | ||||
| 
 | ||||
| #define XQUAD_PORTIO_BASE 0xfe400000 | ||||
| #define XQUAD_PORTIO_QUAD 0x40000  /* 256k per quad. */ | ||||
| #define XQUAD_PORT_ADDR(port, quad) (xquad_portio + (XQUAD_PORTIO_QUAD*quad) + port) | ||||
| 
 | ||||
| /*
 | ||||
|  * SYS_CFG_DATA_PRIV_ADDR, struct eachquadmem, and struct sys_cfg_data are the | ||||
|  */ | ||||
| #define SYS_CFG_DATA_PRIV_ADDR		0x0009d000 /* place for scd in private | ||||
| 						      quad space */ | ||||
| 
 | ||||
| /*
 | ||||
|  * Communication area for each processor on lynxer-processor tests. | ||||
|  * | ||||
|  * NOTE: If you change the size of this eachproc structure you need | ||||
|  *       to change the definition for EACH_QUAD_SIZE. | ||||
|  */ | ||||
| struct eachquadmem { | ||||
| 	unsigned int	priv_mem_start;		/* Starting address of this */ | ||||
| 						/* quad's private memory. */ | ||||
| 						/* This is always 0. */ | ||||
| 						/* In MB. */ | ||||
| 	unsigned int	priv_mem_size;		/* Size of this quad's */ | ||||
| 						/* private memory. */ | ||||
| 						/* In MB. */ | ||||
| 	unsigned int	low_shrd_mem_strp_start;/* Starting address of this */ | ||||
| 						/* quad's low shared block */ | ||||
| 						/* (untranslated). */ | ||||
| 						/* In MB. */ | ||||
| 	unsigned int	low_shrd_mem_start;	/* Starting address of this */ | ||||
| 						/* quad's low shared memory */ | ||||
| 						/* (untranslated). */ | ||||
| 						/* In MB. */ | ||||
| 	unsigned int	low_shrd_mem_size;	/* Size of this quad's low */ | ||||
| 						/* shared memory. */ | ||||
| 						/* In MB. */ | ||||
| 	unsigned int	lmmio_copb_start;	/* Starting address of this */ | ||||
| 						/* quad's local memory */ | ||||
| 						/* mapped I/O in the */ | ||||
| 						/* compatibility OPB. */ | ||||
| 						/* In MB. */ | ||||
| 	unsigned int	lmmio_copb_size;	/* Size of this quad's local */ | ||||
| 						/* memory mapped I/O in the */ | ||||
| 						/* compatibility OPB. */ | ||||
| 						/* In MB. */ | ||||
| 	unsigned int	lmmio_nopb_start;	/* Starting address of this */ | ||||
| 						/* quad's local memory */ | ||||
| 						/* mapped I/O in the */ | ||||
| 						/* non-compatibility OPB. */ | ||||
| 						/* In MB. */ | ||||
| 	unsigned int	lmmio_nopb_size;	/* Size of this quad's local */ | ||||
| 						/* memory mapped I/O in the */ | ||||
| 						/* non-compatibility OPB. */ | ||||
| 						/* In MB. */ | ||||
| 	unsigned int	io_apic_0_start;	/* Starting address of I/O */ | ||||
| 						/* APIC 0. */ | ||||
| 	unsigned int	io_apic_0_sz;		/* Size I/O APIC 0. */ | ||||
| 	unsigned int	io_apic_1_start;	/* Starting address of I/O */ | ||||
| 						/* APIC 1. */ | ||||
| 	unsigned int	io_apic_1_sz;		/* Size I/O APIC 1. */ | ||||
| 	unsigned int	hi_shrd_mem_start;	/* Starting address of this */ | ||||
| 						/* quad's high shared memory.*/ | ||||
| 						/* In MB. */ | ||||
| 	unsigned int	hi_shrd_mem_size;	/* Size of this quad's high */ | ||||
| 						/* shared memory. */ | ||||
| 						/* In MB. */ | ||||
| 	unsigned int	mps_table_addr;		/* Address of this quad's */ | ||||
| 						/* MPS tables from BIOS, */ | ||||
| 						/* in system space.*/ | ||||
| 	unsigned int	lcl_MDC_pio_addr;	/* Port-I/O address for */ | ||||
| 						/* local access of MDC. */ | ||||
| 	unsigned int	rmt_MDC_mmpio_addr;	/* MM-Port-I/O address for */ | ||||
| 						/* remote access of MDC. */ | ||||
| 	unsigned int	mm_port_io_start;	/* Starting address of this */ | ||||
| 						/* quad's memory mapped Port */ | ||||
| 						/* I/O space. */ | ||||
| 	unsigned int	mm_port_io_size;	/* Size of this quad's memory*/ | ||||
| 						/* mapped Port I/O space. */ | ||||
| 	unsigned int	mm_rmt_io_apic_start;	/* Starting address of this */ | ||||
| 						/* quad's memory mapped */ | ||||
| 						/* remote I/O APIC space. */ | ||||
| 	unsigned int	mm_rmt_io_apic_size;	/* Size of this quad's memory*/ | ||||
| 						/* mapped remote I/O APIC */ | ||||
| 						/* space. */ | ||||
| 	unsigned int	mm_isa_start;		/* Starting address of this */ | ||||
| 						/* quad's memory mapped ISA */ | ||||
| 						/* space (contains MDC */ | ||||
| 						/* memory space). */ | ||||
| 	unsigned int	mm_isa_size;		/* Size of this quad's memory*/ | ||||
| 						/* mapped ISA space (contains*/ | ||||
| 						/* MDC memory space). */ | ||||
| 	unsigned int	rmt_qmi_addr;		/* Remote addr to access QMI.*/ | ||||
| 	unsigned int	lcl_qmi_addr;		/* Local addr to access QMI. */ | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
|  * Note: This structure must be NOT be changed unless the multiproc and | ||||
|  * OS are changed to reflect the new structure. | ||||
|  */ | ||||
| struct sys_cfg_data { | ||||
| 	unsigned int	quad_id; | ||||
| 	unsigned int	bsp_proc_id; /* Boot Strap Processor in this quad. */ | ||||
| 	unsigned int	scd_version; /* Version number of this table. */ | ||||
| 	unsigned int	first_quad_id; | ||||
| 	unsigned int	quads_present31_0; /* 1 bit for each quad */ | ||||
| 	unsigned int	quads_present63_32; /* 1 bit for each quad */ | ||||
| 	unsigned int	config_flags; | ||||
| 	unsigned int	boot_flags; | ||||
| 	unsigned int	csr_start_addr; /* Absolute value (not in MB) */ | ||||
| 	unsigned int	csr_size; /* Absolute value (not in MB) */ | ||||
| 	unsigned int	lcl_apic_start_addr; /* Absolute value (not in MB) */ | ||||
| 	unsigned int	lcl_apic_size; /* Absolute value (not in MB) */ | ||||
| 	unsigned int	low_shrd_mem_base; /* 0 or 512MB or 1GB */ | ||||
| 	unsigned int	low_shrd_mem_quad_offset; /* 0,128M,256M,512M,1G */ | ||||
| 					/* may not be totally populated */ | ||||
| 	unsigned int	split_mem_enbl; /* 0 for no low shared memory */ | ||||
| 	unsigned int	mmio_sz; /* Size of total system memory mapped I/O */ | ||||
| 				 /* (in MB). */ | ||||
| 	unsigned int	quad_spin_lock; /* Spare location used for quad */ | ||||
| 					/* bringup. */ | ||||
| 	unsigned int	nonzero55; /* For checksumming. */ | ||||
| 	unsigned int	nonzeroaa; /* For checksumming. */ | ||||
| 	unsigned int	scd_magic_number; | ||||
| 	unsigned int	system_type; | ||||
| 	unsigned int	checksum; | ||||
| 	/*
 | ||||
| 	 *	memory configuration area for each quad | ||||
| 	 */ | ||||
| 	struct		eachquadmem eq[MAX_NUMNODES];	/* indexed by quad id */ | ||||
| }; | ||||
| 
 | ||||
| void numaq_tsc_disable(void); | ||||
| 
 | ||||
| #endif /* CONFIG_X86_NUMAQ */ | ||||
| #endif /* _ASM_X86_NUMAQ_H */ | ||||
| 
 | ||||
|  | @ -18,7 +18,6 @@ obj-y				+= apic_flat_64.o | |||
| endif | ||||
| 
 | ||||
| # APIC probe will depend on the listing order here
 | ||||
| obj-$(CONFIG_X86_NUMAQ)		+= numaq_32.o | ||||
| obj-$(CONFIG_X86_BIGSMP)	+= bigsmp_32.o | ||||
| 
 | ||||
| # For 32bit, probe_32 need to be listed last
 | ||||
|  |  | |||
|  | @ -1,524 +0,0 @@ | |||
| /*
 | ||||
|  * Written by: Patricia Gaughen, IBM Corporation | ||||
|  * | ||||
|  * Copyright (C) 2002, IBM Corp. | ||||
|  * Copyright (C) 2009, Red Hat, Inc., Ingo Molnar | ||||
|  * | ||||
|  * All rights reserved. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation; either version 2 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||||
|  * NON INFRINGEMENT.  See the GNU General Public License for more | ||||
|  * details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||||
|  * | ||||
|  * Send feedback to <gone@us.ibm.com> | ||||
|  */ | ||||
| #include <linux/nodemask.h> | ||||
| #include <linux/topology.h> | ||||
| #include <linux/bootmem.h> | ||||
| #include <linux/memblock.h> | ||||
| #include <linux/threads.h> | ||||
| #include <linux/cpumask.h> | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/mmzone.h> | ||||
| #include <linux/module.h> | ||||
| #include <linux/string.h> | ||||
| #include <linux/init.h> | ||||
| #include <linux/numa.h> | ||||
| #include <linux/smp.h> | ||||
| #include <linux/io.h> | ||||
| #include <linux/mm.h> | ||||
| 
 | ||||
| #include <asm/processor.h> | ||||
| #include <asm/fixmap.h> | ||||
| #include <asm/mpspec.h> | ||||
| #include <asm/numaq.h> | ||||
| #include <asm/setup.h> | ||||
| #include <asm/apic.h> | ||||
| #include <asm/e820.h> | ||||
| #include <asm/ipi.h> | ||||
| 
 | ||||
| int found_numaq; | ||||
| 
 | ||||
| /*
 | ||||
|  * Have to match translation table entries to main table entries by counter | ||||
|  * hence the mpc_record variable .... can't see a less disgusting way of | ||||
|  * doing this .... | ||||
|  */ | ||||
| struct mpc_trans { | ||||
| 	unsigned char			mpc_type; | ||||
| 	unsigned char			trans_len; | ||||
| 	unsigned char			trans_type; | ||||
| 	unsigned char			trans_quad; | ||||
| 	unsigned char			trans_global; | ||||
| 	unsigned char			trans_local; | ||||
| 	unsigned short			trans_reserved; | ||||
| }; | ||||
| 
 | ||||
| static int				mpc_record; | ||||
| 
 | ||||
| static struct mpc_trans			*translation_table[MAX_MPC_ENTRY]; | ||||
| 
 | ||||
| int					mp_bus_id_to_node[MAX_MP_BUSSES]; | ||||
| int					mp_bus_id_to_local[MAX_MP_BUSSES]; | ||||
| int					quad_local_to_mp_bus_id[NR_CPUS/4][4]; | ||||
| 
 | ||||
| 
 | ||||
| static inline void numaq_register_node(int node, struct sys_cfg_data *scd) | ||||
| { | ||||
| 	struct eachquadmem *eq = scd->eq + node; | ||||
| 	u64 start = (u64)(eq->hi_shrd_mem_start - eq->priv_mem_size) << 20; | ||||
| 	u64 end = (u64)(eq->hi_shrd_mem_start + eq->hi_shrd_mem_size) << 20; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	node_set(node, numa_nodes_parsed); | ||||
| 	ret = numa_add_memblk(node, start, end); | ||||
| 	BUG_ON(ret < 0); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Function: smp_dump_qct() | ||||
|  * | ||||
|  * Description: gets memory layout from the quad config table.  This | ||||
|  * function also updates numa_nodes_parsed with the nodes (quads) present. | ||||
|  */ | ||||
| static void __init smp_dump_qct(void) | ||||
| { | ||||
| 	struct sys_cfg_data *scd; | ||||
| 	int node; | ||||
| 
 | ||||
| 	scd = (void *)__va(SYS_CFG_DATA_PRIV_ADDR); | ||||
| 
 | ||||
| 	for_each_node(node) { | ||||
| 		if (scd->quads_present31_0 & (1 << node)) | ||||
| 			numaq_register_node(node, scd); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void numaq_tsc_disable(void) | ||||
| { | ||||
| 	if (!found_numaq) | ||||
| 		return; | ||||
| 
 | ||||
| 	if (num_online_nodes() > 1) { | ||||
| 		printk(KERN_DEBUG "NUMAQ: disabling TSC\n"); | ||||
| 		setup_clear_cpu_cap(X86_FEATURE_TSC); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void __init numaq_tsc_init(void) | ||||
| { | ||||
| 	numaq_tsc_disable(); | ||||
| } | ||||
| 
 | ||||
| static inline int generate_logical_apicid(int quad, int phys_apicid) | ||||
| { | ||||
| 	return (quad << 4) + (phys_apicid ? phys_apicid << 1 : 1); | ||||
| } | ||||
| 
 | ||||
| /* x86_quirks member */ | ||||
| static int mpc_apic_id(struct mpc_cpu *m) | ||||
| { | ||||
| 	int quad = translation_table[mpc_record]->trans_quad; | ||||
| 	int logical_apicid = generate_logical_apicid(quad, m->apicid); | ||||
| 
 | ||||
| 	printk(KERN_DEBUG | ||||
| 		"Processor #%d %u:%u APIC version %d (quad %d, apic %d)\n", | ||||
| 		 m->apicid, (m->cpufeature & CPU_FAMILY_MASK) >> 8, | ||||
| 		(m->cpufeature & CPU_MODEL_MASK) >> 4, | ||||
| 		 m->apicver, quad, logical_apicid); | ||||
| 
 | ||||
| 	return logical_apicid; | ||||
| } | ||||
| 
 | ||||
| /* x86_quirks member */ | ||||
| static void mpc_oem_bus_info(struct mpc_bus *m, char *name) | ||||
| { | ||||
| 	int quad = translation_table[mpc_record]->trans_quad; | ||||
| 	int local = translation_table[mpc_record]->trans_local; | ||||
| 
 | ||||
| 	mp_bus_id_to_node[m->busid] = quad; | ||||
| 	mp_bus_id_to_local[m->busid] = local; | ||||
| 
 | ||||
| 	printk(KERN_INFO "Bus #%d is %s (node %d)\n", m->busid, name, quad); | ||||
| } | ||||
| 
 | ||||
| /* x86_quirks member */ | ||||
| static void mpc_oem_pci_bus(struct mpc_bus *m) | ||||
| { | ||||
| 	int quad = translation_table[mpc_record]->trans_quad; | ||||
| 	int local = translation_table[mpc_record]->trans_local; | ||||
| 
 | ||||
| 	quad_local_to_mp_bus_id[quad][local] = m->busid; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Called from mpparse code. | ||||
|  * mode = 0: prescan | ||||
|  * mode = 1: one mpc entry scanned | ||||
|  */ | ||||
| static void numaq_mpc_record(unsigned int mode) | ||||
| { | ||||
| 	if (!mode) | ||||
| 		mpc_record = 0; | ||||
| 	else | ||||
| 		mpc_record++; | ||||
| } | ||||
| 
 | ||||
| static void __init MP_translation_info(struct mpc_trans *m) | ||||
| { | ||||
| 	printk(KERN_INFO | ||||
| 	    "Translation: record %d, type %d, quad %d, global %d, local %d\n", | ||||
| 	       mpc_record, m->trans_type, m->trans_quad, m->trans_global, | ||||
| 	       m->trans_local); | ||||
| 
 | ||||
| 	if (mpc_record >= MAX_MPC_ENTRY) | ||||
| 		printk(KERN_ERR "MAX_MPC_ENTRY exceeded!\n"); | ||||
| 	else | ||||
| 		translation_table[mpc_record] = m; /* stash this for later */ | ||||
| 
 | ||||
| 	if (m->trans_quad < MAX_NUMNODES && !node_online(m->trans_quad)) | ||||
| 		node_set_online(m->trans_quad); | ||||
| } | ||||
| 
 | ||||
| static int __init mpf_checksum(unsigned char *mp, int len) | ||||
| { | ||||
| 	int sum = 0; | ||||
| 
 | ||||
| 	while (len--) | ||||
| 		sum += *mp++; | ||||
| 
 | ||||
| 	return sum & 0xFF; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Read/parse the MPC oem tables | ||||
|  */ | ||||
| static void __init smp_read_mpc_oem(struct mpc_table *mpc) | ||||
| { | ||||
| 	struct mpc_oemtable *oemtable = (void *)(long)mpc->oemptr; | ||||
| 	int count = sizeof(*oemtable);	/* the header size */ | ||||
| 	unsigned char *oemptr = ((unsigned char *)oemtable) + count; | ||||
| 
 | ||||
| 	mpc_record = 0; | ||||
| 	printk(KERN_INFO | ||||
| 		"Found an OEM MPC table at %8p - parsing it...\n", oemtable); | ||||
| 
 | ||||
| 	if (memcmp(oemtable->signature, MPC_OEM_SIGNATURE, 4)) { | ||||
| 		printk(KERN_WARNING | ||||
| 		       "SMP mpc oemtable: bad signature [%c%c%c%c]!\n", | ||||
| 		       oemtable->signature[0], oemtable->signature[1], | ||||
| 		       oemtable->signature[2], oemtable->signature[3]); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	if (mpf_checksum((unsigned char *)oemtable, oemtable->length)) { | ||||
| 		printk(KERN_WARNING "SMP oem mptable: checksum error!\n"); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	while (count < oemtable->length) { | ||||
| 		switch (*oemptr) { | ||||
| 		case MP_TRANSLATION: | ||||
| 			{ | ||||
| 				struct mpc_trans *m = (void *)oemptr; | ||||
| 
 | ||||
| 				MP_translation_info(m); | ||||
| 				oemptr += sizeof(*m); | ||||
| 				count += sizeof(*m); | ||||
| 				++mpc_record; | ||||
| 				break; | ||||
| 			} | ||||
| 		default: | ||||
| 			printk(KERN_WARNING | ||||
| 			       "Unrecognised OEM table entry type! - %d\n", | ||||
| 			       (int)*oemptr); | ||||
| 			return; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static __init void early_check_numaq(void) | ||||
| { | ||||
| 	/*
 | ||||
| 	 * get boot-time SMP configuration: | ||||
| 	 */ | ||||
| 	if (smp_found_config) | ||||
| 		early_get_smp_config(); | ||||
| 
 | ||||
| 	if (found_numaq) { | ||||
| 		x86_init.mpparse.mpc_record = numaq_mpc_record; | ||||
| 		x86_init.mpparse.setup_ioapic_ids = x86_init_noop; | ||||
| 		x86_init.mpparse.mpc_apic_id = mpc_apic_id; | ||||
| 		x86_init.mpparse.smp_read_mpc_oem = smp_read_mpc_oem; | ||||
| 		x86_init.mpparse.mpc_oem_pci_bus = mpc_oem_pci_bus; | ||||
| 		x86_init.mpparse.mpc_oem_bus_info = mpc_oem_bus_info; | ||||
| 		x86_init.timers.tsc_pre_init = numaq_tsc_init; | ||||
| 		x86_init.pci.init = pci_numaq_init; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| int __init numaq_numa_init(void) | ||||
| { | ||||
| 	early_check_numaq(); | ||||
| 	if (!found_numaq) | ||||
| 		return -ENOENT; | ||||
| 	smp_dump_qct(); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| #define NUMAQ_APIC_DFR_VALUE	(APIC_DFR_CLUSTER) | ||||
| 
 | ||||
| static inline unsigned int numaq_get_apic_id(unsigned long x) | ||||
| { | ||||
| 	return (x >> 24) & 0x0F; | ||||
| } | ||||
| 
 | ||||
| static inline void numaq_send_IPI_mask(const struct cpumask *mask, int vector) | ||||
| { | ||||
| 	default_send_IPI_mask_sequence_logical(mask, vector); | ||||
| } | ||||
| 
 | ||||
| static inline void numaq_send_IPI_allbutself(int vector) | ||||
| { | ||||
| 	default_send_IPI_mask_allbutself_logical(cpu_online_mask, vector); | ||||
| } | ||||
| 
 | ||||
| static inline void numaq_send_IPI_all(int vector) | ||||
| { | ||||
| 	numaq_send_IPI_mask(cpu_online_mask, vector); | ||||
| } | ||||
| 
 | ||||
| #define NUMAQ_TRAMPOLINE_PHYS_LOW	(0x8) | ||||
| #define NUMAQ_TRAMPOLINE_PHYS_HIGH	(0xa) | ||||
| 
 | ||||
| /*
 | ||||
|  * Because we use NMIs rather than the INIT-STARTUP sequence to | ||||
|  * bootstrap the CPUs, the APIC may be in a weird state. Kick it: | ||||
|  */ | ||||
| static inline void numaq_smp_callin_clear_local_apic(void) | ||||
| { | ||||
| 	clear_local_APIC(); | ||||
| } | ||||
| 
 | ||||
| static inline const struct cpumask *numaq_target_cpus(void) | ||||
| { | ||||
| 	return cpu_all_mask; | ||||
| } | ||||
| 
 | ||||
| static unsigned long numaq_check_apicid_used(physid_mask_t *map, int apicid) | ||||
| { | ||||
| 	return physid_isset(apicid, *map); | ||||
| } | ||||
| 
 | ||||
| static inline unsigned long numaq_check_apicid_present(int bit) | ||||
| { | ||||
| 	return physid_isset(bit, phys_cpu_present_map); | ||||
| } | ||||
| 
 | ||||
| static inline int numaq_apic_id_registered(void) | ||||
| { | ||||
| 	return 1; | ||||
| } | ||||
| 
 | ||||
| static inline void numaq_init_apic_ldr(void) | ||||
| { | ||||
| 	/* Already done in NUMA-Q firmware */ | ||||
| } | ||||
| 
 | ||||
| static inline void numaq_setup_apic_routing(void) | ||||
| { | ||||
| 	printk(KERN_INFO | ||||
| 		"Enabling APIC mode:  NUMA-Q.  Using %d I/O APICs\n", | ||||
| 		nr_ioapics); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Skip adding the timer int on secondary nodes, which causes | ||||
|  * a small but painful rift in the time-space continuum. | ||||
|  */ | ||||
| static inline int numaq_multi_timer_check(int apic, int irq) | ||||
| { | ||||
| 	return apic != 0 && irq == 0; | ||||
| } | ||||
| 
 | ||||
| static inline void numaq_ioapic_phys_id_map(physid_mask_t *phys_map, physid_mask_t *retmap) | ||||
| { | ||||
| 	/* We don't have a good way to do this yet - hack */ | ||||
| 	return physids_promote(0xFUL, retmap); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Supporting over 60 cpus on NUMA-Q requires a locality-dependent | ||||
|  * cpu to APIC ID relation to properly interact with the intelligent | ||||
|  * mode of the cluster controller. | ||||
|  */ | ||||
| static inline int numaq_cpu_present_to_apicid(int mps_cpu) | ||||
| { | ||||
| 	if (mps_cpu < 60) | ||||
| 		return ((mps_cpu >> 2) << 4) | (1 << (mps_cpu & 0x3)); | ||||
| 	else | ||||
| 		return BAD_APICID; | ||||
| } | ||||
| 
 | ||||
| static inline int numaq_apicid_to_node(int logical_apicid) | ||||
| { | ||||
| 	return logical_apicid >> 4; | ||||
| } | ||||
| 
 | ||||
| static int numaq_numa_cpu_node(int cpu) | ||||
| { | ||||
| 	int logical_apicid = early_per_cpu(x86_cpu_to_logical_apicid, cpu); | ||||
| 
 | ||||
| 	if (logical_apicid != BAD_APICID) | ||||
| 		return numaq_apicid_to_node(logical_apicid); | ||||
| 	return NUMA_NO_NODE; | ||||
| } | ||||
| 
 | ||||
| static void numaq_apicid_to_cpu_present(int logical_apicid, physid_mask_t *retmap) | ||||
| { | ||||
| 	int node = numaq_apicid_to_node(logical_apicid); | ||||
| 	int cpu = __ffs(logical_apicid & 0xf); | ||||
| 
 | ||||
| 	physid_set_mask_of_physid(cpu + 4*node, retmap); | ||||
| } | ||||
| 
 | ||||
| /* Where the IO area was mapped on multiquad, always 0 otherwise */ | ||||
| void *xquad_portio; | ||||
| 
 | ||||
| static inline int numaq_check_phys_apicid_present(int phys_apicid) | ||||
| { | ||||
| 	return 1; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * We use physical apicids here, not logical, so just return the default | ||||
|  * physical broadcast to stop people from breaking us | ||||
|  */ | ||||
| static int | ||||
| numaq_cpu_mask_to_apicid_and(const struct cpumask *cpumask, | ||||
| 			     const struct cpumask *andmask, | ||||
| 			     unsigned int *apicid) | ||||
| { | ||||
| 	*apicid = 0x0F; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /* No NUMA-Q box has a HT CPU, but it can't hurt to use the default code. */ | ||||
| static inline int numaq_phys_pkg_id(int cpuid_apic, int index_msb) | ||||
| { | ||||
| 	return cpuid_apic >> index_msb; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| numaq_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) | ||||
| { | ||||
| 	if (strncmp(oem, "IBM NUMA", 8)) | ||||
| 		printk(KERN_ERR "Warning! Not a NUMA-Q system!\n"); | ||||
| 	else | ||||
| 		found_numaq = 1; | ||||
| 
 | ||||
| 	return found_numaq; | ||||
| } | ||||
| 
 | ||||
| static int probe_numaq(void) | ||||
| { | ||||
| 	/* already know from get_memcfg_numaq() */ | ||||
| 	return found_numaq; | ||||
| } | ||||
| 
 | ||||
| static void numaq_setup_portio_remap(void) | ||||
| { | ||||
| 	int num_quads = num_online_nodes(); | ||||
| 
 | ||||
| 	if (num_quads <= 1) | ||||
| 		return; | ||||
| 
 | ||||
| 	printk(KERN_INFO | ||||
| 		"Remapping cross-quad port I/O for %d quads\n", num_quads); | ||||
| 
 | ||||
| 	xquad_portio = ioremap(XQUAD_PORTIO_BASE, num_quads*XQUAD_PORTIO_QUAD); | ||||
| 
 | ||||
| 	printk(KERN_INFO | ||||
| 		"xquad_portio vaddr 0x%08lx, len %08lx\n", | ||||
| 		(u_long) xquad_portio, (u_long) num_quads*XQUAD_PORTIO_QUAD); | ||||
| } | ||||
| 
 | ||||
| /* Use __refdata to keep false positive warning calm.  */ | ||||
| static struct apic __refdata apic_numaq = { | ||||
| 
 | ||||
| 	.name				= "NUMAQ", | ||||
| 	.probe				= probe_numaq, | ||||
| 	.acpi_madt_oem_check		= NULL, | ||||
| 	.apic_id_valid			= default_apic_id_valid, | ||||
| 	.apic_id_registered		= numaq_apic_id_registered, | ||||
| 
 | ||||
| 	.irq_delivery_mode		= dest_LowestPrio, | ||||
| 	/* physical delivery on LOCAL quad: */ | ||||
| 	.irq_dest_mode			= 0, | ||||
| 
 | ||||
| 	.target_cpus			= numaq_target_cpus, | ||||
| 	.disable_esr			= 1, | ||||
| 	.dest_logical			= APIC_DEST_LOGICAL, | ||||
| 	.check_apicid_used		= numaq_check_apicid_used, | ||||
| 	.check_apicid_present		= numaq_check_apicid_present, | ||||
| 
 | ||||
| 	.vector_allocation_domain	= flat_vector_allocation_domain, | ||||
| 	.init_apic_ldr			= numaq_init_apic_ldr, | ||||
| 
 | ||||
| 	.ioapic_phys_id_map		= numaq_ioapic_phys_id_map, | ||||
| 	.setup_apic_routing		= numaq_setup_apic_routing, | ||||
| 	.multi_timer_check		= numaq_multi_timer_check, | ||||
| 	.cpu_present_to_apicid		= numaq_cpu_present_to_apicid, | ||||
| 	.apicid_to_cpu_present		= numaq_apicid_to_cpu_present, | ||||
| 	.setup_portio_remap		= numaq_setup_portio_remap, | ||||
| 	.check_phys_apicid_present	= numaq_check_phys_apicid_present, | ||||
| 	.enable_apic_mode		= NULL, | ||||
| 	.phys_pkg_id			= numaq_phys_pkg_id, | ||||
| 	.mps_oem_check			= numaq_mps_oem_check, | ||||
| 
 | ||||
| 	.get_apic_id			= numaq_get_apic_id, | ||||
| 	.set_apic_id			= NULL, | ||||
| 	.apic_id_mask			= 0x0F << 24, | ||||
| 
 | ||||
| 	.cpu_mask_to_apicid_and		= numaq_cpu_mask_to_apicid_and, | ||||
| 
 | ||||
| 	.send_IPI_mask			= numaq_send_IPI_mask, | ||||
| 	.send_IPI_mask_allbutself	= NULL, | ||||
| 	.send_IPI_allbutself		= numaq_send_IPI_allbutself, | ||||
| 	.send_IPI_all			= numaq_send_IPI_all, | ||||
| 	.send_IPI_self			= default_send_IPI_self, | ||||
| 
 | ||||
| 	.wakeup_secondary_cpu		= wakeup_secondary_cpu_via_nmi, | ||||
| 	.trampoline_phys_low		= NUMAQ_TRAMPOLINE_PHYS_LOW, | ||||
| 	.trampoline_phys_high		= NUMAQ_TRAMPOLINE_PHYS_HIGH, | ||||
| 
 | ||||
| 	/* We don't do anything here because we use NMI's to boot instead */ | ||||
| 	.wait_for_init_deassert		= false, | ||||
| 	.smp_callin_clear_local_apic	= numaq_smp_callin_clear_local_apic, | ||||
| 	.inquire_remote_apic		= NULL, | ||||
| 
 | ||||
| 	.read				= native_apic_mem_read, | ||||
| 	.write				= native_apic_mem_write, | ||||
| 	.eoi_write			= native_apic_mem_write, | ||||
| 	.icr_read			= native_apic_icr_read, | ||||
| 	.icr_write			= native_apic_icr_write, | ||||
| 	.wait_icr_idle			= native_apic_wait_icr_idle, | ||||
| 	.safe_wait_icr_idle		= native_safe_apic_wait_icr_idle, | ||||
| 
 | ||||
| 	.x86_32_early_logical_apicid	= noop_x86_32_early_logical_apicid, | ||||
| 	.x86_32_numa_cpu_node		= numaq_numa_cpu_node, | ||||
| }; | ||||
| 
 | ||||
| apic_driver(apic_numaq); | ||||
|  | @ -267,10 +267,6 @@ static void intel_workarounds(struct cpuinfo_x86 *c) | |||
| 	} | ||||
| #endif | ||||
| 
 | ||||
| #ifdef CONFIG_X86_NUMAQ | ||||
| 	numaq_tsc_disable(); | ||||
| #endif | ||||
| 
 | ||||
| 	intel_smp_check(c); | ||||
| } | ||||
| #else | ||||
|  |  | |||
|  | @ -687,10 +687,6 @@ static int __init dummy_numa_init(void) | |||
| void __init x86_numa_init(void) | ||||
| { | ||||
| 	if (!numa_off) { | ||||
| #ifdef CONFIG_X86_NUMAQ | ||||
| 		if (!numa_init(numaq_numa_init)) | ||||
| 			return; | ||||
| #endif | ||||
| #ifdef CONFIG_ACPI_NUMA | ||||
| 		if (!numa_init(x86_acpi_numa_init)) | ||||
| 			return; | ||||
|  |  | |||
|  | @ -13,7 +13,6 @@ obj-y				+= legacy.o irq.o | |||
| 
 | ||||
| obj-$(CONFIG_STA2X11)           += sta2x11-fixup.o | ||||
| 
 | ||||
| obj-$(CONFIG_X86_NUMAQ)		+= numaq_32.o | ||||
| obj-$(CONFIG_X86_NUMACHIP)	+= numachip.o | ||||
| 
 | ||||
| obj-$(CONFIG_X86_INTEL_MID)	+= intel_mid_pci.o | ||||
|  |  | |||
|  | @ -1,165 +0,0 @@ | |||
| /*
 | ||||
|  * numaq_32.c - Low-level PCI access for NUMA-Q machines | ||||
|  */ | ||||
| 
 | ||||
| #include <linux/pci.h> | ||||
| #include <linux/init.h> | ||||
| #include <linux/nodemask.h> | ||||
| #include <asm/apic.h> | ||||
| #include <asm/mpspec.h> | ||||
| #include <asm/pci_x86.h> | ||||
| #include <asm/numaq.h> | ||||
| 
 | ||||
| #define BUS2QUAD(global) (mp_bus_id_to_node[global]) | ||||
| 
 | ||||
| #define BUS2LOCAL(global) (mp_bus_id_to_local[global]) | ||||
| 
 | ||||
| #define QUADLOCAL2BUS(quad,local) (quad_local_to_mp_bus_id[quad][local]) | ||||
| 
 | ||||
| #define PCI_CONF1_MQ_ADDRESS(bus, devfn, reg) \ | ||||
| 	(0x80000000 | (BUS2LOCAL(bus) << 16) | (devfn << 8) | (reg & ~3)) | ||||
| 
 | ||||
| static void write_cf8(unsigned bus, unsigned devfn, unsigned reg) | ||||
| { | ||||
| 	unsigned val = PCI_CONF1_MQ_ADDRESS(bus, devfn, reg); | ||||
| 	if (xquad_portio) | ||||
| 		writel(val, XQUAD_PORT_ADDR(0xcf8, BUS2QUAD(bus))); | ||||
| 	else | ||||
| 		outl(val, 0xCF8); | ||||
| } | ||||
| 
 | ||||
| static int pci_conf1_mq_read(unsigned int seg, unsigned int bus, | ||||
| 			     unsigned int devfn, int reg, int len, u32 *value) | ||||
| { | ||||
| 	unsigned long flags; | ||||
| 	void *adr __iomem = XQUAD_PORT_ADDR(0xcfc, BUS2QUAD(bus)); | ||||
| 
 | ||||
| 	WARN_ON(seg); | ||||
| 	if (!value || (bus >= MAX_MP_BUSSES) || (devfn > 255) || (reg > 255)) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	raw_spin_lock_irqsave(&pci_config_lock, flags); | ||||
| 
 | ||||
| 	write_cf8(bus, devfn, reg); | ||||
| 
 | ||||
| 	switch (len) { | ||||
| 	case 1: | ||||
| 		if (xquad_portio) | ||||
| 			*value = readb(adr + (reg & 3)); | ||||
| 		else | ||||
| 			*value = inb(0xCFC + (reg & 3)); | ||||
| 		break; | ||||
| 	case 2: | ||||
| 		if (xquad_portio) | ||||
| 			*value = readw(adr + (reg & 2)); | ||||
| 		else | ||||
| 			*value = inw(0xCFC + (reg & 2)); | ||||
| 		break; | ||||
| 	case 4: | ||||
| 		if (xquad_portio) | ||||
| 			*value = readl(adr); | ||||
| 		else | ||||
| 			*value = inl(0xCFC); | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	raw_spin_unlock_irqrestore(&pci_config_lock, flags); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int pci_conf1_mq_write(unsigned int seg, unsigned int bus, | ||||
| 			      unsigned int devfn, int reg, int len, u32 value) | ||||
| { | ||||
| 	unsigned long flags; | ||||
| 	void *adr __iomem = XQUAD_PORT_ADDR(0xcfc, BUS2QUAD(bus)); | ||||
| 
 | ||||
| 	WARN_ON(seg); | ||||
| 	if ((bus >= MAX_MP_BUSSES) || (devfn > 255) || (reg > 255))  | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	raw_spin_lock_irqsave(&pci_config_lock, flags); | ||||
| 
 | ||||
| 	write_cf8(bus, devfn, reg); | ||||
| 
 | ||||
| 	switch (len) { | ||||
| 	case 1: | ||||
| 		if (xquad_portio) | ||||
| 			writeb(value, adr + (reg & 3)); | ||||
| 		else | ||||
| 			outb((u8)value, 0xCFC + (reg & 3)); | ||||
| 		break; | ||||
| 	case 2: | ||||
| 		if (xquad_portio) | ||||
| 			writew(value, adr + (reg & 2)); | ||||
| 		else | ||||
| 			outw((u16)value, 0xCFC + (reg & 2)); | ||||
| 		break; | ||||
| 	case 4: | ||||
| 		if (xquad_portio) | ||||
| 			writel(value, adr + reg); | ||||
| 		else | ||||
| 			outl((u32)value, 0xCFC); | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	raw_spin_unlock_irqrestore(&pci_config_lock, flags); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| #undef PCI_CONF1_MQ_ADDRESS | ||||
| 
 | ||||
| static const struct pci_raw_ops pci_direct_conf1_mq = { | ||||
| 	.read	= pci_conf1_mq_read, | ||||
| 	.write	= pci_conf1_mq_write | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| static void pci_fixup_i450nx(struct pci_dev *d) | ||||
| { | ||||
| 	/*
 | ||||
| 	 * i450NX -- Find and scan all secondary buses on all PXB's. | ||||
| 	 */ | ||||
| 	int pxb, reg; | ||||
| 	u8 busno, suba, subb; | ||||
| 	int quad = BUS2QUAD(d->bus->number); | ||||
| 
 | ||||
| 	dev_info(&d->dev, "searching for i450NX host bridges\n"); | ||||
| 	reg = 0xd0; | ||||
| 	for(pxb=0; pxb<2; pxb++) { | ||||
| 		pci_read_config_byte(d, reg++, &busno); | ||||
| 		pci_read_config_byte(d, reg++, &suba); | ||||
| 		pci_read_config_byte(d, reg++, &subb); | ||||
| 		dev_dbg(&d->dev, "i450NX PXB %d: %02x/%02x/%02x\n", | ||||
| 			pxb, busno, suba, subb); | ||||
| 		if (busno) { | ||||
| 			/* Bus A */ | ||||
| 			pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, busno)); | ||||
| 		} | ||||
| 		if (suba < subb) { | ||||
| 			/* Bus B */ | ||||
| 			pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, suba+1)); | ||||
| 		} | ||||
| 	} | ||||
| 	pcibios_last_bus = -1; | ||||
| } | ||||
| DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx); | ||||
| 
 | ||||
| int __init pci_numaq_init(void) | ||||
| { | ||||
| 	int quad; | ||||
| 
 | ||||
| 	raw_pci_ops = &pci_direct_conf1_mq; | ||||
| 
 | ||||
| 	pcibios_scan_root(0); | ||||
| 	if (num_online_nodes() > 1) | ||||
| 		for_each_online_node(quad) { | ||||
| 			if (quad == 0) | ||||
| 				continue; | ||||
| 			printk("Scanning PCI bus %d for quad %d\n",  | ||||
| 				QUADLOCAL2BUS(quad,0), quad); | ||||
| 			pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, 0)); | ||||
| 		} | ||||
| 	return 0; | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 H. Peter Anvin
				H. Peter Anvin