diff options
author | Cliff Wickman <cpw@sgi.com> | 2010-06-02 17:22:02 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-06-08 15:13:46 -0400 |
commit | a8328ee58c15c9d763a67607a35bb987b38950fa (patch) | |
tree | 30fd2f8ef13eb8fbc72209237d366b2cddb4f1ca /arch/x86 | |
parent | 39847e7f3c8198b14102fe7ba4b3a6a1d84bbcfe (diff) |
x86, UV: Correct BAU discovery of hubs and sockets
Correct the initialization-time assumption of contigous blade
numbers and of sockets numbered from zero.
There may be hubs present with no cpu's enabled.
There may be disabled sockets such that the active socket is not
number zero.
And assign a 'socket master' by assuming that a socket is a
node. (it is not safe to extract socket number from an apicid)
Signed-off-by: Cliff Wickman <cpw@sgi.com>
Cc: gregkh@suse.de
LKML-Reference: <E1OJvNy-0004aW-9S@eag09.americas.sgi.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/kernel/tlb_uv.c | 49 |
1 files changed, 31 insertions, 18 deletions
diff --git a/arch/x86/kernel/tlb_uv.c b/arch/x86/kernel/tlb_uv.c index 295a41122da1..ab929e976502 100644 --- a/arch/x86/kernel/tlb_uv.c +++ b/arch/x86/kernel/tlb_uv.c | |||
@@ -1547,11 +1547,13 @@ calculate_destination_timeout(void) | |||
1547 | */ | 1547 | */ |
1548 | static void uv_init_per_cpu(int nuvhubs) | 1548 | static void uv_init_per_cpu(int nuvhubs) |
1549 | { | 1549 | { |
1550 | int i, j, k; | 1550 | int i; |
1551 | int cpu; | 1551 | int cpu; |
1552 | int pnode; | 1552 | int pnode; |
1553 | int uvhub; | 1553 | int uvhub; |
1554 | short socket = 0; | 1554 | short socket = 0; |
1555 | unsigned short socket_mask; | ||
1556 | unsigned int uvhub_mask; | ||
1555 | struct bau_control *bcp; | 1557 | struct bau_control *bcp; |
1556 | struct uvhub_desc *bdp; | 1558 | struct uvhub_desc *bdp; |
1557 | struct socket_desc *sdp; | 1559 | struct socket_desc *sdp; |
@@ -1562,7 +1564,7 @@ static void uv_init_per_cpu(int nuvhubs) | |||
1562 | short cpu_number[16]; | 1564 | short cpu_number[16]; |
1563 | }; | 1565 | }; |
1564 | struct uvhub_desc { | 1566 | struct uvhub_desc { |
1565 | short num_sockets; | 1567 | unsigned short socket_mask; |
1566 | short num_cpus; | 1568 | short num_cpus; |
1567 | short uvhub; | 1569 | short uvhub; |
1568 | short pnode; | 1570 | short pnode; |
@@ -1581,43 +1583,54 @@ static void uv_init_per_cpu(int nuvhubs) | |||
1581 | spin_lock_init(&bcp->masks_lock); | 1583 | spin_lock_init(&bcp->masks_lock); |
1582 | pnode = uv_cpu_hub_info(cpu)->pnode; | 1584 | pnode = uv_cpu_hub_info(cpu)->pnode; |
1583 | uvhub = uv_cpu_hub_info(cpu)->numa_blade_id; | 1585 | uvhub = uv_cpu_hub_info(cpu)->numa_blade_id; |
1586 | uvhub_mask |= (1 << uvhub); | ||
1584 | bdp = &uvhub_descs[uvhub]; | 1587 | bdp = &uvhub_descs[uvhub]; |
1585 | bdp->num_cpus++; | 1588 | bdp->num_cpus++; |
1586 | bdp->uvhub = uvhub; | 1589 | bdp->uvhub = uvhub; |
1587 | bdp->pnode = pnode; | 1590 | bdp->pnode = pnode; |
1588 | /* kludge: assume uv_hub.h is constant */ | 1591 | /* kludge: 'assuming' one node per socket, and assuming that |
1589 | socket = (cpu_physical_id(cpu)>>5)&1; | 1592 | disabling a socket just leaves a gap in node numbers */ |
1590 | if (socket >= bdp->num_sockets) | 1593 | socket = (cpu_to_node(cpu) & 1);; |
1591 | bdp->num_sockets = socket+1; | 1594 | bdp->socket_mask |= (1 << socket); |
1592 | sdp = &bdp->socket[socket]; | 1595 | sdp = &bdp->socket[socket]; |
1593 | sdp->cpu_number[sdp->num_cpus] = cpu; | 1596 | sdp->cpu_number[sdp->num_cpus] = cpu; |
1594 | sdp->num_cpus++; | 1597 | sdp->num_cpus++; |
1595 | } | 1598 | } |
1596 | socket = 0; | 1599 | uvhub = 0; |
1597 | for_each_possible_blade(uvhub) { | 1600 | while (uvhub_mask) { |
1601 | if (!(uvhub_mask & 1)) | ||
1602 | goto nexthub; | ||
1598 | bdp = &uvhub_descs[uvhub]; | 1603 | bdp = &uvhub_descs[uvhub]; |
1599 | for (i = 0; i < bdp->num_sockets; i++) { | 1604 | socket_mask = bdp->socket_mask; |
1600 | sdp = &bdp->socket[i]; | 1605 | socket = 0; |
1601 | for (j = 0; j < sdp->num_cpus; j++) { | 1606 | while (socket_mask) { |
1602 | cpu = sdp->cpu_number[j]; | 1607 | if (!(socket_mask & 1)) |
1608 | goto nextsocket; | ||
1609 | sdp = &bdp->socket[socket]; | ||
1610 | for (i = 0; i < sdp->num_cpus; i++) { | ||
1611 | cpu = sdp->cpu_number[i]; | ||
1603 | bcp = &per_cpu(bau_control, cpu); | 1612 | bcp = &per_cpu(bau_control, cpu); |
1604 | bcp->cpu = cpu; | 1613 | bcp->cpu = cpu; |
1605 | if (j == 0) { | 1614 | if (i == 0) { |
1606 | smaster = bcp; | 1615 | smaster = bcp; |
1607 | if (i == 0) | 1616 | if (socket == 0) |
1608 | hmaster = bcp; | 1617 | hmaster = bcp; |
1609 | } | 1618 | } |
1610 | bcp->cpus_in_uvhub = bdp->num_cpus; | 1619 | bcp->cpus_in_uvhub = bdp->num_cpus; |
1611 | bcp->cpus_in_socket = sdp->num_cpus; | 1620 | bcp->cpus_in_socket = sdp->num_cpus; |
1612 | bcp->socket_master = smaster; | 1621 | bcp->socket_master = smaster; |
1622 | bcp->uvhub = bdp->uvhub; | ||
1613 | bcp->uvhub_master = hmaster; | 1623 | bcp->uvhub_master = hmaster; |
1614 | for (k = 0; k < DEST_Q_SIZE; k++) | 1624 | bcp->uvhub_cpu = uv_cpu_hub_info(cpu)-> |
1615 | bcp->socket_acknowledge_count[k] = 0; | 1625 | blade_processor_id; |
1616 | bcp->uvhub_cpu = | ||
1617 | uv_cpu_hub_info(cpu)->blade_processor_id; | ||
1618 | } | 1626 | } |
1627 | nextsocket: | ||
1619 | socket++; | 1628 | socket++; |
1629 | socket_mask = (socket_mask >> 1); | ||
1620 | } | 1630 | } |
1631 | nexthub: | ||
1632 | uvhub++; | ||
1633 | uvhub_mask = (uvhub_mask >> 1); | ||
1621 | } | 1634 | } |
1622 | kfree(uvhub_descs); | 1635 | kfree(uvhub_descs); |
1623 | for_each_present_cpu(cpu) { | 1636 | for_each_present_cpu(cpu) { |