diff options
Diffstat (limited to 'arch/sparc/kernel')
| -rw-r--r-- | arch/sparc/kernel/entry.h | 2 | ||||
| -rw-r--r-- | arch/sparc/kernel/leon_pci_grpci2.c | 1 | ||||
| -rw-r--r-- | arch/sparc/kernel/mdesc.c | 136 | ||||
| -rw-r--r-- | arch/sparc/kernel/pci.c | 59 | ||||
| -rw-r--r-- | arch/sparc/kernel/setup_64.c | 21 | ||||
| -rw-r--r-- | arch/sparc/kernel/smp_64.c | 13 | ||||
| -rw-r--r-- | arch/sparc/kernel/vmlinux.lds.S | 5 | 
7 files changed, 202 insertions, 35 deletions
| diff --git a/arch/sparc/kernel/entry.h b/arch/sparc/kernel/entry.h index 07cc49e541f4..0f679421b468 100644 --- a/arch/sparc/kernel/entry.h +++ b/arch/sparc/kernel/entry.h @@ -69,6 +69,8 @@ void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *,  			     struct sun4v_1insn_patch_entry *);  void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *,  			     struct sun4v_2insn_patch_entry *); +void sun_m7_patch_2insn_range(struct sun4v_2insn_patch_entry *, +			     struct sun4v_2insn_patch_entry *);  extern unsigned int dcache_parity_tl1_occurred;  extern unsigned int icache_parity_tl1_occurred; diff --git a/arch/sparc/kernel/leon_pci_grpci2.c b/arch/sparc/kernel/leon_pci_grpci2.c index 94e392bdee7d..814fb1729b12 100644 --- a/arch/sparc/kernel/leon_pci_grpci2.c +++ b/arch/sparc/kernel/leon_pci_grpci2.c @@ -723,7 +723,6 @@ static int grpci2_of_probe(struct platform_device *ofdev)  		err = -ENOMEM;  		goto err1;  	} -	memset(grpci2priv, 0, sizeof(*grpci2priv));  	priv->regs = regs;  	priv->irq = ofdev->archdata.irqs[0]; /* BASE IRQ */  	priv->irq_mode = (capability & STS_IRQMODE) >> STS_IRQMODE_BIT; diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c index 26c80e18d7b1..6f80936e0eea 100644 --- a/arch/sparc/kernel/mdesc.c +++ b/arch/sparc/kernel/mdesc.c @@ -614,45 +614,68 @@ static void fill_in_one_cache(cpuinfo_sparc *c, struct mdesc_handle *hp, u64 mp)  	}  } -static void mark_core_ids(struct mdesc_handle *hp, u64 mp, int core_id) +static void find_back_node_value(struct mdesc_handle *hp, u64 node, +				 char *srch_val, +				 void (*func)(struct mdesc_handle *, u64, int), +				 u64 val, int depth)  { -	u64 a; - -	mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_BACK) { -		u64 t = mdesc_arc_target(hp, a); -		const char *name; -		const u64 *id; +	u64 arc; -		name = mdesc_node_name(hp, t); -		if (!strcmp(name, "cpu")) { -			id = mdesc_get_property(hp, t, "id", NULL); -			if (*id < NR_CPUS) -				cpu_data(*id).core_id = core_id; -		} else { -			u64 j; +	/* Since we have an estimate of recursion depth, do a sanity check. */ +	if (depth == 0) +		return; -			mdesc_for_each_arc(j, hp, t, MDESC_ARC_TYPE_BACK) { -				u64 n = mdesc_arc_target(hp, j); -				const char *n_name; +	mdesc_for_each_arc(arc, hp, node, MDESC_ARC_TYPE_BACK) { +		u64 n = mdesc_arc_target(hp, arc); +		const char *name = mdesc_node_name(hp, n); -				n_name = mdesc_node_name(hp, n); -				if (strcmp(n_name, "cpu")) -					continue; +		if (!strcmp(srch_val, name)) +			(*func)(hp, n, val); -				id = mdesc_get_property(hp, n, "id", NULL); -				if (*id < NR_CPUS) -					cpu_data(*id).core_id = core_id; -			} -		} +		find_back_node_value(hp, n, srch_val, func, val, depth-1);  	}  } +static void __mark_core_id(struct mdesc_handle *hp, u64 node, +			   int core_id) +{ +	const u64 *id = mdesc_get_property(hp, node, "id", NULL); + +	if (*id < num_possible_cpus()) +		cpu_data(*id).core_id = core_id; +} + +static void __mark_sock_id(struct mdesc_handle *hp, u64 node, +			   int sock_id) +{ +	const u64 *id = mdesc_get_property(hp, node, "id", NULL); + +	if (*id < num_possible_cpus()) +		cpu_data(*id).sock_id = sock_id; +} + +static void mark_core_ids(struct mdesc_handle *hp, u64 mp, +			  int core_id) +{ +	find_back_node_value(hp, mp, "cpu", __mark_core_id, core_id, 10); +} + +static void mark_sock_ids(struct mdesc_handle *hp, u64 mp, +			  int sock_id) +{ +	find_back_node_value(hp, mp, "cpu", __mark_sock_id, sock_id, 10); +} +  static void set_core_ids(struct mdesc_handle *hp)  {  	int idx;  	u64 mp;  	idx = 1; + +	/* Identify unique cores by looking for cpus backpointed to by +	 * level 1 instruction caches. +	 */  	mdesc_for_each_node_by_name(hp, mp, "cache") {  		const u64 *level;  		const char *type; @@ -667,11 +690,72 @@ static void set_core_ids(struct mdesc_handle *hp)  			continue;  		mark_core_ids(hp, mp, idx); +		idx++; +	} +} + +static int set_sock_ids_by_cache(struct mdesc_handle *hp, int level) +{ +	u64 mp; +	int idx = 1; +	int fnd = 0; + +	/* Identify unique sockets by looking for cpus backpointed to by +	 * shared level n caches. +	 */ +	mdesc_for_each_node_by_name(hp, mp, "cache") { +		const u64 *cur_lvl; + +		cur_lvl = mdesc_get_property(hp, mp, "level", NULL); +		if (*cur_lvl != level) +			continue; + +		mark_sock_ids(hp, mp, idx); +		idx++; +		fnd = 1; +	} +	return fnd; +} + +static void set_sock_ids_by_socket(struct mdesc_handle *hp, u64 mp) +{ +	int idx = 1; +	mdesc_for_each_node_by_name(hp, mp, "socket") { +		u64 a; + +		mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) { +			u64 t = mdesc_arc_target(hp, a); +			const char *name; +			const u64 *id; + +			name = mdesc_node_name(hp, t); +			if (strcmp(name, "cpu")) +				continue; + +			id = mdesc_get_property(hp, t, "id", NULL); +			if (*id < num_possible_cpus()) +				cpu_data(*id).sock_id = idx; +		}  		idx++;  	}  } +static void set_sock_ids(struct mdesc_handle *hp) +{ +	u64 mp; + +	/* If machine description exposes sockets data use it. +	 * Otherwise fallback to use shared L3 or L2 caches. +	 */ +	mp = mdesc_node_by_name(hp, MDESC_NODE_NULL, "sockets"); +	if (mp != MDESC_NODE_NULL) +		return set_sock_ids_by_socket(hp, mp); + +	if (!set_sock_ids_by_cache(hp, 3)) +		set_sock_ids_by_cache(hp, 2); +} +  static void mark_proc_ids(struct mdesc_handle *hp, u64 mp, int proc_id)  {  	u64 a; @@ -707,7 +791,6 @@ static void __set_proc_ids(struct mdesc_handle *hp, const char *exec_unit_name)  			continue;  		mark_proc_ids(hp, mp, idx); -  		idx++;  	}  } @@ -900,6 +983,7 @@ void mdesc_fill_in_cpu_data(cpumask_t *mask)  	set_core_ids(hp);  	set_proc_ids(hp); +	set_sock_ids(hp);  	mdesc_release(hp); diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c index 6f7251fd2eab..c928bc64b4ba 100644 --- a/arch/sparc/kernel/pci.c +++ b/arch/sparc/kernel/pci.c @@ -1002,6 +1002,38 @@ static int __init pcibios_init(void)  subsys_initcall(pcibios_init);  #ifdef CONFIG_SYSFS + +#define SLOT_NAME_SIZE  11  /* Max decimal digits + null in u32 */ + +static void pcie_bus_slot_names(struct pci_bus *pbus) +{ +	struct pci_dev *pdev; +	struct pci_bus *bus; + +	list_for_each_entry(pdev, &pbus->devices, bus_list) { +		char name[SLOT_NAME_SIZE]; +		struct pci_slot *pci_slot; +		const u32 *slot_num; +		int len; + +		slot_num = of_get_property(pdev->dev.of_node, +					   "physical-slot#", &len); + +		if (slot_num == NULL || len != 4) +			continue; + +		snprintf(name, sizeof(name), "%u", slot_num[0]); +		pci_slot = pci_create_slot(pbus, slot_num[0], name, NULL); + +		if (IS_ERR(pci_slot)) +			pr_err("PCI: pci_create_slot returned %ld.\n", +			       PTR_ERR(pci_slot)); +	} + +	list_for_each_entry(bus, &pbus->children, node) +		pcie_bus_slot_names(bus); +} +  static void pci_bus_slot_names(struct device_node *node, struct pci_bus *bus)  {  	const struct pci_slot_names { @@ -1053,18 +1085,29 @@ static int __init of_pci_slot_init(void)  	while ((pbus = pci_find_next_bus(pbus)) != NULL) {  		struct device_node *node; +		struct pci_dev *pdev; + +		pdev = list_first_entry(&pbus->devices, struct pci_dev, +					bus_list); -		if (pbus->self) { -			/* PCI->PCI bridge */ -			node = pbus->self->dev.of_node; +		if (pdev && pci_is_pcie(pdev)) { +			pcie_bus_slot_names(pbus);  		} else { -			struct pci_pbm_info *pbm = pbus->sysdata; -			/* Host PCI controller */ -			node = pbm->op->dev.of_node; -		} +			if (pbus->self) { + +				/* PCI->PCI bridge */ +				node = pbus->self->dev.of_node; + +			} else { +				struct pci_pbm_info *pbm = pbus->sysdata; -		pci_bus_slot_names(node, pbus); +				/* Host PCI controller */ +				node = pbm->op->dev.of_node; +			} + +			pci_bus_slot_names(node, pbus); +		}  	}  	return 0; diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c index c38d19fc27ba..f7b261749383 100644 --- a/arch/sparc/kernel/setup_64.c +++ b/arch/sparc/kernel/setup_64.c @@ -255,6 +255,24 @@ void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *start,  	}  } +void sun_m7_patch_2insn_range(struct sun4v_2insn_patch_entry *start, +			     struct sun4v_2insn_patch_entry *end) +{ +	while (start < end) { +		unsigned long addr = start->addr; + +		*(unsigned int *) (addr +  0) = start->insns[0]; +		wmb(); +		__asm__ __volatile__("flush	%0" : : "r" (addr +  0)); + +		*(unsigned int *) (addr +  4) = start->insns[1]; +		wmb(); +		__asm__ __volatile__("flush	%0" : : "r" (addr +  4)); + +		start++; +	} +} +  static void __init sun4v_patch(void)  {  	extern void sun4v_hvapi_init(void); @@ -267,6 +285,9 @@ static void __init sun4v_patch(void)  	sun4v_patch_2insn_range(&__sun4v_2insn_patch,  				&__sun4v_2insn_patch_end); +	if (sun4v_chip_type == SUN4V_CHIP_SPARC_M7) +		sun_m7_patch_2insn_range(&__sun_m7_2insn_patch, +					 &__sun_m7_2insn_patch_end);  	sun4v_hvapi_init();  } diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c index 61139d9924ca..19cd08d18672 100644 --- a/arch/sparc/kernel/smp_64.c +++ b/arch/sparc/kernel/smp_64.c @@ -60,8 +60,12 @@ DEFINE_PER_CPU(cpumask_t, cpu_sibling_map) = CPU_MASK_NONE;  cpumask_t cpu_core_map[NR_CPUS] __read_mostly =  	{ [0 ... NR_CPUS-1] = CPU_MASK_NONE }; +cpumask_t cpu_core_sib_map[NR_CPUS] __read_mostly = { +	[0 ... NR_CPUS-1] = CPU_MASK_NONE }; +  EXPORT_PER_CPU_SYMBOL(cpu_sibling_map);  EXPORT_SYMBOL(cpu_core_map); +EXPORT_SYMBOL(cpu_core_sib_map);  static cpumask_t smp_commenced_mask; @@ -1243,6 +1247,15 @@ void smp_fill_in_sib_core_maps(void)  		}  	} +	for_each_present_cpu(i)  { +		unsigned int j; + +		for_each_present_cpu(j)  { +			if (cpu_data(i).sock_id == cpu_data(j).sock_id) +				cpumask_set_cpu(j, &cpu_core_sib_map[i]); +		} +	} +  	for_each_present_cpu(i) {  		unsigned int j; diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S index 09243057cb0b..f1a2f688b28a 100644 --- a/arch/sparc/kernel/vmlinux.lds.S +++ b/arch/sparc/kernel/vmlinux.lds.S @@ -138,6 +138,11 @@ SECTIONS  		*(.pause_3insn_patch)  		__pause_3insn_patch_end = .;  	} +	.sun_m7_2insn_patch : { +		__sun_m7_2insn_patch = .; +		*(.sun_m7_2insn_patch) +		__sun_m7_2insn_patch_end = .; +	}  	PERCPU_SECTION(SMP_CACHE_BYTES)  	. = ALIGN(PAGE_SIZE); |