x86, UV: allow for non-consecutive sockets
Subsystems (2)
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH v4 1/8 x86, UV: smp_processor_id in a preemptable region
Fix a call by tunables_write() to smp_processor_id() within a preemptable region.
Call get_cpu()/put_cpu() around the region where the returned cpu number is actually used, which makes it non-preemptable.
Diffed against 3.0.0-rc3
---
A DEBUG_PREEMPT warning is prevented.
UV does not support cpu hotplug yet, but this is a step toward that ability.
arch/x86/platform/uv/tlb_uv.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
arch/x86/platform/uv/tlb_uv.c +3 -2
@@ -1334,9 +1334,10 @@ static ssize_t tunables_write(struct fil instr[count] ='\0' ; - bcp = &per_cpu (bau_control,smp_processor_id ()); - + cpu =get_cpu (); + bcp = &per_cpu (bau_control, cpu); ret =parse_tunables_write (bcp, instr, count); +put_cpu ();if (ret)return ret;
PATCH v4 2/8 x86, UV: inline header file functions
In reply to a message not in the archiveMake all the functions in uv_bau.h inline so that it can be included in the fake prom (used in simulations).
Diffed against 3.0.0-rc3
---
If not inlined the unused functions will generate compiler warnings.
arch/x86/include/asm/uv/uv_bau.h | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-)
arch/x86/include/asm/uv/uv_bau.h +14 -14
@@ -526,72 +526,72 @@ struct bau_control {struct hub_and_pnode *thp; }; -static unsigned long read_mmr_uv2_status (void ) +static inline unsigned long read_mmr_uv2_status (void ) {return read_lmmr (UV2H_LB_BAU_SB_ACTIVATION_STATUS_2 ); } -static void write_mmr_data_broadcast (int pnode,unsigned long mmr_image) +static inline void write_mmr_data_broadcast (int pnode,unsigned long mmr_image) {write_gmmr (pnode,UVH_BAU_DATA_BROADCAST , mmr_image); } -static void write_mmr_descriptor_base (int pnode,unsigned long mmr_image) +static inline void write_mmr_descriptor_base (int pnode,unsigned long mmr_image) {write_gmmr (pnode,UVH_LB_BAU_SB_DESCRIPTOR_BASE , mmr_image); } -static void write_mmr_activation (unsigned long index) +static inline void write_mmr_activation (unsigned long index) {write_lmmr (UVH_LB_BAU_SB_ACTIVATION_CONTROL , index); } -static void write_gmmr_activation (int pnode,unsigned long mmr_image) +static inline void write_gmmr_activation (int pnode,unsigned long mmr_image) {write_gmmr (pnode,UVH_LB_BAU_SB_ACTIVATION_CONTROL , mmr_image); } -static void write_mmr_payload_first (int pnode,unsigned long mmr_image) +static inline void write_mmr_payload_first (int pnode,unsigned long mmr_image) {write_gmmr (pnode,UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST , mmr_image); } -static void write_mmr_payload_tail (int pnode,unsigned long mmr_image) +static inline void write_mmr_payload_tail (int pnode,unsigned long mmr_image) {write_gmmr (pnode,UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL , mmr_image); } -static void write_mmr_payload_last (int pnode,unsigned long mmr_image) +static inline void write_mmr_payload_last (int pnode,unsigned long mmr_image) {write_gmmr (pnode,UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST , mmr_image); } -static void write_mmr_misc_control (int pnode,unsigned long mmr_image) +static inline void write_mmr_misc_control (int pnode,unsigned long mmr_image) {write_gmmr (pnode,UVH_LB_BAU_MISC_CONTROL , mmr_image); } -static unsigned long read_mmr_misc_control (int pnode) +static inline unsigned long read_mmr_misc_control (int pnode) {return read_gmmr (pnode,UVH_LB_BAU_MISC_CONTROL ); } -static void write_mmr_sw_ack (unsigned long mr) +static inline void write_mmr_sw_ack (unsigned long mr) {uv_write_local_mmr (UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS , mr); } -static unsigned long read_mmr_sw_ack (void ) +static inline unsigned long read_mmr_sw_ack (void ) {return read_lmmr (UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE ); } -static unsigned long read_gmmr_sw_ack (int pnode) +static inline unsigned long read_gmmr_sw_ack (int pnode) {return read_gmmr (pnode,UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE ); } -static void write_mmr_data_config (int pnode,unsigned long mr) +static inline void write_mmr_data_config (int pnode,unsigned long mr) {uv_write_global_mmr64 (pnode,UVH_BAU_DATA_CONFIG , mr); }
PATCH v4 3/8 x86, UV: allow for non-consecutive sockets
In reply to a message not in the archiveFix for the topology in which there is a socket 1 on a blade with no socket 0.
Diffed against 3.0.0-rc3
---
Only call make_per_cpu_thp() for present sockets. We have only seen this fail for internal configurations.
arch/x86/platform/uv/tlb_uv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/platform/uv/tlb_uv.c +1 -1
@@ -1752,10 +1752,10 @@ static int __init summarize_uvhub_socket sdp = &bdp->socket[socket];if (scan_sock (sdp, bdp, &smaster, &hmaster))return 1 ; +make_per_cpu_thp (smaster); } socket++; socket_mask = (socket_mask >>1 ); -make_per_cpu_thp (smaster); } }return 0 ;
PATCH v4 4/8 x86, UV: correct reset_with_ipi()
In reply to a message not in the archiveFix reset_with_ipi() to look up a cpu for a blade based on the distribution map being indexed by the potentially sparsely numbered pnode.
This patch is critical to tlb shootdown on a partitioned UV system, or one with nonconsecutive blade numbers.
Diffed against 3.0.0-rc3
---
The distribution map bits represent pnodes relative to the partition base pnode. Previous to this patch it had been assuming bits based on 0-based, consecutive blade ids.
arch/x86/platform/uv/tlb_uv.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-)
arch/x86/platform/uv/tlb_uv.c +21 -12
@@ -296,14 +296,18 @@ static void bau_process_message(struct m }/* -* Determine the first cpu on a uvhub. +* Determine the first cpu on a pnode. */ -static int uvhub_to_first_cpu (int uvhub) +static int pnode_to_first_cpu (int pnode,struct bau_control *smaster) {int cpu; -for_each_present_cpu (cpu) -if (uvhub ==uv_cpu_to_blade_id (cpu)) +struct hub_and_pnode *hpp; + +for_each_present_cpu (cpu) { + hpp = &smaster->thp[cpu]; +if (pnode == hpp->pnode)return cpu; + }return -1 ; }
@@ -366,23 +370,28 @@ static void do_reset(void *ptr)* Use IPI to get all target uvhubs to release resources held by * a given sending cpu number. */ -static void reset_with_ipi (struct bau_targ_hubmask *distribution,int sender) +static void reset_with_ipi (struct bau_targ_hubmask *distribution, +struct bau_control *bcp) { -int uvhub; +int pnode; +int apnode;int maskbits;cpumask_t mask; +int sender = bcp->cpu; +struct bau_control *smaster = bcp->socket_master;struct reset_args reset_args; reset_args.sender = sender;cpus_clear (mask);/* find a single cpu for each uvhub in this distribution mask */ maskbits =sizeof (struct bau_targ_hubmask ) *BITSPERBYTE ; -for (uvhub =0 ; uvhub < maskbits; uvhub++) { +/* each bit is a pnode relative to the partition base pnode */ +for (pnode =0 ; pnode < maskbits; pnode++) {int cpu; -if (!bau_uvhub_isset (uvhub, distribution)) +if (!bau_uvhub_isset (pnode, distribution))continue ; -/* find a cpu for this uvhub */ - cpu =uvhub_to_first_cpu (uvhub); + apnode = pnode + bcp->partition_base_pnode; + cpu =pnode_to_first_cpu (apnode, smaster);cpu_set (cpu, mask); }
@@ -604,7 +613,7 @@ static void destination_plugged(struct bquiesce_local_uvhub (hmaster);spin_lock (&hmaster->queue_lock); -reset_with_ipi (&bau_desc->distribution, bcp->cpu); +reset_with_ipi (&bau_desc->distribution, bcp);spin_unlock (&hmaster->queue_lock);end_uvhub_quiesce (hmaster);
@@ -626,7 +635,7 @@ static void destination_timeout(struct bquiesce_local_uvhub (hmaster);spin_lock (&hmaster->queue_lock); -reset_with_ipi (&bau_desc->distribution, bcp->cpu); +reset_with_ipi (&bau_desc->distribution, bcp);spin_unlock (&hmaster->queue_lock);end_uvhub_quiesce (hmaster);
PATCH v4 5/8 x86, UV: rename hubmask to pnmask
In reply to a message not in the archiveRename 'bau_targ_hubmask' to 'pnmask' for clarity.
Diffed against 3.0.0-rc3
---
The BAU distribution bit mask is indexed by pnode number, not hub or blade number. This important fact is not clear while the mask is called a 'hubmask'.
arch/x86/include/asm/uv/uv_bau.h | 12 ++++++------ arch/x86/platform/uv/tlb_uv.c | 5 ++--- 2 files changed, 8 insertions(+), 9 deletions(-)
arch/x86/include/asm/uv/uv_bau.h +6 -6
@@ -183,7 +183,7 @@* 'base_dest_nasid' field of the header corresponds to the * destination nodeID associated with that specified bit. */ -struct bau_targ_hubmask { +struct pnmask {unsigned long bits[BITS_TO_LONGS (UV_DISTRIBUTION_SIZE )]; };
@@ -314,7 +314,7 @@ struct bau_msg_header {* Should be 64 bytes */ struct bau_desc { -struct bau_targ_hubmask distribution; +struct pnmask distribution;/* * message template, consisting of header and payload: */
@@ -596,20 +596,20 @@ static inline void write_mmr_data_configuv_write_global_mmr64 (pnode,UVH_BAU_DATA_CONFIG , mr); } -static inline int bau_uvhub_isset (int uvhub,struct bau_targ_hubmask *dstp) +static inline int bau_uvhub_isset (int uvhub,struct pnmask *dstp) {return constant_test_bit (uvhub, &dstp->bits[0 ]); } -static inline void bau_uvhub_set (int pnode,struct bau_targ_hubmask *dstp) +static inline void bau_uvhub_set (int pnode,struct pnmask *dstp) {__set_bit (pnode, &dstp->bits[0 ]); } -static inline void bau_uvhubs_clear (struct bau_targ_hubmask *dstp, +static inline void bau_uvhubs_clear (struct pnmask *dstp,int nbits) {bitmap_zero (&dstp->bits[0 ], nbits); } -static inline int bau_uvhub_weight (struct bau_targ_hubmask *dstp) +static inline int bau_uvhub_weight (struct pnmask *dstp) {return bitmap_weight ((unsigned long *)&dstp->bits[0 ],UV_DISTRIBUTION_SIZE );
arch/x86/platform/uv/tlb_uv.c +2 -3
@@ -370,8 +370,7 @@ static void do_reset(void *ptr)* Use IPI to get all target uvhubs to release resources held by * a given sending cpu number. */ -static void reset_with_ipi (struct bau_targ_hubmask *distribution, -struct bau_control *bcp) +static void reset_with_ipi (struct pnmask *distribution,struct bau_control *bcp) {int pnode;int apnode;
@@ -384,7 +383,7 @@ static void reset_with_ipi(struct bau_ta reset_args.sender = sender;cpus_clear (mask);/* find a single cpu for each uvhub in this distribution mask */ - maskbits =sizeof (struct bau_targ_hubmask ) *BITSPERBYTE ; + maskbits =sizeof (struct pnmask ) *BITSPERBYTE ;/* each bit is a pnode relative to the partition base pnode */ for (pnode =0 ; pnode < maskbits; pnode++) {int cpu;
PATCH v4 6/8 x86, UV: remove cpumask_t from the stack
In reply to a message not in the archiveRemove the large stack-resident cpumask_t from reset_with_ipi()'s stack by allocating one per uvhub.
Diffed against 3.0.0-rc3
---
Due to the limited size of the stack the potentially huge cpumask_t may cause stack overrun. We haven't seen it happen yet, but we need to make it a practice not to push such structures onto the stack.
arch/x86/include/asm/uv/uv_bau.h | 1 + arch/x86/platform/uv/tlb_uv.c | 19 +++++++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-)
arch/x86/include/asm/uv/uv_bau.h +1 -0
@@ -488,6 +488,7 @@ struct bau_control {struct bau_control *uvhub_master;struct bau_control *socket_master;struct ptc_stats *statp; +cpumask_t *cpumask;unsigned long timeout_interval;unsigned long set_bau_on_time;atomic_t active_descriptor_count;
arch/x86/platform/uv/tlb_uv.c +15 -4
@@ -375,13 +375,13 @@ static void reset_with_ipi(struct pnmaskint pnode;int apnode;int maskbits; -cpumask_t mask;int sender = bcp->cpu; +cpumask_t *mask = bcp->uvhub_master->cpumask;struct bau_control *smaster = bcp->socket_master;struct reset_args reset_args; reset_args.sender = sender; -cpus_clear (mask); +cpus_clear (*mask);/* find a single cpu for each uvhub in this distribution mask */ maskbits =sizeof (struct pnmask ) *BITSPERBYTE ;/* each bit is a pnode relative to the partition base pnode */
@@ -391,11 +391,11 @@ static void reset_with_ipi(struct pnmaskcontinue ; apnode = pnode + bcp->partition_base_pnode; cpu =pnode_to_first_cpu (apnode, smaster); -cpu_set (cpu, mask); +cpu_set (cpu, *mask); }/* IPI all cpus; preemption is already disabled */ -smp_call_function_many (&mask, do_reset, (void *)&reset_args,1 ); +smp_call_function_many (mask, do_reset, (void *)&reset_args,1 );return ; }
@@ -1696,6 +1696,16 @@ static void make_per_cpu_thp(struct bau_ }/* +* Each uvhub is to get a local cpumask. +*/ +static void make_per_hub_cpumask (struct bau_control *hmaster) +{ +int sz =sizeof (cpumask_t); + + hmaster->cpumask =kzalloc_node (sz,GFP_KERNEL , hmaster->osnode); +} + +/* * Initialize all the per_cpu information for the cpu's on a given socket, * given what has been gathered into the socket_desc struct. * And reports the chosen hub and socket masters back to the caller.
@@ -1765,6 +1775,7 @@ static int __init summarize_uvhub_socket socket++; socket_mask = (socket_mask >>1 ); } +make_per_hub_cpumask (hmaster); }return 0 ; }
PATCH v4 7/8 x86, UV: correct failed topology memory leak
In reply to a message not in the archiveFix a memory leak in init_per_cpu() when the topology check fails.
Diffed against 3.0.0-rc3
---
The leak should never occur after development. It would only occur in an unexpected topology that would make the BAU unuseable as a result.
arch/x86/platform/uv/tlb_uv.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
arch/x86/platform/uv/tlb_uv.c +7 -2
@@ -1797,15 +1797,20 @@ static int __init init_per_cpu(int nuvhu uvhub_mask =kzalloc ((nuvhubs+7 )/8 ,GFP_KERNEL );if (get_cpu_topology (base_part_pnode, uvhub_descs, uvhub_mask)) -return 1 ; + goto fail;if (summarize_uvhub_sockets (nuvhubs, uvhub_descs, uvhub_mask)) -return 1 ; + goto fail;kfree (uvhub_descs);kfree (uvhub_mask);init_per_cpu_tunables ();return 0 ; + +fail: +kfree (uvhub_descs); +kfree (uvhub_mask); +return 1 ; }/*
PATCH v4 8/8 x86, UV: correct UV2 BAU destination timeout
In reply to a message not in the archiveCorrect the UV2 broacast assist unit's destination timeout period. And the activation status register in UV2 should be tested for a destination timeout with a 4, not a 2. The values for Active versus Timeout were reversed.
This patch is critical for TLB shootdown on an Altix UV2 system (i.e. the follow-on to the current Altix UV).
Diffed against 3.0.0-rc3
---
Destination timeout period:
The period is set in 4 bits of memory-mapped register MISC_CONTROL. The left bit toggles base period between 10us and 80us. The other 3 bits are the multiplier.
Decimal 15, hex f, gives the maximum: 7 * 80us
arch/x86/include/asm/uv/uv_bau.h | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-)
arch/x86/include/asm/uv/uv_bau.h +13 -5
@@ -67,7 +67,7 @@* we're using 655us, similar to UV1: 65 units of 10us */ #define UV1_INTD_SOFT_ACK_TIMEOUT_PERIOD (9UL) -#define UV2_INTD_SOFT_ACK_TIMEOUT_PERIOD (65*10UL) +#define UV2_INTD_SOFT_ACK_TIMEOUT_PERIOD (15UL)#define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD (is_uv1_hub() ? \ UV1_INTD_SOFT_ACK_TIMEOUT_PERIOD : \
@@ -106,12 +106,20 @@#define DS_SOURCE_TIMEOUT 3/* * bits put together from HRP_LB_BAU_SB_ACTIVATION_STATUS_0/1/2 -* values 1 and 5 will not occur +* values 1 and 3 will not occur +* Decoded meaning ERROR BUSY AUX ERR +* ------------------------------- ---- ----- ------- +* IDLE 0 0 0 +* BUSY (active) 0 1 0 +* SW Ack Timeout (destination) 1 0 0 +* SW Ack INTD rejected (strong NACK) 1 0 1 +* Source Side Time Out Detected 1 1 0 +* Destination Side PUT Failed 1 1 1 */ #define UV2H_DESC_IDLE 0 -#define UV2H_DESC_DEST_TIMEOUT 2 -#define UV2H_DESC_DEST_STRONG_NACK 3 -#define UV2H_DESC_BUSY 4 +#define UV2H_DESC_BUSY 2 +#define UV2H_DESC_DEST_TIMEOUT 4 +#define UV2H_DESC_DEST_STRONG_NACK 5#define UV2H_DESC_SOURCE_TIMEOUT 6#define UV2H_DESC_DEST_PUT_ERR 7