diff options
author | Cliff Wickman <cpw@sgi.com> | 2010-07-30 15:10:55 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-08-01 03:18:41 -0400 |
commit | c4026cfd8febcd63dd278894108839f30e525a0e (patch) | |
tree | 6eea79fdb39ef80d0eabbd0395d9dc1f93e1361a /arch | |
parent | 5edd19af18a36a4e22c570b1b969179e0ca1fe4c (diff) |
x86, UV: Initialize BAU hub map
Fix uninitialized uvhub_mask:
- An unitialized bit map variable was causing initialization of
non-existant hubs (this one causes boot panics).
- And the bit map was too small for large machines. This patch
makes it dynamic in size.
- Fix the case where socket 0 has no enabled cpu's. Don't assume
every hub has a socket 0.
- uv_init_per_cpu() should be __init.
Signed-off-by: Cliff Wickman <cpw@sgi.com>
Cc: <stable@kernel.org> # for .35.x
LKML-Reference: <E1Oeuyt-0004XS-0y@eag09.americas.sgi.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/tlb_uv.c | 26 |
1 files changed, 14 insertions, 12 deletions
diff --git a/arch/x86/kernel/tlb_uv.c b/arch/x86/kernel/tlb_uv.c index 59efb5390b37..312ef0292815 100644 --- a/arch/x86/kernel/tlb_uv.c +++ b/arch/x86/kernel/tlb_uv.c | |||
@@ -1484,15 +1484,16 @@ calculate_destination_timeout(void) | |||
1484 | /* | 1484 | /* |
1485 | * initialize the bau_control structure for each cpu | 1485 | * initialize the bau_control structure for each cpu |
1486 | */ | 1486 | */ |
1487 | static void uv_init_per_cpu(int nuvhubs) | 1487 | static void __init uv_init_per_cpu(int nuvhubs) |
1488 | { | 1488 | { |
1489 | int i; | 1489 | int i; |
1490 | int cpu; | 1490 | int cpu; |
1491 | int pnode; | 1491 | int pnode; |
1492 | int uvhub; | 1492 | int uvhub; |
1493 | int have_hmaster; | ||
1493 | short socket = 0; | 1494 | short socket = 0; |
1494 | unsigned short socket_mask; | 1495 | unsigned short socket_mask; |
1495 | unsigned int uvhub_mask; | 1496 | unsigned char *uvhub_mask; |
1496 | struct bau_control *bcp; | 1497 | struct bau_control *bcp; |
1497 | struct uvhub_desc *bdp; | 1498 | struct uvhub_desc *bdp; |
1498 | struct socket_desc *sdp; | 1499 | struct socket_desc *sdp; |
@@ -1516,28 +1517,29 @@ static void uv_init_per_cpu(int nuvhubs) | |||
1516 | uvhub_descs = (struct uvhub_desc *) | 1517 | uvhub_descs = (struct uvhub_desc *) |
1517 | kmalloc(nuvhubs * sizeof(struct uvhub_desc), GFP_KERNEL); | 1518 | kmalloc(nuvhubs * sizeof(struct uvhub_desc), GFP_KERNEL); |
1518 | memset(uvhub_descs, 0, nuvhubs * sizeof(struct uvhub_desc)); | 1519 | memset(uvhub_descs, 0, nuvhubs * sizeof(struct uvhub_desc)); |
1520 | uvhub_mask = kzalloc((nuvhubs+7)/8, GFP_KERNEL); | ||
1519 | for_each_present_cpu(cpu) { | 1521 | for_each_present_cpu(cpu) { |
1520 | bcp = &per_cpu(bau_control, cpu); | 1522 | bcp = &per_cpu(bau_control, cpu); |
1521 | memset(bcp, 0, sizeof(struct bau_control)); | 1523 | memset(bcp, 0, sizeof(struct bau_control)); |
1522 | pnode = uv_cpu_hub_info(cpu)->pnode; | 1524 | pnode = uv_cpu_hub_info(cpu)->pnode; |
1523 | uvhub = uv_cpu_hub_info(cpu)->numa_blade_id; | 1525 | uvhub = uv_cpu_hub_info(cpu)->numa_blade_id; |
1524 | uvhub_mask |= (1 << uvhub); | 1526 | *(uvhub_mask + (uvhub/8)) |= (1 << (uvhub%8)); |
1525 | bdp = &uvhub_descs[uvhub]; | 1527 | bdp = &uvhub_descs[uvhub]; |
1526 | bdp->num_cpus++; | 1528 | bdp->num_cpus++; |
1527 | bdp->uvhub = uvhub; | 1529 | bdp->uvhub = uvhub; |
1528 | bdp->pnode = pnode; | 1530 | bdp->pnode = pnode; |
1529 | /* kludge: 'assuming' one node per socket, and assuming that | 1531 | /* kludge: 'assuming' one node per socket, and assuming that |
1530 | disabling a socket just leaves a gap in node numbers */ | 1532 | disabling a socket just leaves a gap in node numbers */ |
1531 | socket = (cpu_to_node(cpu) & 1);; | 1533 | socket = (cpu_to_node(cpu) & 1); |
1532 | bdp->socket_mask |= (1 << socket); | 1534 | bdp->socket_mask |= (1 << socket); |
1533 | sdp = &bdp->socket[socket]; | 1535 | sdp = &bdp->socket[socket]; |
1534 | sdp->cpu_number[sdp->num_cpus] = cpu; | 1536 | sdp->cpu_number[sdp->num_cpus] = cpu; |
1535 | sdp->num_cpus++; | 1537 | sdp->num_cpus++; |
1536 | } | 1538 | } |
1537 | uvhub = 0; | 1539 | for (uvhub = 0; uvhub < nuvhubs; uvhub++) { |
1538 | while (uvhub_mask) { | 1540 | if (!(*(uvhub_mask + (uvhub/8)) & (1 << (uvhub%8)))) |
1539 | if (!(uvhub_mask & 1)) | 1541 | continue; |
1540 | goto nexthub; | 1542 | have_hmaster = 0; |
1541 | bdp = &uvhub_descs[uvhub]; | 1543 | bdp = &uvhub_descs[uvhub]; |
1542 | socket_mask = bdp->socket_mask; | 1544 | socket_mask = bdp->socket_mask; |
1543 | socket = 0; | 1545 | socket = 0; |
@@ -1551,8 +1553,10 @@ static void uv_init_per_cpu(int nuvhubs) | |||
1551 | bcp->cpu = cpu; | 1553 | bcp->cpu = cpu; |
1552 | if (i == 0) { | 1554 | if (i == 0) { |
1553 | smaster = bcp; | 1555 | smaster = bcp; |
1554 | if (socket == 0) | 1556 | if (!have_hmaster) { |
1557 | have_hmaster++; | ||
1555 | hmaster = bcp; | 1558 | hmaster = bcp; |
1559 | } | ||
1556 | } | 1560 | } |
1557 | bcp->cpus_in_uvhub = bdp->num_cpus; | 1561 | bcp->cpus_in_uvhub = bdp->num_cpus; |
1558 | bcp->cpus_in_socket = sdp->num_cpus; | 1562 | bcp->cpus_in_socket = sdp->num_cpus; |
@@ -1566,11 +1570,9 @@ nextsocket: | |||
1566 | socket++; | 1570 | socket++; |
1567 | socket_mask = (socket_mask >> 1); | 1571 | socket_mask = (socket_mask >> 1); |
1568 | } | 1572 | } |
1569 | nexthub: | ||
1570 | uvhub++; | ||
1571 | uvhub_mask = (uvhub_mask >> 1); | ||
1572 | } | 1573 | } |
1573 | kfree(uvhub_descs); | 1574 | kfree(uvhub_descs); |
1575 | kfree(uvhub_mask); | ||
1574 | for_each_present_cpu(cpu) { | 1576 | for_each_present_cpu(cpu) { |
1575 | bcp = &per_cpu(bau_control, cpu); | 1577 | bcp = &per_cpu(bau_control, cpu); |
1576 | bcp->baudisabled = 0; | 1578 | bcp->baudisabled = 0; |