Skip to content

Commit

Permalink
x86, UV: Calculate BAU destination timeout
Browse files Browse the repository at this point in the history
Calculate the Broadcast Assist Unit's destination timeout period from the
values in the relevant MMR's.

Store it in each cpu's per-cpu BAU structure so that a destination
timeout can be differentiated from a 'plugged' situation in which all
software ack resources are already allocated and a timeout is pending.
That case returns an immediate destination error.

Signed-off-by: Cliff Wickman <cpw@sgi.com>
Cc: gregkh@suse.de
LKML-Reference: <E1OJvNx-0004Zq-RK@eag09.americas.sgi.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
  • Loading branch information
Cliff Wickman authored and Ingo Molnar committed Jun 8, 2010
1 parent 3975d16 commit 12a6611
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 4 deletions.
12 changes: 12 additions & 0 deletions arch/x86/include/asm/uv/uv_bau.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,18 @@
#define UV_ENABLE_INTD_SOFT_ACK_MODE_SHIFT 15
#define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHIFT 16
#define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD 0x000000000bUL
/* [19:16] SOFT_ACK timeout period 19: 1 is urgency 7 17:16 1 is multiplier */
#define BAU_MISC_CONTROL_MULT_MASK 3

#define UVH_AGING_PRESCALE_SEL 0x000000b000UL
/* [30:28] URGENCY_7 an index into a table of times */
#define BAU_URGENCY_7_SHIFT 28
#define BAU_URGENCY_7_MASK 7

#define UVH_TRANSACTION_TIMEOUT 0x000000b200UL
/* [45:40] BAU - BAU transaction timeout select - a multiplier */
#define BAU_TRANS_SHIFT 40
#define BAU_TRANS_MASK 0x3f

/*
* bits in UVH_LB_BAU_SB_ACTIVATION_STATUS_0/1
Expand Down
51 changes: 47 additions & 4 deletions arch/x86/kernel/tlb_uv.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,19 @@ struct msg_desc {
struct bau_payload_queue_entry *va_queue_last;
};

/* timeouts in nanoseconds (indexed by UVH_AGING_PRESCALE_SEL urgency7 30:28) */
static int timeout_base_ns[] = {
20,
160,
1280,
10240,
81920,
655360,
5242880,
167772160
};
static int timeout_us;

#define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD 0x000000000bUL

static int uv_bau_max_concurrent __read_mostly;
Expand Down Expand Up @@ -423,7 +436,8 @@ static int uv_wait_completion(struct bau_desc *bau_desc,
* pending. In that case hardware returns the
* ERROR that looks like a destination timeout.
*/
if (cycles_2_us(ttime - bcp->send_message) < BIOS_TO) {
if (cycles_2_us(ttime - bcp->send_message) <
timeout_us) {
bcp->conseccompletes = 0;
return FLUSH_RETRY_PLUGGED;
}
Expand Down Expand Up @@ -908,12 +922,12 @@ static void uv_ptc_seq_stop(struct seq_file *file, void *data)
}

static inline unsigned long long
millisec_2_cycles(unsigned long millisec)
microsec_2_cycles(unsigned long microsec)
{
unsigned long ns;
unsigned long long cyc;

ns = millisec * 1000;
ns = microsec * 1000;
cyc = (ns << CYC2NS_SCALE_FACTOR)/(per_cpu(cyc2ns, smp_processor_id()));
return cyc;
}
Expand Down Expand Up @@ -1258,6 +1272,33 @@ static void __init uv_init_uvhub(int uvhub, int vector)
((apicid << 32) | vector));
}

/*
* We will set BAU_MISC_CONTROL with a timeout period.
* But the BIOS has set UVH_AGING_PRESCALE_SEL and UVH_TRANSACTION_TIMEOUT.
* So the destination timeout period has be be calculated from them.
*/
static int
calculate_destination_timeout(void)
{
unsigned long mmr_image;
int mult1;
int mult2;
int index;
int base;
int ret;
unsigned long ts_ns;

mult1 = UV_INTD_SOFT_ACK_TIMEOUT_PERIOD & BAU_MISC_CONTROL_MULT_MASK;
mmr_image = uv_read_local_mmr(UVH_AGING_PRESCALE_SEL);
index = (mmr_image >> BAU_URGENCY_7_SHIFT) & BAU_URGENCY_7_MASK;
mmr_image = uv_read_local_mmr(UVH_TRANSACTION_TIMEOUT);
mult2 = (mmr_image >> BAU_TRANS_SHIFT) & BAU_TRANS_MASK;
base = timeout_base_ns[index];
ts_ns = base * mult1 * mult2;
ret = ts_ns / 1000;
return ret;
}

/*
* initialize the bau_control structure for each cpu
*/
Expand Down Expand Up @@ -1286,6 +1327,8 @@ static void uv_init_per_cpu(int nuvhubs)
};
struct uvhub_desc *uvhub_descs;

timeout_us = calculate_destination_timeout();

uvhub_descs = (struct uvhub_desc *)
kmalloc(nuvhubs * sizeof(struct uvhub_desc), GFP_KERNEL);
memset(uvhub_descs, 0, nuvhubs * sizeof(struct uvhub_desc));
Expand All @@ -1301,7 +1344,7 @@ static void uv_init_per_cpu(int nuvhubs)
bdp->uvhub = uvhub;
bdp->pnode = pnode;
/* time interval to catch a hardware stay-busy bug */
bcp->timeout_interval = millisec_2_cycles(3);
bcp->timeout_interval = microsec_2_cycles(2*timeout_us);
/* kludge: assume uv_hub.h is constant */
socket = (cpu_physical_id(cpu)>>5)&1;
if (socket >= bdp->num_sockets)
Expand Down

0 comments on commit 12a6611

Please sign in to comment.