0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/init.h>
0014 #include <linux/kernel.h>
0015 #include <linux/memblock.h>
0016 #include <linux/mm.h>
0017 #include <linux/mmzone.h>
0018 #include <linux/export.h>
0019 #include <linux/nodemask.h>
0020 #include <linux/swap.h>
0021 #include <linux/pfn.h>
0022 #include <linux/highmem.h>
0023 #include <asm/page.h>
0024 #include <asm/pgalloc.h>
0025 #include <asm/sections.h>
0026
0027 #include <asm/sn/arch.h>
0028 #include <asm/sn/agent.h>
0029 #include <asm/sn/klconfig.h>
0030
0031 #include "ip27-common.h"
0032
0033 #define SLOT_PFNSHIFT (SLOT_SHIFT - PAGE_SHIFT)
0034 #define PFN_NASIDSHFT (NASID_SHFT - PAGE_SHIFT)
0035
0036 struct node_data *__node_data[MAX_NUMNODES];
0037
0038 EXPORT_SYMBOL(__node_data);
0039
0040 static u64 gen_region_mask(void)
0041 {
0042 int region_shift;
0043 u64 region_mask;
0044 nasid_t nasid;
0045
0046 region_shift = get_region_shift();
0047 region_mask = 0;
0048 for_each_online_node(nasid)
0049 region_mask |= BIT_ULL(nasid >> region_shift);
0050
0051 return region_mask;
0052 }
0053
0054 #define rou_rflag rou_flags
0055
0056 static int router_distance;
0057
0058 static void router_recurse(klrou_t *router_a, klrou_t *router_b, int depth)
0059 {
0060 klrou_t *router;
0061 lboard_t *brd;
0062 int port;
0063
0064 if (router_a->rou_rflag == 1)
0065 return;
0066
0067 if (depth >= router_distance)
0068 return;
0069
0070 router_a->rou_rflag = 1;
0071
0072 for (port = 1; port <= MAX_ROUTER_PORTS; port++) {
0073 if (router_a->rou_port[port].port_nasid == INVALID_NASID)
0074 continue;
0075
0076 brd = (lboard_t *)NODE_OFFSET_TO_K0(
0077 router_a->rou_port[port].port_nasid,
0078 router_a->rou_port[port].port_offset);
0079
0080 if (brd->brd_type == KLTYPE_ROUTER) {
0081 router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd), brd->brd_compts[0]);
0082 if (router == router_b) {
0083 if (depth < router_distance)
0084 router_distance = depth;
0085 }
0086 else
0087 router_recurse(router, router_b, depth + 1);
0088 }
0089 }
0090
0091 router_a->rou_rflag = 0;
0092 }
0093
0094 unsigned char __node_distances[MAX_NUMNODES][MAX_NUMNODES];
0095 EXPORT_SYMBOL(__node_distances);
0096
0097 static int __init compute_node_distance(nasid_t nasid_a, nasid_t nasid_b)
0098 {
0099 klrou_t *router, *router_a = NULL, *router_b = NULL;
0100 lboard_t *brd, *dest_brd;
0101 nasid_t nasid;
0102 int port;
0103
0104
0105 for_each_online_node(nasid) {
0106 brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid),
0107 KLTYPE_ROUTER);
0108
0109 if (!brd)
0110 continue;
0111
0112 do {
0113 if (brd->brd_flags & DUPLICATE_BOARD)
0114 continue;
0115
0116 router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd), brd->brd_compts[0]);
0117 router->rou_rflag = 0;
0118
0119 for (port = 1; port <= MAX_ROUTER_PORTS; port++) {
0120 if (router->rou_port[port].port_nasid == INVALID_NASID)
0121 continue;
0122
0123 dest_brd = (lboard_t *)NODE_OFFSET_TO_K0(
0124 router->rou_port[port].port_nasid,
0125 router->rou_port[port].port_offset);
0126
0127 if (dest_brd->brd_type == KLTYPE_IP27) {
0128 if (dest_brd->brd_nasid == nasid_a)
0129 router_a = router;
0130 if (dest_brd->brd_nasid == nasid_b)
0131 router_b = router;
0132 }
0133 }
0134
0135 } while ((brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER)));
0136 }
0137
0138 if (nasid_a == nasid_b)
0139 return LOCAL_DISTANCE;
0140
0141 if (router_a == router_b)
0142 return LOCAL_DISTANCE + 1;
0143
0144 if (router_a == NULL) {
0145 pr_info("node_distance: router_a NULL\n");
0146 return 255;
0147 }
0148 if (router_b == NULL) {
0149 pr_info("node_distance: router_b NULL\n");
0150 return 255;
0151 }
0152
0153 router_distance = 100;
0154 router_recurse(router_a, router_b, 2);
0155
0156 return LOCAL_DISTANCE + router_distance;
0157 }
0158
0159 static void __init init_topology_matrix(void)
0160 {
0161 nasid_t row, col;
0162
0163 for (row = 0; row < MAX_NUMNODES; row++)
0164 for (col = 0; col < MAX_NUMNODES; col++)
0165 __node_distances[row][col] = -1;
0166
0167 for_each_online_node(row) {
0168 for_each_online_node(col) {
0169 __node_distances[row][col] =
0170 compute_node_distance(row, col);
0171 }
0172 }
0173 }
0174
0175 static void __init dump_topology(void)
0176 {
0177 nasid_t nasid;
0178 lboard_t *brd, *dest_brd;
0179 int port;
0180 int router_num = 0;
0181 klrou_t *router;
0182 nasid_t row, col;
0183
0184 pr_info("************** Topology ********************\n");
0185
0186 pr_info(" ");
0187 for_each_online_node(col)
0188 pr_cont("%02d ", col);
0189 pr_cont("\n");
0190 for_each_online_node(row) {
0191 pr_info("%02d ", row);
0192 for_each_online_node(col)
0193 pr_cont("%2d ", node_distance(row, col));
0194 pr_cont("\n");
0195 }
0196
0197 for_each_online_node(nasid) {
0198 brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid),
0199 KLTYPE_ROUTER);
0200
0201 if (!brd)
0202 continue;
0203
0204 do {
0205 if (brd->brd_flags & DUPLICATE_BOARD)
0206 continue;
0207 pr_cont("Router %d:", router_num);
0208 router_num++;
0209
0210 router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd), brd->brd_compts[0]);
0211
0212 for (port = 1; port <= MAX_ROUTER_PORTS; port++) {
0213 if (router->rou_port[port].port_nasid == INVALID_NASID)
0214 continue;
0215
0216 dest_brd = (lboard_t *)NODE_OFFSET_TO_K0(
0217 router->rou_port[port].port_nasid,
0218 router->rou_port[port].port_offset);
0219
0220 if (dest_brd->brd_type == KLTYPE_IP27)
0221 pr_cont(" %d", dest_brd->brd_nasid);
0222 if (dest_brd->brd_type == KLTYPE_ROUTER)
0223 pr_cont(" r");
0224 }
0225 pr_cont("\n");
0226
0227 } while ( (brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER)) );
0228 }
0229 }
0230
0231 static unsigned long __init slot_getbasepfn(nasid_t nasid, int slot)
0232 {
0233 return ((unsigned long)nasid << PFN_NASIDSHFT) | (slot << SLOT_PFNSHIFT);
0234 }
0235
0236 static unsigned long __init slot_psize_compute(nasid_t nasid, int slot)
0237 {
0238 lboard_t *brd;
0239 klmembnk_t *banks;
0240 unsigned long size;
0241
0242
0243 brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27);
0244 if (!brd)
0245 return 0;
0246
0247
0248 banks = (klmembnk_t *) find_first_component(brd, KLSTRUCT_MEMBNK);
0249 if (!banks)
0250 return 0;
0251
0252
0253 size = (unsigned long)banks->membnk_bnksz[slot/4];
0254
0255
0256 if (size <= 128) {
0257 if (slot % 4 == 0) {
0258 size <<= 20;
0259 return size >> PAGE_SHIFT;
0260 } else
0261 return 0;
0262 } else {
0263 size /= 4;
0264 size <<= 20;
0265 return size >> PAGE_SHIFT;
0266 }
0267 }
0268
0269 static void __init mlreset(void)
0270 {
0271 u64 region_mask;
0272 nasid_t nasid;
0273
0274 master_nasid = get_nasid();
0275
0276
0277
0278
0279
0280 #ifdef CONFIG_SMP
0281 cpu_node_probe();
0282 #endif
0283
0284 init_topology_matrix();
0285 dump_topology();
0286
0287 region_mask = gen_region_mask();
0288
0289 setup_replication_mask();
0290
0291
0292
0293
0294 for_each_online_node(nasid) {
0295
0296
0297
0298
0299
0300 REMOTE_HUB_S(nasid, PI_REGION_PRESENT, (region_mask | 1));
0301 REMOTE_HUB_S(nasid, PI_CALIAS_SIZE, PI_CALIAS_SIZE_0);
0302
0303 #ifdef LATER
0304
0305
0306
0307
0308 REMOTE_HUB_S(nasid, IIO_ITTE(SWIN0_BIGWIN),
0309 ((HUB_PIO_MAP_TO_MEM << IIO_ITTE_IOSP_SHIFT) |
0310 (0 << IIO_ITTE_WIDGET_SHIFT)));
0311 #endif
0312 }
0313 }
0314
0315 static void __init szmem(void)
0316 {
0317 unsigned long slot_psize, slot0sz = 0, nodebytes;
0318 int slot;
0319 nasid_t node;
0320
0321 for_each_online_node(node) {
0322 nodebytes = 0;
0323 for (slot = 0; slot < MAX_MEM_SLOTS; slot++) {
0324 slot_psize = slot_psize_compute(node, slot);
0325 if (slot == 0)
0326 slot0sz = slot_psize;
0327
0328
0329
0330
0331 nodebytes += (1LL << SLOT_SHIFT);
0332
0333 if (!slot_psize)
0334 continue;
0335
0336 if ((nodebytes >> PAGE_SHIFT) * (sizeof(struct page)) >
0337 (slot0sz << PAGE_SHIFT)) {
0338 pr_info("Ignoring slot %d onwards on node %d\n",
0339 slot, node);
0340 slot = MAX_MEM_SLOTS;
0341 continue;
0342 }
0343 memblock_add_node(PFN_PHYS(slot_getbasepfn(node, slot)),
0344 PFN_PHYS(slot_psize), node,
0345 MEMBLOCK_NONE);
0346 }
0347 }
0348 }
0349
0350 static void __init node_mem_init(nasid_t node)
0351 {
0352 unsigned long slot_firstpfn = slot_getbasepfn(node, 0);
0353 unsigned long slot_freepfn = node_getfirstfree(node);
0354 unsigned long start_pfn, end_pfn;
0355
0356 get_pfn_range_for_nid(node, &start_pfn, &end_pfn);
0357
0358
0359
0360
0361 __node_data[node] = __va(slot_freepfn << PAGE_SHIFT);
0362 memset(__node_data[node], 0, PAGE_SIZE);
0363
0364 NODE_DATA(node)->node_start_pfn = start_pfn;
0365 NODE_DATA(node)->node_spanned_pages = end_pfn - start_pfn;
0366
0367 cpumask_clear(&hub_data(node)->h_cpus);
0368
0369 slot_freepfn += PFN_UP(sizeof(struct pglist_data) +
0370 sizeof(struct hub_data));
0371
0372 memblock_reserve(slot_firstpfn << PAGE_SHIFT,
0373 ((slot_freepfn - slot_firstpfn) << PAGE_SHIFT));
0374 }
0375
0376
0377
0378
0379
0380 static struct node_data null_node = {
0381 .hub = {
0382 .h_cpus = CPU_MASK_NONE
0383 }
0384 };
0385
0386
0387
0388
0389
0390
0391 void __init prom_meminit(void)
0392 {
0393 nasid_t node;
0394
0395 mlreset();
0396 szmem();
0397 max_low_pfn = PHYS_PFN(memblock_end_of_DRAM());
0398
0399 for (node = 0; node < MAX_NUMNODES; node++) {
0400 if (node_online(node)) {
0401 node_mem_init(node);
0402 continue;
0403 }
0404 __node_data[node] = &null_node;
0405 }
0406 }
0407
0408 extern void setup_zero_pages(void);
0409
0410 void __init paging_init(void)
0411 {
0412 unsigned long zones_size[MAX_NR_ZONES] = {0, };
0413
0414 pagetable_init();
0415 zones_size[ZONE_NORMAL] = max_low_pfn;
0416 free_area_init(zones_size);
0417 }
0418
0419 void __init mem_init(void)
0420 {
0421 high_memory = (void *) __va(get_num_physpages() << PAGE_SHIFT);
0422 memblock_free_all();
0423 setup_zero_pages();
0424 }
0425
0426 pg_data_t * __init arch_alloc_nodedata(int nid)
0427 {
0428 return memblock_alloc(sizeof(pg_data_t), SMP_CACHE_BYTES);
0429 }
0430
0431 void arch_refresh_nodedata(int nid, pg_data_t *pgdat)
0432 {
0433 __node_data[nid] = (struct node_data *)pgdat;
0434 }