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 *, | |||
69 | struct sun4v_1insn_patch_entry *); | 69 | struct sun4v_1insn_patch_entry *); |
70 | void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *, | 70 | void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *, |
71 | struct sun4v_2insn_patch_entry *); | 71 | struct sun4v_2insn_patch_entry *); |
72 | void sun_m7_patch_2insn_range(struct sun4v_2insn_patch_entry *, | ||
73 | struct sun4v_2insn_patch_entry *); | ||
72 | extern unsigned int dcache_parity_tl1_occurred; | 74 | extern unsigned int dcache_parity_tl1_occurred; |
73 | extern unsigned int icache_parity_tl1_occurred; | 75 | extern unsigned int icache_parity_tl1_occurred; |
74 | 76 | ||
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) | |||
723 | err = -ENOMEM; | 723 | err = -ENOMEM; |
724 | goto err1; | 724 | goto err1; |
725 | } | 725 | } |
726 | memset(grpci2priv, 0, sizeof(*grpci2priv)); | ||
727 | priv->regs = regs; | 726 | priv->regs = regs; |
728 | priv->irq = ofdev->archdata.irqs[0]; /* BASE IRQ */ | 727 | priv->irq = ofdev->archdata.irqs[0]; /* BASE IRQ */ |
729 | priv->irq_mode = (capability & STS_IRQMODE) >> STS_IRQMODE_BIT; | 728 | 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) | |||
614 | } | 614 | } |
615 | } | 615 | } |
616 | 616 | ||
617 | static void mark_core_ids(struct mdesc_handle *hp, u64 mp, int core_id) | 617 | static void find_back_node_value(struct mdesc_handle *hp, u64 node, |
618 | char *srch_val, | ||
619 | void (*func)(struct mdesc_handle *, u64, int), | ||
620 | u64 val, int depth) | ||
618 | { | 621 | { |
619 | u64 a; | 622 | u64 arc; |
620 | |||
621 | mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_BACK) { | ||
622 | u64 t = mdesc_arc_target(hp, a); | ||
623 | const char *name; | ||
624 | const u64 *id; | ||
625 | 623 | ||
626 | name = mdesc_node_name(hp, t); | 624 | /* Since we have an estimate of recursion depth, do a sanity check. */ |
627 | if (!strcmp(name, "cpu")) { | 625 | if (depth == 0) |
628 | id = mdesc_get_property(hp, t, "id", NULL); | 626 | return; |
629 | if (*id < NR_CPUS) | ||
630 | cpu_data(*id).core_id = core_id; | ||
631 | } else { | ||
632 | u64 j; | ||
633 | 627 | ||
634 | mdesc_for_each_arc(j, hp, t, MDESC_ARC_TYPE_BACK) { | 628 | mdesc_for_each_arc(arc, hp, node, MDESC_ARC_TYPE_BACK) { |
635 | u64 n = mdesc_arc_target(hp, j); | 629 | u64 n = mdesc_arc_target(hp, arc); |
636 | const char *n_name; | 630 | const char *name = mdesc_node_name(hp, n); |
637 | 631 | ||
638 | n_name = mdesc_node_name(hp, n); | 632 | if (!strcmp(srch_val, name)) |
639 | if (strcmp(n_name, "cpu")) | 633 | (*func)(hp, n, val); |
640 | continue; | ||
641 | 634 | ||
642 | id = mdesc_get_property(hp, n, "id", NULL); | 635 | find_back_node_value(hp, n, srch_val, func, val, depth-1); |
643 | if (*id < NR_CPUS) | ||
644 | cpu_data(*id).core_id = core_id; | ||
645 | } | ||
646 | } | ||
647 | } | 636 | } |
648 | } | 637 | } |
649 | 638 | ||
639 | static void __mark_core_id(struct mdesc_handle *hp, u64 node, | ||
640 | int core_id) | ||
641 | { | ||
642 | const u64 *id = mdesc_get_property(hp, node, "id", NULL); | ||
643 | |||
644 | if (*id < num_possible_cpus()) | ||
645 | cpu_data(*id).core_id = core_id; | ||
646 | } | ||
647 | |||
648 | static void __mark_sock_id(struct mdesc_handle *hp, u64 node, | ||
649 | int sock_id) | ||
650 | { | ||
651 | const u64 *id = mdesc_get_property(hp, node, "id", NULL); | ||
652 | |||
653 | if (*id < num_possible_cpus()) | ||
654 | cpu_data(*id).sock_id = sock_id; | ||
655 | } | ||
656 | |||
657 | static void mark_core_ids(struct mdesc_handle *hp, u64 mp, | ||
658 | int core_id) | ||
659 | { | ||
660 | find_back_node_value(hp, mp, "cpu", __mark_core_id, core_id, 10); | ||
661 | } | ||
662 | |||
663 | static void mark_sock_ids(struct mdesc_handle *hp, u64 mp, | ||
664 | int sock_id) | ||
665 | { | ||
666 | find_back_node_value(hp, mp, "cpu", __mark_sock_id, sock_id, 10); | ||
667 | } | ||
668 | |||
650 | static void set_core_ids(struct mdesc_handle *hp) | 669 | static void set_core_ids(struct mdesc_handle *hp) |
651 | { | 670 | { |
652 | int idx; | 671 | int idx; |
653 | u64 mp; | 672 | u64 mp; |
654 | 673 | ||
655 | idx = 1; | 674 | idx = 1; |
675 | |||
676 | /* Identify unique cores by looking for cpus backpointed to by | ||
677 | * level 1 instruction caches. | ||
678 | */ | ||
656 | mdesc_for_each_node_by_name(hp, mp, "cache") { | 679 | mdesc_for_each_node_by_name(hp, mp, "cache") { |
657 | const u64 *level; | 680 | const u64 *level; |
658 | const char *type; | 681 | const char *type; |
@@ -667,11 +690,72 @@ static void set_core_ids(struct mdesc_handle *hp) | |||
667 | continue; | 690 | continue; |
668 | 691 | ||
669 | mark_core_ids(hp, mp, idx); | 692 | mark_core_ids(hp, mp, idx); |
693 | idx++; | ||
694 | } | ||
695 | } | ||
696 | |||
697 | static int set_sock_ids_by_cache(struct mdesc_handle *hp, int level) | ||
698 | { | ||
699 | u64 mp; | ||
700 | int idx = 1; | ||
701 | int fnd = 0; | ||
702 | |||
703 | /* Identify unique sockets by looking for cpus backpointed to by | ||
704 | * shared level n caches. | ||
705 | */ | ||
706 | mdesc_for_each_node_by_name(hp, mp, "cache") { | ||
707 | const u64 *cur_lvl; | ||
708 | |||
709 | cur_lvl = mdesc_get_property(hp, mp, "level", NULL); | ||
710 | if (*cur_lvl != level) | ||
711 | continue; | ||
712 | |||
713 | mark_sock_ids(hp, mp, idx); | ||
714 | idx++; | ||
715 | fnd = 1; | ||
716 | } | ||
717 | return fnd; | ||
718 | } | ||
719 | |||
720 | static void set_sock_ids_by_socket(struct mdesc_handle *hp, u64 mp) | ||
721 | { | ||
722 | int idx = 1; | ||
670 | 723 | ||
724 | mdesc_for_each_node_by_name(hp, mp, "socket") { | ||
725 | u64 a; | ||
726 | |||
727 | mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) { | ||
728 | u64 t = mdesc_arc_target(hp, a); | ||
729 | const char *name; | ||
730 | const u64 *id; | ||
731 | |||
732 | name = mdesc_node_name(hp, t); | ||
733 | if (strcmp(name, "cpu")) | ||
734 | continue; | ||
735 | |||
736 | id = mdesc_get_property(hp, t, "id", NULL); | ||
737 | if (*id < num_possible_cpus()) | ||
738 | cpu_data(*id).sock_id = idx; | ||
739 | } | ||
671 | idx++; | 740 | idx++; |
672 | } | 741 | } |
673 | } | 742 | } |
674 | 743 | ||
744 | static void set_sock_ids(struct mdesc_handle *hp) | ||
745 | { | ||
746 | u64 mp; | ||
747 | |||
748 | /* If machine description exposes sockets data use it. | ||
749 | * Otherwise fallback to use shared L3 or L2 caches. | ||
750 | */ | ||
751 | mp = mdesc_node_by_name(hp, MDESC_NODE_NULL, "sockets"); | ||
752 | if (mp != MDESC_NODE_NULL) | ||
753 | return set_sock_ids_by_socket(hp, mp); | ||
754 | |||
755 | if (!set_sock_ids_by_cache(hp, 3)) | ||
756 | set_sock_ids_by_cache(hp, 2); | ||
757 | } | ||
758 | |||
675 | static void mark_proc_ids(struct mdesc_handle *hp, u64 mp, int proc_id) | 759 | static void mark_proc_ids(struct mdesc_handle *hp, u64 mp, int proc_id) |
676 | { | 760 | { |
677 | u64 a; | 761 | u64 a; |
@@ -707,7 +791,6 @@ static void __set_proc_ids(struct mdesc_handle *hp, const char *exec_unit_name) | |||
707 | continue; | 791 | continue; |
708 | 792 | ||
709 | mark_proc_ids(hp, mp, idx); | 793 | mark_proc_ids(hp, mp, idx); |
710 | |||
711 | idx++; | 794 | idx++; |
712 | } | 795 | } |
713 | } | 796 | } |
@@ -900,6 +983,7 @@ void mdesc_fill_in_cpu_data(cpumask_t *mask) | |||
900 | 983 | ||
901 | set_core_ids(hp); | 984 | set_core_ids(hp); |
902 | set_proc_ids(hp); | 985 | set_proc_ids(hp); |
986 | set_sock_ids(hp); | ||
903 | 987 | ||
904 | mdesc_release(hp); | 988 | mdesc_release(hp); |
905 | 989 | ||
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) | |||
1002 | subsys_initcall(pcibios_init); | 1002 | subsys_initcall(pcibios_init); |
1003 | 1003 | ||
1004 | #ifdef CONFIG_SYSFS | 1004 | #ifdef CONFIG_SYSFS |
1005 | |||
1006 | #define SLOT_NAME_SIZE 11 /* Max decimal digits + null in u32 */ | ||
1007 | |||
1008 | static void pcie_bus_slot_names(struct pci_bus *pbus) | ||
1009 | { | ||
1010 | struct pci_dev *pdev; | ||
1011 | struct pci_bus *bus; | ||
1012 | |||
1013 | list_for_each_entry(pdev, &pbus->devices, bus_list) { | ||
1014 | char name[SLOT_NAME_SIZE]; | ||
1015 | struct pci_slot *pci_slot; | ||
1016 | const u32 *slot_num; | ||
1017 | int len; | ||
1018 | |||
1019 | slot_num = of_get_property(pdev->dev.of_node, | ||
1020 | "physical-slot#", &len); | ||
1021 | |||
1022 | if (slot_num == NULL || len != 4) | ||
1023 | continue; | ||
1024 | |||
1025 | snprintf(name, sizeof(name), "%u", slot_num[0]); | ||
1026 | pci_slot = pci_create_slot(pbus, slot_num[0], name, NULL); | ||
1027 | |||
1028 | if (IS_ERR(pci_slot)) | ||
1029 | pr_err("PCI: pci_create_slot returned %ld.\n", | ||
1030 | PTR_ERR(pci_slot)); | ||
1031 | } | ||
1032 | |||
1033 | list_for_each_entry(bus, &pbus->children, node) | ||
1034 | pcie_bus_slot_names(bus); | ||
1035 | } | ||
1036 | |||
1005 | static void pci_bus_slot_names(struct device_node *node, struct pci_bus *bus) | 1037 | static void pci_bus_slot_names(struct device_node *node, struct pci_bus *bus) |
1006 | { | 1038 | { |
1007 | const struct pci_slot_names { | 1039 | const struct pci_slot_names { |
@@ -1053,18 +1085,29 @@ static int __init of_pci_slot_init(void) | |||
1053 | 1085 | ||
1054 | while ((pbus = pci_find_next_bus(pbus)) != NULL) { | 1086 | while ((pbus = pci_find_next_bus(pbus)) != NULL) { |
1055 | struct device_node *node; | 1087 | struct device_node *node; |
1088 | struct pci_dev *pdev; | ||
1089 | |||
1090 | pdev = list_first_entry(&pbus->devices, struct pci_dev, | ||
1091 | bus_list); | ||
1056 | 1092 | ||
1057 | if (pbus->self) { | 1093 | if (pdev && pci_is_pcie(pdev)) { |
1058 | /* PCI->PCI bridge */ | 1094 | pcie_bus_slot_names(pbus); |
1059 | node = pbus->self->dev.of_node; | ||
1060 | } else { | 1095 | } else { |
1061 | struct pci_pbm_info *pbm = pbus->sysdata; | ||
1062 | 1096 | ||
1063 | /* Host PCI controller */ | 1097 | if (pbus->self) { |
1064 | node = pbm->op->dev.of_node; | 1098 | |
1065 | } | 1099 | /* PCI->PCI bridge */ |
1100 | node = pbus->self->dev.of_node; | ||
1101 | |||
1102 | } else { | ||
1103 | struct pci_pbm_info *pbm = pbus->sysdata; | ||
1066 | 1104 | ||
1067 | pci_bus_slot_names(node, pbus); | 1105 | /* Host PCI controller */ |
1106 | node = pbm->op->dev.of_node; | ||
1107 | } | ||
1108 | |||
1109 | pci_bus_slot_names(node, pbus); | ||
1110 | } | ||
1068 | } | 1111 | } |
1069 | 1112 | ||
1070 | return 0; | 1113 | 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, | |||
255 | } | 255 | } |
256 | } | 256 | } |
257 | 257 | ||
258 | void sun_m7_patch_2insn_range(struct sun4v_2insn_patch_entry *start, | ||
259 | struct sun4v_2insn_patch_entry *end) | ||
260 | { | ||
261 | while (start < end) { | ||
262 | unsigned long addr = start->addr; | ||
263 | |||
264 | *(unsigned int *) (addr + 0) = start->insns[0]; | ||
265 | wmb(); | ||
266 | __asm__ __volatile__("flush %0" : : "r" (addr + 0)); | ||
267 | |||
268 | *(unsigned int *) (addr + 4) = start->insns[1]; | ||
269 | wmb(); | ||
270 | __asm__ __volatile__("flush %0" : : "r" (addr + 4)); | ||
271 | |||
272 | start++; | ||
273 | } | ||
274 | } | ||
275 | |||
258 | static void __init sun4v_patch(void) | 276 | static void __init sun4v_patch(void) |
259 | { | 277 | { |
260 | extern void sun4v_hvapi_init(void); | 278 | extern void sun4v_hvapi_init(void); |
@@ -267,6 +285,9 @@ static void __init sun4v_patch(void) | |||
267 | 285 | ||
268 | sun4v_patch_2insn_range(&__sun4v_2insn_patch, | 286 | sun4v_patch_2insn_range(&__sun4v_2insn_patch, |
269 | &__sun4v_2insn_patch_end); | 287 | &__sun4v_2insn_patch_end); |
288 | if (sun4v_chip_type == SUN4V_CHIP_SPARC_M7) | ||
289 | sun_m7_patch_2insn_range(&__sun_m7_2insn_patch, | ||
290 | &__sun_m7_2insn_patch_end); | ||
270 | 291 | ||
271 | sun4v_hvapi_init(); | 292 | sun4v_hvapi_init(); |
272 | } | 293 | } |
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; | |||
60 | cpumask_t cpu_core_map[NR_CPUS] __read_mostly = | 60 | cpumask_t cpu_core_map[NR_CPUS] __read_mostly = |
61 | { [0 ... NR_CPUS-1] = CPU_MASK_NONE }; | 61 | { [0 ... NR_CPUS-1] = CPU_MASK_NONE }; |
62 | 62 | ||
63 | cpumask_t cpu_core_sib_map[NR_CPUS] __read_mostly = { | ||
64 | [0 ... NR_CPUS-1] = CPU_MASK_NONE }; | ||
65 | |||
63 | EXPORT_PER_CPU_SYMBOL(cpu_sibling_map); | 66 | EXPORT_PER_CPU_SYMBOL(cpu_sibling_map); |
64 | EXPORT_SYMBOL(cpu_core_map); | 67 | EXPORT_SYMBOL(cpu_core_map); |
68 | EXPORT_SYMBOL(cpu_core_sib_map); | ||
65 | 69 | ||
66 | static cpumask_t smp_commenced_mask; | 70 | static cpumask_t smp_commenced_mask; |
67 | 71 | ||
@@ -1243,6 +1247,15 @@ void smp_fill_in_sib_core_maps(void) | |||
1243 | } | 1247 | } |
1244 | } | 1248 | } |
1245 | 1249 | ||
1250 | for_each_present_cpu(i) { | ||
1251 | unsigned int j; | ||
1252 | |||
1253 | for_each_present_cpu(j) { | ||
1254 | if (cpu_data(i).sock_id == cpu_data(j).sock_id) | ||
1255 | cpumask_set_cpu(j, &cpu_core_sib_map[i]); | ||
1256 | } | ||
1257 | } | ||
1258 | |||
1246 | for_each_present_cpu(i) { | 1259 | for_each_present_cpu(i) { |
1247 | unsigned int j; | 1260 | unsigned int j; |
1248 | 1261 | ||
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 | |||
138 | *(.pause_3insn_patch) | 138 | *(.pause_3insn_patch) |
139 | __pause_3insn_patch_end = .; | 139 | __pause_3insn_patch_end = .; |
140 | } | 140 | } |
141 | .sun_m7_2insn_patch : { | ||
142 | __sun_m7_2insn_patch = .; | ||
143 | *(.sun_m7_2insn_patch) | ||
144 | __sun_m7_2insn_patch_end = .; | ||
145 | } | ||
141 | PERCPU_SECTION(SMP_CACHE_BYTES) | 146 | PERCPU_SECTION(SMP_CACHE_BYTES) |
142 | 147 | ||
143 | . = ALIGN(PAGE_SIZE); | 148 | . = ALIGN(PAGE_SIZE); |