diff options
Diffstat (limited to 'drivers/platform/x86/intel/ifs/runtest.c')
| -rw-r--r-- | drivers/platform/x86/intel/ifs/runtest.c | 79 | 
1 files changed, 68 insertions, 11 deletions
| diff --git a/drivers/platform/x86/intel/ifs/runtest.c b/drivers/platform/x86/intel/ifs/runtest.c index 1061eb7ec399..13ecd55c6668 100644 --- a/drivers/platform/x86/intel/ifs/runtest.c +++ b/drivers/platform/x86/intel/ifs/runtest.c @@ -40,6 +40,8 @@ enum ifs_status_err_code {  	IFS_UNASSIGNED_ERROR_CODE		= 7,  	IFS_EXCEED_NUMBER_OF_THREADS_CONCURRENT	= 8,  	IFS_INTERRUPTED_DURING_EXECUTION	= 9, +	IFS_UNASSIGNED_ERROR_CODE_0xA		= 0xA, +	IFS_CORRUPTED_CHUNK		= 0xB,  };  static const char * const scan_test_status[] = { @@ -55,6 +57,8 @@ static const char * const scan_test_status[] = {  	[IFS_EXCEED_NUMBER_OF_THREADS_CONCURRENT] =  	"Exceeded number of Logical Processors (LP) allowed to run Scan-At-Field concurrently",  	[IFS_INTERRUPTED_DURING_EXECUTION] = "Interrupt occurred prior to SCAN start", +	[IFS_UNASSIGNED_ERROR_CODE_0xA] = "Unassigned error code 0xA", +	[IFS_CORRUPTED_CHUNK] = "Scan operation aborted due to corrupted image. Try reloading",  };  static void message_not_tested(struct device *dev, int cpu, union ifs_status status) @@ -123,6 +127,8 @@ static bool can_restart(union ifs_status status)  	case IFS_MISMATCH_ARGUMENTS_BETWEEN_THREADS:  	case IFS_CORE_NOT_CAPABLE_CURRENTLY:  	case IFS_UNASSIGNED_ERROR_CODE: +	case IFS_UNASSIGNED_ERROR_CODE_0xA: +	case IFS_CORRUPTED_CHUNK:  		break;  	}  	return false; @@ -171,21 +177,31 @@ static void ifs_test_core(int cpu, struct device *dev)  	union ifs_status status;  	unsigned long timeout;  	struct ifs_data *ifsd; +	int to_start, to_stop; +	int status_chunk;  	u64 msrvals[2];  	int retries;  	ifsd = ifs_get_data(dev); -	activate.rsvd = 0; +	activate.gen0.rsvd = 0;  	activate.delay = IFS_THREAD_WAIT;  	activate.sigmce = 0; -	activate.start = 0; -	activate.stop = ifsd->valid_chunks - 1; +	to_start = 0; +	to_stop = ifsd->valid_chunks - 1; + +	if (ifsd->generation) { +		activate.gen2.start = to_start; +		activate.gen2.stop = to_stop; +	} else { +		activate.gen0.start = to_start; +		activate.gen0.stop = to_stop; +	}  	timeout = jiffies + HZ / 2;  	retries = MAX_IFS_RETRIES; -	while (activate.start <= activate.stop) { +	while (to_start <= to_stop) {  		if (time_after(jiffies, timeout)) {  			status.error_code = IFS_SW_TIMEOUT;  			break; @@ -196,13 +212,14 @@ static void ifs_test_core(int cpu, struct device *dev)  		status.data = msrvals[1]; -		trace_ifs_status(cpu, activate, status); +		trace_ifs_status(cpu, to_start, to_stop, status.data);  		/* Some cases can be retried, give up for others */  		if (!can_restart(status))  			break; -		if (status.chunk_num == activate.start) { +		status_chunk = ifsd->generation ? status.gen2.chunk_num : status.gen0.chunk_num; +		if (status_chunk == to_start) {  			/* Check for forward progress */  			if (--retries == 0) {  				if (status.error_code == IFS_NO_ERROR) @@ -211,7 +228,11 @@ static void ifs_test_core(int cpu, struct device *dev)  			}  		} else {  			retries = MAX_IFS_RETRIES; -			activate.start = status.chunk_num; +			if (ifsd->generation) +				activate.gen2.start = status_chunk; +			else +				activate.gen0.start = status_chunk; +			to_start = status_chunk;  		}  	} @@ -308,6 +329,38 @@ static void ifs_array_test_core(int cpu, struct device *dev)  		ifsd->status = SCAN_TEST_PASS;  } +#define ARRAY_GEN1_TEST_ALL_ARRAYS	0x0ULL +#define ARRAY_GEN1_STATUS_FAIL		0x1ULL + +static int do_array_test_gen1(void *status) +{ +	int cpu = smp_processor_id(); +	int first; + +	first = cpumask_first(cpu_smt_mask(cpu)); + +	if (cpu == first) { +		wrmsrl(MSR_ARRAY_TRIGGER, ARRAY_GEN1_TEST_ALL_ARRAYS); +		rdmsrl(MSR_ARRAY_STATUS, *((u64 *)status)); +	} + +	return 0; +} + +static void ifs_array_test_gen1(int cpu, struct device *dev) +{ +	struct ifs_data *ifsd = ifs_get_data(dev); +	u64 status = 0; + +	stop_core_cpuslocked(cpu, do_array_test_gen1, &status); +	ifsd->scan_details = status; + +	if (status & ARRAY_GEN1_STATUS_FAIL) +		ifsd->status = SCAN_TEST_FAIL; +	else +		ifsd->status = SCAN_TEST_PASS; +} +  /*   * Initiate per core test. It wakes up work queue threads on the target cpu and   * its sibling cpu. Once all sibling threads wake up, the scan test gets executed and @@ -331,14 +384,18 @@ int do_core_test(int cpu, struct device *dev)  	switch (test->test_num) {  	case IFS_TYPE_SAF:  		if (!ifsd->loaded) -			return -EPERM; -		ifs_test_core(cpu, dev); +			ret = -EPERM; +		else +			ifs_test_core(cpu, dev);  		break;  	case IFS_TYPE_ARRAY_BIST: -		ifs_array_test_core(cpu, dev); +		if (ifsd->array_gen == ARRAY_GEN0) +			ifs_array_test_core(cpu, dev); +		else +			ifs_array_test_gen1(cpu, dev);  		break;  	default: -		return -EINVAL; +		ret = -EINVAL;  	}  out:  	cpus_read_unlock(); |