diff options
Diffstat (limited to 'drivers/platform/x86/intel/ifs/runtest.c')
| -rw-r--r-- | drivers/platform/x86/intel/ifs/runtest.c | 101 | 
1 files changed, 62 insertions, 39 deletions
| diff --git a/drivers/platform/x86/intel/ifs/runtest.c b/drivers/platform/x86/intel/ifs/runtest.c index 13ecd55c6668..95b4b71fab53 100644 --- a/drivers/platform/x86/intel/ifs/runtest.c +++ b/drivers/platform/x86/intel/ifs/runtest.c @@ -23,6 +23,12 @@  /* Max retries on the same chunk */  #define MAX_IFS_RETRIES  5 +struct run_params { +	struct ifs_data *ifsd; +	union ifs_scan *activate; +	union ifs_status status; +}; +  /*   * Number of TSC cycles that a logical CPU will wait for the other   * logical CPU on the core in the WRMSR(ACTIVATE_SCAN). @@ -134,19 +140,56 @@ static bool can_restart(union ifs_status status)  	return false;  } +#define SPINUNIT 100 /* 100 nsec */ +static atomic_t array_cpus_in; +static atomic_t scan_cpus_in; + +/* + * Simplified cpu sibling rendezvous loop based on microcode loader __wait_for_cpus() + */ +static void wait_for_sibling_cpu(atomic_t *t, long long timeout) +{ +	int cpu = smp_processor_id(); +	const struct cpumask *smt_mask = cpu_smt_mask(cpu); +	int all_cpus = cpumask_weight(smt_mask); + +	atomic_inc(t); +	while (atomic_read(t) < all_cpus) { +		if (timeout < SPINUNIT) +			return; +		ndelay(SPINUNIT); +		timeout -= SPINUNIT; +		touch_nmi_watchdog(); +	} +} +  /*   * Execute the scan. Called "simultaneously" on all threads of a core   * at high priority using the stop_cpus mechanism.   */  static int doscan(void *data)  { -	int cpu = smp_processor_id(); -	u64 *msrs = data; +	int cpu = smp_processor_id(), start, stop; +	struct run_params *params = data; +	union ifs_status status; +	struct ifs_data *ifsd;  	int first; +	ifsd = params->ifsd; + +	if (ifsd->generation) { +		start = params->activate->gen2.start; +		stop = params->activate->gen2.stop; +	} else { +		start = params->activate->gen0.start; +		stop = params->activate->gen0.stop; +	} +  	/* Only the first logical CPU on a core reports result */  	first = cpumask_first(cpu_smt_mask(cpu)); +	wait_for_sibling_cpu(&scan_cpus_in, NSEC_PER_SEC); +  	/*  	 * This WRMSR will wait for other HT threads to also write  	 * to this MSR (at most for activate.delay cycles). Then it @@ -155,12 +198,14 @@ static int doscan(void *data)  	 * take up to 200 milliseconds (in the case where all chunks  	 * are processed in a single pass) before it retires.  	 */ -	wrmsrl(MSR_ACTIVATE_SCAN, msrs[0]); +	wrmsrl(MSR_ACTIVATE_SCAN, params->activate->data); +	rdmsrl(MSR_SCAN_STATUS, status.data); -	if (cpu == first) { -		/* Pass back the result of the scan */ -		rdmsrl(MSR_SCAN_STATUS, msrs[1]); -	} +	trace_ifs_status(ifsd->cur_batch, start, stop, status.data); + +	/* Pass back the result of the scan */ +	if (cpu == first) +		params->status = status;  	return 0;  } @@ -179,7 +224,7 @@ static void ifs_test_core(int cpu, struct device *dev)  	struct ifs_data *ifsd;  	int to_start, to_stop;  	int status_chunk; -	u64 msrvals[2]; +	struct run_params params;  	int retries;  	ifsd = ifs_get_data(dev); @@ -190,6 +235,8 @@ static void ifs_test_core(int cpu, struct device *dev)  	to_start = 0;  	to_stop = ifsd->valid_chunks - 1; +	params.ifsd = ifs_get_data(dev); +  	if (ifsd->generation) {  		activate.gen2.start = to_start;  		activate.gen2.stop = to_stop; @@ -207,12 +254,11 @@ static void ifs_test_core(int cpu, struct device *dev)  			break;  		} -		msrvals[0] = activate.data; -		stop_core_cpuslocked(cpu, doscan, msrvals); - -		status.data = msrvals[1]; +		params.activate = &activate; +		atomic_set(&scan_cpus_in, 0); +		stop_core_cpuslocked(cpu, doscan, ¶ms); -		trace_ifs_status(cpu, to_start, to_stop, status.data); +		status = params.status;  		/* Some cases can be retried, give up for others */  		if (!can_restart(status)) @@ -250,34 +296,14 @@ static void ifs_test_core(int cpu, struct device *dev)  	}  } -#define SPINUNIT 100 /* 100 nsec */ -static atomic_t array_cpus_out; - -/* - * Simplified cpu sibling rendezvous loop based on microcode loader __wait_for_cpus() - */ -static void wait_for_sibling_cpu(atomic_t *t, long long timeout) -{ -	int cpu = smp_processor_id(); -	const struct cpumask *smt_mask = cpu_smt_mask(cpu); -	int all_cpus = cpumask_weight(smt_mask); - -	atomic_inc(t); -	while (atomic_read(t) < all_cpus) { -		if (timeout < SPINUNIT) -			return; -		ndelay(SPINUNIT); -		timeout -= SPINUNIT; -		touch_nmi_watchdog(); -	} -} -  static int do_array_test(void *data)  {  	union ifs_array *command = data;  	int cpu = smp_processor_id();  	int first; +	wait_for_sibling_cpu(&array_cpus_in, NSEC_PER_SEC); +  	/*  	 * Only one logical CPU on a core needs to trigger the Array test via MSR write.  	 */ @@ -289,9 +315,6 @@ static int do_array_test(void *data)  		rdmsrl(MSR_ARRAY_BIST, command->data);  	} -	/* Tests complete faster if the sibling is spinning here */ -	wait_for_sibling_cpu(&array_cpus_out, NSEC_PER_SEC); -  	return 0;  } @@ -312,7 +335,7 @@ static void ifs_array_test_core(int cpu, struct device *dev)  			timed_out = true;  			break;  		} -		atomic_set(&array_cpus_out, 0); +		atomic_set(&array_cpus_in, 0);  		stop_core_cpuslocked(cpu, do_array_test, &command);  		if (command.ctrl_result) |