162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright 2015 IBM Corp.
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include <linux/compiler.h>
862306a36Sopenharmony_ci#include <linux/types.h>
962306a36Sopenharmony_ci#include <linux/delay.h>
1062306a36Sopenharmony_ci#include <asm/byteorder.h>
1162306a36Sopenharmony_ci#include "hcalls.h"
1262306a36Sopenharmony_ci#include "trace.h"
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#define CXL_HCALL_TIMEOUT 60000
1562306a36Sopenharmony_ci#define CXL_HCALL_TIMEOUT_DOWNLOAD 120000
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#define H_ATTACH_CA_PROCESS    0x344
1862306a36Sopenharmony_ci#define H_CONTROL_CA_FUNCTION  0x348
1962306a36Sopenharmony_ci#define H_DETACH_CA_PROCESS    0x34C
2062306a36Sopenharmony_ci#define H_COLLECT_CA_INT_INFO  0x350
2162306a36Sopenharmony_ci#define H_CONTROL_CA_FAULTS    0x354
2262306a36Sopenharmony_ci#define H_DOWNLOAD_CA_FUNCTION 0x35C
2362306a36Sopenharmony_ci#define H_DOWNLOAD_CA_FACILITY 0x364
2462306a36Sopenharmony_ci#define H_CONTROL_CA_FACILITY  0x368
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#define H_CONTROL_CA_FUNCTION_RESET                   1 /* perform a reset */
2762306a36Sopenharmony_ci#define H_CONTROL_CA_FUNCTION_SUSPEND_PROCESS         2 /* suspend a process from being executed */
2862306a36Sopenharmony_ci#define H_CONTROL_CA_FUNCTION_RESUME_PROCESS          3 /* resume a process to be executed */
2962306a36Sopenharmony_ci#define H_CONTROL_CA_FUNCTION_READ_ERR_STATE          4 /* read the error state */
3062306a36Sopenharmony_ci#define H_CONTROL_CA_FUNCTION_GET_AFU_ERR             5 /* collect the AFU error buffer */
3162306a36Sopenharmony_ci#define H_CONTROL_CA_FUNCTION_GET_CONFIG              6 /* collect configuration record */
3262306a36Sopenharmony_ci#define H_CONTROL_CA_FUNCTION_GET_DOWNLOAD_STATE      7 /* query to return download status */
3362306a36Sopenharmony_ci#define H_CONTROL_CA_FUNCTION_TERMINATE_PROCESS       8 /* terminate the process before completion */
3462306a36Sopenharmony_ci#define H_CONTROL_CA_FUNCTION_COLLECT_VPD             9 /* collect VPD */
3562306a36Sopenharmony_ci#define H_CONTROL_CA_FUNCTION_GET_FUNCTION_ERR_INT   11 /* read the function-wide error data based on an interrupt */
3662306a36Sopenharmony_ci#define H_CONTROL_CA_FUNCTION_ACK_FUNCTION_ERR_INT   12 /* acknowledge function-wide error data based on an interrupt */
3762306a36Sopenharmony_ci#define H_CONTROL_CA_FUNCTION_GET_ERROR_LOG          13 /* retrieve the Platform Log ID (PLID) of an error log */
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci#define H_CONTROL_CA_FAULTS_RESPOND_PSL         1
4062306a36Sopenharmony_ci#define H_CONTROL_CA_FAULTS_RESPOND_AFU         2
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci#define H_CONTROL_CA_FACILITY_RESET             1 /* perform a reset */
4362306a36Sopenharmony_ci#define H_CONTROL_CA_FACILITY_COLLECT_VPD       2 /* collect VPD */
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci#define H_DOWNLOAD_CA_FACILITY_DOWNLOAD         1 /* download adapter image */
4662306a36Sopenharmony_ci#define H_DOWNLOAD_CA_FACILITY_VALIDATE         2 /* validate adapter image */
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci#define _CXL_LOOP_HCALL(call, rc, retbuf, fn, ...)			\
5062306a36Sopenharmony_ci	{								\
5162306a36Sopenharmony_ci		unsigned int delay, total_delay = 0;			\
5262306a36Sopenharmony_ci		u64 token = 0;						\
5362306a36Sopenharmony_ci									\
5462306a36Sopenharmony_ci		memset(retbuf, 0, sizeof(retbuf));			\
5562306a36Sopenharmony_ci		while (1) {						\
5662306a36Sopenharmony_ci			rc = call(fn, retbuf, __VA_ARGS__, token);	\
5762306a36Sopenharmony_ci			token = retbuf[0];				\
5862306a36Sopenharmony_ci			if (rc != H_BUSY && !H_IS_LONG_BUSY(rc))	\
5962306a36Sopenharmony_ci				break;					\
6062306a36Sopenharmony_ci									\
6162306a36Sopenharmony_ci			if (rc == H_BUSY)				\
6262306a36Sopenharmony_ci				delay = 10;				\
6362306a36Sopenharmony_ci			else						\
6462306a36Sopenharmony_ci				delay = get_longbusy_msecs(rc);		\
6562306a36Sopenharmony_ci									\
6662306a36Sopenharmony_ci			total_delay += delay;				\
6762306a36Sopenharmony_ci			if (total_delay > CXL_HCALL_TIMEOUT) {		\
6862306a36Sopenharmony_ci				WARN(1, "Warning: Giving up waiting for CXL hcall " \
6962306a36Sopenharmony_ci					"%#x after %u msec\n", fn, total_delay); \
7062306a36Sopenharmony_ci				rc = H_BUSY;				\
7162306a36Sopenharmony_ci				break;					\
7262306a36Sopenharmony_ci			}						\
7362306a36Sopenharmony_ci			msleep(delay);					\
7462306a36Sopenharmony_ci		}							\
7562306a36Sopenharmony_ci	}
7662306a36Sopenharmony_ci#define CXL_H_WAIT_UNTIL_DONE(...)  _CXL_LOOP_HCALL(plpar_hcall, __VA_ARGS__)
7762306a36Sopenharmony_ci#define CXL_H9_WAIT_UNTIL_DONE(...) _CXL_LOOP_HCALL(plpar_hcall9, __VA_ARGS__)
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci#define _PRINT_MSG(rc, format, ...)					\
8062306a36Sopenharmony_ci	{								\
8162306a36Sopenharmony_ci		if ((rc != H_SUCCESS) && (rc != H_CONTINUE))		\
8262306a36Sopenharmony_ci			pr_err(format, __VA_ARGS__);			\
8362306a36Sopenharmony_ci		else							\
8462306a36Sopenharmony_ci			pr_devel(format, __VA_ARGS__);			\
8562306a36Sopenharmony_ci	}								\
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_cistatic char *afu_op_names[] = {
8962306a36Sopenharmony_ci	"UNKNOWN_OP",		/* 0 undefined */
9062306a36Sopenharmony_ci	"RESET",		/* 1 */
9162306a36Sopenharmony_ci	"SUSPEND_PROCESS",	/* 2 */
9262306a36Sopenharmony_ci	"RESUME_PROCESS",	/* 3 */
9362306a36Sopenharmony_ci	"READ_ERR_STATE",	/* 4 */
9462306a36Sopenharmony_ci	"GET_AFU_ERR",		/* 5 */
9562306a36Sopenharmony_ci	"GET_CONFIG",		/* 6 */
9662306a36Sopenharmony_ci	"GET_DOWNLOAD_STATE",	/* 7 */
9762306a36Sopenharmony_ci	"TERMINATE_PROCESS",	/* 8 */
9862306a36Sopenharmony_ci	"COLLECT_VPD",		/* 9 */
9962306a36Sopenharmony_ci	"UNKNOWN_OP",		/* 10 undefined */
10062306a36Sopenharmony_ci	"GET_FUNCTION_ERR_INT",	/* 11 */
10162306a36Sopenharmony_ci	"ACK_FUNCTION_ERR_INT",	/* 12 */
10262306a36Sopenharmony_ci	"GET_ERROR_LOG",	/* 13 */
10362306a36Sopenharmony_ci};
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_cistatic char *control_adapter_op_names[] = {
10662306a36Sopenharmony_ci	"UNKNOWN_OP",		/* 0 undefined */
10762306a36Sopenharmony_ci	"RESET",		/* 1 */
10862306a36Sopenharmony_ci	"COLLECT_VPD",		/* 2 */
10962306a36Sopenharmony_ci};
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_cistatic char *download_op_names[] = {
11262306a36Sopenharmony_ci	"UNKNOWN_OP",		/* 0 undefined */
11362306a36Sopenharmony_ci	"DOWNLOAD",		/* 1 */
11462306a36Sopenharmony_ci	"VALIDATE",		/* 2 */
11562306a36Sopenharmony_ci};
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_cistatic char *op_str(unsigned int op, char *name_array[], int array_len)
11862306a36Sopenharmony_ci{
11962306a36Sopenharmony_ci	if (op >= array_len)
12062306a36Sopenharmony_ci		return "UNKNOWN_OP";
12162306a36Sopenharmony_ci	return name_array[op];
12262306a36Sopenharmony_ci}
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci#define OP_STR(op, name_array)      op_str(op, name_array, ARRAY_SIZE(name_array))
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci#define OP_STR_AFU(op)              OP_STR(op, afu_op_names)
12762306a36Sopenharmony_ci#define OP_STR_CONTROL_ADAPTER(op)  OP_STR(op, control_adapter_op_names)
12862306a36Sopenharmony_ci#define OP_STR_DOWNLOAD_ADAPTER(op) OP_STR(op, download_op_names)
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_cilong cxl_h_attach_process(u64 unit_address,
13262306a36Sopenharmony_ci			struct cxl_process_element_hcall *element,
13362306a36Sopenharmony_ci			u64 *process_token, u64 *mmio_addr, u64 *mmio_size)
13462306a36Sopenharmony_ci{
13562306a36Sopenharmony_ci	unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
13662306a36Sopenharmony_ci	long rc;
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	CXL_H_WAIT_UNTIL_DONE(rc, retbuf, H_ATTACH_CA_PROCESS, unit_address, virt_to_phys(element));
13962306a36Sopenharmony_ci	_PRINT_MSG(rc, "cxl_h_attach_process(%#.16llx, %#.16lx): %li\n",
14062306a36Sopenharmony_ci		unit_address, virt_to_phys(element), rc);
14162306a36Sopenharmony_ci	trace_cxl_hcall_attach(unit_address, virt_to_phys(element), retbuf[0], retbuf[1], retbuf[2], rc);
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	pr_devel("token: 0x%.8lx mmio_addr: 0x%lx mmio_size: 0x%lx\nProcess Element Structure:\n",
14462306a36Sopenharmony_ci		retbuf[0], retbuf[1], retbuf[2]);
14562306a36Sopenharmony_ci	cxl_dump_debug_buffer(element, sizeof(*element));
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	switch (rc) {
14862306a36Sopenharmony_ci	case H_SUCCESS:       /* The process info is attached to the coherent platform function */
14962306a36Sopenharmony_ci		*process_token = retbuf[0];
15062306a36Sopenharmony_ci		if (mmio_addr)
15162306a36Sopenharmony_ci			*mmio_addr = retbuf[1];
15262306a36Sopenharmony_ci		if (mmio_size)
15362306a36Sopenharmony_ci			*mmio_size = retbuf[2];
15462306a36Sopenharmony_ci		return 0;
15562306a36Sopenharmony_ci	case H_PARAMETER:     /* An incorrect parameter was supplied. */
15662306a36Sopenharmony_ci	case H_FUNCTION:      /* The function is not supported. */
15762306a36Sopenharmony_ci		return -EINVAL;
15862306a36Sopenharmony_ci	case H_AUTHORITY:     /* The partition does not have authority to perform this hcall */
15962306a36Sopenharmony_ci	case H_RESOURCE:      /* The coherent platform function does not have enough additional resource to attach the process */
16062306a36Sopenharmony_ci	case H_HARDWARE:      /* A hardware event prevented the attach operation */
16162306a36Sopenharmony_ci	case H_STATE:         /* The coherent platform function is not in a valid state */
16262306a36Sopenharmony_ci	case H_BUSY:
16362306a36Sopenharmony_ci		return -EBUSY;
16462306a36Sopenharmony_ci	default:
16562306a36Sopenharmony_ci		WARN(1, "Unexpected return code: %lx", rc);
16662306a36Sopenharmony_ci		return -EINVAL;
16762306a36Sopenharmony_ci	}
16862306a36Sopenharmony_ci}
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci/*
17162306a36Sopenharmony_ci * cxl_h_detach_process - Detach a process element from a coherent
17262306a36Sopenharmony_ci *                        platform function.
17362306a36Sopenharmony_ci */
17462306a36Sopenharmony_cilong cxl_h_detach_process(u64 unit_address, u64 process_token)
17562306a36Sopenharmony_ci{
17662306a36Sopenharmony_ci	unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
17762306a36Sopenharmony_ci	long rc;
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci	CXL_H_WAIT_UNTIL_DONE(rc, retbuf, H_DETACH_CA_PROCESS, unit_address, process_token);
18062306a36Sopenharmony_ci	_PRINT_MSG(rc, "cxl_h_detach_process(%#.16llx, 0x%.8llx): %li\n", unit_address, process_token, rc);
18162306a36Sopenharmony_ci	trace_cxl_hcall_detach(unit_address, process_token, rc);
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci	switch (rc) {
18462306a36Sopenharmony_ci	case H_SUCCESS:       /* The process was detached from the coherent platform function */
18562306a36Sopenharmony_ci		return 0;
18662306a36Sopenharmony_ci	case H_PARAMETER:     /* An incorrect parameter was supplied. */
18762306a36Sopenharmony_ci		return -EINVAL;
18862306a36Sopenharmony_ci	case H_AUTHORITY:     /* The partition does not have authority to perform this hcall */
18962306a36Sopenharmony_ci	case H_RESOURCE:      /* The function has page table mappings for MMIO */
19062306a36Sopenharmony_ci	case H_HARDWARE:      /* A hardware event prevented the detach operation */
19162306a36Sopenharmony_ci	case H_STATE:         /* The coherent platform function is not in a valid state */
19262306a36Sopenharmony_ci	case H_BUSY:
19362306a36Sopenharmony_ci		return -EBUSY;
19462306a36Sopenharmony_ci	default:
19562306a36Sopenharmony_ci		WARN(1, "Unexpected return code: %lx", rc);
19662306a36Sopenharmony_ci		return -EINVAL;
19762306a36Sopenharmony_ci	}
19862306a36Sopenharmony_ci}
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci/*
20162306a36Sopenharmony_ci * cxl_h_control_function - This H_CONTROL_CA_FUNCTION hypervisor call allows
20262306a36Sopenharmony_ci *                          the partition to manipulate or query
20362306a36Sopenharmony_ci *                          certain coherent platform function behaviors.
20462306a36Sopenharmony_ci */
20562306a36Sopenharmony_cistatic long cxl_h_control_function(u64 unit_address, u64 op,
20662306a36Sopenharmony_ci				   u64 p1, u64 p2, u64 p3, u64 p4, u64 *out)
20762306a36Sopenharmony_ci{
20862306a36Sopenharmony_ci	unsigned long retbuf[PLPAR_HCALL9_BUFSIZE];
20962306a36Sopenharmony_ci	long rc;
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci	CXL_H9_WAIT_UNTIL_DONE(rc, retbuf, H_CONTROL_CA_FUNCTION, unit_address, op, p1, p2, p3, p4);
21262306a36Sopenharmony_ci	_PRINT_MSG(rc, "cxl_h_control_function(%#.16llx, %s(%#llx, %#llx, %#llx, %#llx, R4: %#lx)): %li\n",
21362306a36Sopenharmony_ci		unit_address, OP_STR_AFU(op), p1, p2, p3, p4, retbuf[0], rc);
21462306a36Sopenharmony_ci	trace_cxl_hcall_control_function(unit_address, OP_STR_AFU(op), p1, p2, p3, p4, retbuf[0], rc);
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci	switch (rc) {
21762306a36Sopenharmony_ci	case H_SUCCESS:       /* The operation is completed for the coherent platform function */
21862306a36Sopenharmony_ci		if ((op == H_CONTROL_CA_FUNCTION_GET_FUNCTION_ERR_INT ||
21962306a36Sopenharmony_ci		     op == H_CONTROL_CA_FUNCTION_READ_ERR_STATE ||
22062306a36Sopenharmony_ci		     op == H_CONTROL_CA_FUNCTION_COLLECT_VPD))
22162306a36Sopenharmony_ci			*out = retbuf[0];
22262306a36Sopenharmony_ci		return 0;
22362306a36Sopenharmony_ci	case H_PARAMETER:     /* An incorrect parameter was supplied. */
22462306a36Sopenharmony_ci	case H_FUNCTION:      /* The function is not supported. */
22562306a36Sopenharmony_ci	case H_NOT_FOUND:     /* The operation supplied was not valid */
22662306a36Sopenharmony_ci	case H_NOT_AVAILABLE: /* The operation cannot be performed because the AFU has not been downloaded */
22762306a36Sopenharmony_ci	case H_SG_LIST:       /* An block list entry was invalid */
22862306a36Sopenharmony_ci		return -EINVAL;
22962306a36Sopenharmony_ci	case H_AUTHORITY:     /* The partition does not have authority to perform this hcall */
23062306a36Sopenharmony_ci	case H_RESOURCE:      /* The function has page table mappings for MMIO */
23162306a36Sopenharmony_ci	case H_HARDWARE:      /* A hardware event prevented the attach operation */
23262306a36Sopenharmony_ci	case H_STATE:         /* The coherent platform function is not in a valid state */
23362306a36Sopenharmony_ci	case H_BUSY:
23462306a36Sopenharmony_ci		return -EBUSY;
23562306a36Sopenharmony_ci	default:
23662306a36Sopenharmony_ci		WARN(1, "Unexpected return code: %lx", rc);
23762306a36Sopenharmony_ci		return -EINVAL;
23862306a36Sopenharmony_ci	}
23962306a36Sopenharmony_ci}
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci/*
24262306a36Sopenharmony_ci * cxl_h_reset_afu - Perform a reset to the coherent platform function.
24362306a36Sopenharmony_ci */
24462306a36Sopenharmony_cilong cxl_h_reset_afu(u64 unit_address)
24562306a36Sopenharmony_ci{
24662306a36Sopenharmony_ci	return cxl_h_control_function(unit_address,
24762306a36Sopenharmony_ci				H_CONTROL_CA_FUNCTION_RESET,
24862306a36Sopenharmony_ci				0, 0, 0, 0,
24962306a36Sopenharmony_ci				NULL);
25062306a36Sopenharmony_ci}
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci/*
25362306a36Sopenharmony_ci * cxl_h_suspend_process - Suspend a process from being executed
25462306a36Sopenharmony_ci * Parameter1 = process-token as returned from H_ATTACH_CA_PROCESS when
25562306a36Sopenharmony_ci *              process was attached.
25662306a36Sopenharmony_ci */
25762306a36Sopenharmony_cilong cxl_h_suspend_process(u64 unit_address, u64 process_token)
25862306a36Sopenharmony_ci{
25962306a36Sopenharmony_ci	return cxl_h_control_function(unit_address,
26062306a36Sopenharmony_ci				H_CONTROL_CA_FUNCTION_SUSPEND_PROCESS,
26162306a36Sopenharmony_ci				process_token, 0, 0, 0,
26262306a36Sopenharmony_ci				NULL);
26362306a36Sopenharmony_ci}
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci/*
26662306a36Sopenharmony_ci * cxl_h_resume_process - Resume a process to be executed
26762306a36Sopenharmony_ci * Parameter1 = process-token as returned from H_ATTACH_CA_PROCESS when
26862306a36Sopenharmony_ci *              process was attached.
26962306a36Sopenharmony_ci */
27062306a36Sopenharmony_cilong cxl_h_resume_process(u64 unit_address, u64 process_token)
27162306a36Sopenharmony_ci{
27262306a36Sopenharmony_ci	return cxl_h_control_function(unit_address,
27362306a36Sopenharmony_ci				H_CONTROL_CA_FUNCTION_RESUME_PROCESS,
27462306a36Sopenharmony_ci				process_token, 0, 0, 0,
27562306a36Sopenharmony_ci				NULL);
27662306a36Sopenharmony_ci}
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci/*
27962306a36Sopenharmony_ci * cxl_h_read_error_state - Checks the error state of the coherent
28062306a36Sopenharmony_ci *                          platform function.
28162306a36Sopenharmony_ci * R4 contains the error state
28262306a36Sopenharmony_ci */
28362306a36Sopenharmony_cilong cxl_h_read_error_state(u64 unit_address, u64 *state)
28462306a36Sopenharmony_ci{
28562306a36Sopenharmony_ci	return cxl_h_control_function(unit_address,
28662306a36Sopenharmony_ci				H_CONTROL_CA_FUNCTION_READ_ERR_STATE,
28762306a36Sopenharmony_ci				0, 0, 0, 0,
28862306a36Sopenharmony_ci				state);
28962306a36Sopenharmony_ci}
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci/*
29262306a36Sopenharmony_ci * cxl_h_get_afu_err - collect the AFU error buffer
29362306a36Sopenharmony_ci * Parameter1 = byte offset into error buffer to retrieve, valid values
29462306a36Sopenharmony_ci *              are between 0 and (ibm,error-buffer-size - 1)
29562306a36Sopenharmony_ci * Parameter2 = 4K aligned real address of error buffer, to be filled in
29662306a36Sopenharmony_ci * Parameter3 = length of error buffer, valid values are 4K or less
29762306a36Sopenharmony_ci */
29862306a36Sopenharmony_cilong cxl_h_get_afu_err(u64 unit_address, u64 offset,
29962306a36Sopenharmony_ci		u64 buf_address, u64 len)
30062306a36Sopenharmony_ci{
30162306a36Sopenharmony_ci	return cxl_h_control_function(unit_address,
30262306a36Sopenharmony_ci				H_CONTROL_CA_FUNCTION_GET_AFU_ERR,
30362306a36Sopenharmony_ci				offset, buf_address, len, 0,
30462306a36Sopenharmony_ci				NULL);
30562306a36Sopenharmony_ci}
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci/*
30862306a36Sopenharmony_ci * cxl_h_get_config - collect configuration record for the
30962306a36Sopenharmony_ci *                    coherent platform function
31062306a36Sopenharmony_ci * Parameter1 = # of configuration record to retrieve, valid values are
31162306a36Sopenharmony_ci *              between 0 and (ibm,#config-records - 1)
31262306a36Sopenharmony_ci * Parameter2 = byte offset into configuration record to retrieve,
31362306a36Sopenharmony_ci *              valid values are between 0 and (ibm,config-record-size - 1)
31462306a36Sopenharmony_ci * Parameter3 = 4K aligned real address of configuration record buffer,
31562306a36Sopenharmony_ci *              to be filled in
31662306a36Sopenharmony_ci * Parameter4 = length of configuration buffer, valid values are 4K or less
31762306a36Sopenharmony_ci */
31862306a36Sopenharmony_cilong cxl_h_get_config(u64 unit_address, u64 cr_num, u64 offset,
31962306a36Sopenharmony_ci		u64 buf_address, u64 len)
32062306a36Sopenharmony_ci{
32162306a36Sopenharmony_ci	return cxl_h_control_function(unit_address,
32262306a36Sopenharmony_ci				H_CONTROL_CA_FUNCTION_GET_CONFIG,
32362306a36Sopenharmony_ci				cr_num, offset, buf_address, len,
32462306a36Sopenharmony_ci				NULL);
32562306a36Sopenharmony_ci}
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci/*
32862306a36Sopenharmony_ci * cxl_h_terminate_process - Terminate the process before completion
32962306a36Sopenharmony_ci * Parameter1 = process-token as returned from H_ATTACH_CA_PROCESS when
33062306a36Sopenharmony_ci *              process was attached.
33162306a36Sopenharmony_ci */
33262306a36Sopenharmony_cilong cxl_h_terminate_process(u64 unit_address, u64 process_token)
33362306a36Sopenharmony_ci{
33462306a36Sopenharmony_ci	return cxl_h_control_function(unit_address,
33562306a36Sopenharmony_ci				H_CONTROL_CA_FUNCTION_TERMINATE_PROCESS,
33662306a36Sopenharmony_ci				process_token, 0, 0, 0,
33762306a36Sopenharmony_ci				NULL);
33862306a36Sopenharmony_ci}
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci/*
34162306a36Sopenharmony_ci * cxl_h_collect_vpd - Collect VPD for the coherent platform function.
34262306a36Sopenharmony_ci * Parameter1 = # of VPD record to retrieve, valid values are between 0
34362306a36Sopenharmony_ci *              and (ibm,#config-records - 1).
34462306a36Sopenharmony_ci * Parameter2 = 4K naturally aligned real buffer containing block
34562306a36Sopenharmony_ci *              list entries
34662306a36Sopenharmony_ci * Parameter3 = number of block list entries in the block list, valid
34762306a36Sopenharmony_ci *              values are between 0 and 256
34862306a36Sopenharmony_ci */
34962306a36Sopenharmony_cilong cxl_h_collect_vpd(u64 unit_address, u64 record, u64 list_address,
35062306a36Sopenharmony_ci		       u64 num, u64 *out)
35162306a36Sopenharmony_ci{
35262306a36Sopenharmony_ci	return cxl_h_control_function(unit_address,
35362306a36Sopenharmony_ci				H_CONTROL_CA_FUNCTION_COLLECT_VPD,
35462306a36Sopenharmony_ci				record, list_address, num, 0,
35562306a36Sopenharmony_ci				out);
35662306a36Sopenharmony_ci}
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci/*
35962306a36Sopenharmony_ci * cxl_h_get_fn_error_interrupt - Read the function-wide error data based on an interrupt
36062306a36Sopenharmony_ci */
36162306a36Sopenharmony_cilong cxl_h_get_fn_error_interrupt(u64 unit_address, u64 *reg)
36262306a36Sopenharmony_ci{
36362306a36Sopenharmony_ci	return cxl_h_control_function(unit_address,
36462306a36Sopenharmony_ci				H_CONTROL_CA_FUNCTION_GET_FUNCTION_ERR_INT,
36562306a36Sopenharmony_ci				0, 0, 0, 0, reg);
36662306a36Sopenharmony_ci}
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ci/*
36962306a36Sopenharmony_ci * cxl_h_ack_fn_error_interrupt - Acknowledge function-wide error data
37062306a36Sopenharmony_ci *                                based on an interrupt
37162306a36Sopenharmony_ci * Parameter1 = value to write to the function-wide error interrupt register
37262306a36Sopenharmony_ci */
37362306a36Sopenharmony_cilong cxl_h_ack_fn_error_interrupt(u64 unit_address, u64 value)
37462306a36Sopenharmony_ci{
37562306a36Sopenharmony_ci	return cxl_h_control_function(unit_address,
37662306a36Sopenharmony_ci				H_CONTROL_CA_FUNCTION_ACK_FUNCTION_ERR_INT,
37762306a36Sopenharmony_ci				value, 0, 0, 0,
37862306a36Sopenharmony_ci				NULL);
37962306a36Sopenharmony_ci}
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci/*
38262306a36Sopenharmony_ci * cxl_h_get_error_log - Retrieve the Platform Log ID (PLID) of
38362306a36Sopenharmony_ci *                       an error log
38462306a36Sopenharmony_ci */
38562306a36Sopenharmony_cilong cxl_h_get_error_log(u64 unit_address, u64 value)
38662306a36Sopenharmony_ci{
38762306a36Sopenharmony_ci	return cxl_h_control_function(unit_address,
38862306a36Sopenharmony_ci				H_CONTROL_CA_FUNCTION_GET_ERROR_LOG,
38962306a36Sopenharmony_ci				0, 0, 0, 0,
39062306a36Sopenharmony_ci				NULL);
39162306a36Sopenharmony_ci}
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci/*
39462306a36Sopenharmony_ci * cxl_h_collect_int_info - Collect interrupt info about a coherent
39562306a36Sopenharmony_ci *                          platform function after an interrupt occurred.
39662306a36Sopenharmony_ci */
39762306a36Sopenharmony_cilong cxl_h_collect_int_info(u64 unit_address, u64 process_token,
39862306a36Sopenharmony_ci			    struct cxl_irq_info *info)
39962306a36Sopenharmony_ci{
40062306a36Sopenharmony_ci	long rc;
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ci	BUG_ON(sizeof(*info) != sizeof(unsigned long[PLPAR_HCALL9_BUFSIZE]));
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci	rc = plpar_hcall9(H_COLLECT_CA_INT_INFO, (unsigned long *) info,
40562306a36Sopenharmony_ci			unit_address, process_token);
40662306a36Sopenharmony_ci	_PRINT_MSG(rc, "cxl_h_collect_int_info(%#.16llx, 0x%llx): %li\n",
40762306a36Sopenharmony_ci		unit_address, process_token, rc);
40862306a36Sopenharmony_ci	trace_cxl_hcall_collect_int_info(unit_address, process_token, rc);
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci	switch (rc) {
41162306a36Sopenharmony_ci	case H_SUCCESS:     /* The interrupt info is returned in return registers. */
41262306a36Sopenharmony_ci		pr_devel("dsisr:%#llx, dar:%#llx, dsr:%#llx, pid_tid:%#llx, afu_err:%#llx, errstat:%#llx\n",
41362306a36Sopenharmony_ci			info->dsisr, info->dar, info->dsr, info->reserved,
41462306a36Sopenharmony_ci			info->afu_err, info->errstat);
41562306a36Sopenharmony_ci		return 0;
41662306a36Sopenharmony_ci	case H_PARAMETER:   /* An incorrect parameter was supplied. */
41762306a36Sopenharmony_ci		return -EINVAL;
41862306a36Sopenharmony_ci	case H_AUTHORITY:   /* The partition does not have authority to perform this hcall. */
41962306a36Sopenharmony_ci	case H_HARDWARE:    /* A hardware event prevented the collection of the interrupt info.*/
42062306a36Sopenharmony_ci	case H_STATE:       /* The coherent platform function is not in a valid state to collect interrupt info. */
42162306a36Sopenharmony_ci		return -EBUSY;
42262306a36Sopenharmony_ci	default:
42362306a36Sopenharmony_ci		WARN(1, "Unexpected return code: %lx", rc);
42462306a36Sopenharmony_ci		return -EINVAL;
42562306a36Sopenharmony_ci	}
42662306a36Sopenharmony_ci}
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci/*
42962306a36Sopenharmony_ci * cxl_h_control_faults - Control the operation of a coherent platform
43062306a36Sopenharmony_ci *                        function after a fault occurs.
43162306a36Sopenharmony_ci *
43262306a36Sopenharmony_ci * Parameters
43362306a36Sopenharmony_ci *    control-mask: value to control the faults
43462306a36Sopenharmony_ci *                  looks like PSL_TFC_An shifted >> 32
43562306a36Sopenharmony_ci *    reset-mask: mask to control reset of function faults
43662306a36Sopenharmony_ci *                Set reset_mask = 1 to reset PSL errors
43762306a36Sopenharmony_ci */
43862306a36Sopenharmony_cilong cxl_h_control_faults(u64 unit_address, u64 process_token,
43962306a36Sopenharmony_ci			  u64 control_mask, u64 reset_mask)
44062306a36Sopenharmony_ci{
44162306a36Sopenharmony_ci	unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
44262306a36Sopenharmony_ci	long rc;
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ci	memset(retbuf, 0, sizeof(retbuf));
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_ci	rc = plpar_hcall(H_CONTROL_CA_FAULTS, retbuf, unit_address,
44762306a36Sopenharmony_ci			H_CONTROL_CA_FAULTS_RESPOND_PSL, process_token,
44862306a36Sopenharmony_ci			control_mask, reset_mask);
44962306a36Sopenharmony_ci	_PRINT_MSG(rc, "cxl_h_control_faults(%#.16llx, 0x%llx, %#llx, %#llx): %li (%#lx)\n",
45062306a36Sopenharmony_ci		unit_address, process_token, control_mask, reset_mask,
45162306a36Sopenharmony_ci		rc, retbuf[0]);
45262306a36Sopenharmony_ci	trace_cxl_hcall_control_faults(unit_address, process_token,
45362306a36Sopenharmony_ci				control_mask, reset_mask, retbuf[0], rc);
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_ci	switch (rc) {
45662306a36Sopenharmony_ci	case H_SUCCESS:    /* Faults were successfully controlled for the function. */
45762306a36Sopenharmony_ci		return 0;
45862306a36Sopenharmony_ci	case H_PARAMETER:  /* An incorrect parameter was supplied. */
45962306a36Sopenharmony_ci		return -EINVAL;
46062306a36Sopenharmony_ci	case H_HARDWARE:   /* A hardware event prevented the control of faults. */
46162306a36Sopenharmony_ci	case H_STATE:      /* The function was in an invalid state. */
46262306a36Sopenharmony_ci	case H_AUTHORITY:  /* The partition does not have authority to perform this hcall; the coherent platform facilities may need to be licensed. */
46362306a36Sopenharmony_ci		return -EBUSY;
46462306a36Sopenharmony_ci	case H_FUNCTION:   /* The function is not supported */
46562306a36Sopenharmony_ci	case H_NOT_FOUND:  /* The operation supplied was not valid */
46662306a36Sopenharmony_ci		return -EINVAL;
46762306a36Sopenharmony_ci	default:
46862306a36Sopenharmony_ci		WARN(1, "Unexpected return code: %lx", rc);
46962306a36Sopenharmony_ci		return -EINVAL;
47062306a36Sopenharmony_ci	}
47162306a36Sopenharmony_ci}
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_ci/*
47462306a36Sopenharmony_ci * cxl_h_control_facility - This H_CONTROL_CA_FACILITY hypervisor call
47562306a36Sopenharmony_ci *                          allows the partition to manipulate or query
47662306a36Sopenharmony_ci *                          certain coherent platform facility behaviors.
47762306a36Sopenharmony_ci */
47862306a36Sopenharmony_cistatic long cxl_h_control_facility(u64 unit_address, u64 op,
47962306a36Sopenharmony_ci				   u64 p1, u64 p2, u64 p3, u64 p4, u64 *out)
48062306a36Sopenharmony_ci{
48162306a36Sopenharmony_ci	unsigned long retbuf[PLPAR_HCALL9_BUFSIZE];
48262306a36Sopenharmony_ci	long rc;
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_ci	CXL_H9_WAIT_UNTIL_DONE(rc, retbuf, H_CONTROL_CA_FACILITY, unit_address, op, p1, p2, p3, p4);
48562306a36Sopenharmony_ci	_PRINT_MSG(rc, "cxl_h_control_facility(%#.16llx, %s(%#llx, %#llx, %#llx, %#llx, R4: %#lx)): %li\n",
48662306a36Sopenharmony_ci		unit_address, OP_STR_CONTROL_ADAPTER(op), p1, p2, p3, p4, retbuf[0], rc);
48762306a36Sopenharmony_ci	trace_cxl_hcall_control_facility(unit_address, OP_STR_CONTROL_ADAPTER(op), p1, p2, p3, p4, retbuf[0], rc);
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_ci	switch (rc) {
49062306a36Sopenharmony_ci	case H_SUCCESS:       /* The operation is completed for the coherent platform facility */
49162306a36Sopenharmony_ci		if (op == H_CONTROL_CA_FACILITY_COLLECT_VPD)
49262306a36Sopenharmony_ci			*out = retbuf[0];
49362306a36Sopenharmony_ci		return 0;
49462306a36Sopenharmony_ci	case H_PARAMETER:     /* An incorrect parameter was supplied. */
49562306a36Sopenharmony_ci	case H_FUNCTION:      /* The function is not supported. */
49662306a36Sopenharmony_ci	case H_NOT_FOUND:     /* The operation supplied was not valid */
49762306a36Sopenharmony_ci	case H_NOT_AVAILABLE: /* The operation cannot be performed because the AFU has not been downloaded */
49862306a36Sopenharmony_ci	case H_SG_LIST:       /* An block list entry was invalid */
49962306a36Sopenharmony_ci		return -EINVAL;
50062306a36Sopenharmony_ci	case H_AUTHORITY:     /* The partition does not have authority to perform this hcall */
50162306a36Sopenharmony_ci	case H_RESOURCE:      /* The function has page table mappings for MMIO */
50262306a36Sopenharmony_ci	case H_HARDWARE:      /* A hardware event prevented the attach operation */
50362306a36Sopenharmony_ci	case H_STATE:         /* The coherent platform facility is not in a valid state */
50462306a36Sopenharmony_ci	case H_BUSY:
50562306a36Sopenharmony_ci		return -EBUSY;
50662306a36Sopenharmony_ci	default:
50762306a36Sopenharmony_ci		WARN(1, "Unexpected return code: %lx", rc);
50862306a36Sopenharmony_ci		return -EINVAL;
50962306a36Sopenharmony_ci	}
51062306a36Sopenharmony_ci}
51162306a36Sopenharmony_ci
51262306a36Sopenharmony_ci/*
51362306a36Sopenharmony_ci * cxl_h_reset_adapter - Perform a reset to the coherent platform facility.
51462306a36Sopenharmony_ci */
51562306a36Sopenharmony_cilong cxl_h_reset_adapter(u64 unit_address)
51662306a36Sopenharmony_ci{
51762306a36Sopenharmony_ci	return cxl_h_control_facility(unit_address,
51862306a36Sopenharmony_ci				H_CONTROL_CA_FACILITY_RESET,
51962306a36Sopenharmony_ci				0, 0, 0, 0,
52062306a36Sopenharmony_ci				NULL);
52162306a36Sopenharmony_ci}
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci/*
52462306a36Sopenharmony_ci * cxl_h_collect_vpd - Collect VPD for the coherent platform function.
52562306a36Sopenharmony_ci * Parameter1 = 4K naturally aligned real buffer containing block
52662306a36Sopenharmony_ci *              list entries
52762306a36Sopenharmony_ci * Parameter2 = number of block list entries in the block list, valid
52862306a36Sopenharmony_ci *              values are between 0 and 256
52962306a36Sopenharmony_ci */
53062306a36Sopenharmony_cilong cxl_h_collect_vpd_adapter(u64 unit_address, u64 list_address,
53162306a36Sopenharmony_ci			       u64 num, u64 *out)
53262306a36Sopenharmony_ci{
53362306a36Sopenharmony_ci	return cxl_h_control_facility(unit_address,
53462306a36Sopenharmony_ci				H_CONTROL_CA_FACILITY_COLLECT_VPD,
53562306a36Sopenharmony_ci				list_address, num, 0, 0,
53662306a36Sopenharmony_ci				out);
53762306a36Sopenharmony_ci}
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci/*
54062306a36Sopenharmony_ci * cxl_h_download_facility - This H_DOWNLOAD_CA_FACILITY
54162306a36Sopenharmony_ci *                    hypervisor call provide platform support for
54262306a36Sopenharmony_ci *                    downloading a base adapter image to the coherent
54362306a36Sopenharmony_ci *                    platform facility, and for validating the entire
54462306a36Sopenharmony_ci *                    image after the download.
54562306a36Sopenharmony_ci * Parameters
54662306a36Sopenharmony_ci *    op: operation to perform to the coherent platform function
54762306a36Sopenharmony_ci *      Download: operation = 1, the base image in the coherent platform
54862306a36Sopenharmony_ci *                               facility is first erased, and then
54962306a36Sopenharmony_ci *                               programmed using the image supplied
55062306a36Sopenharmony_ci *                               in the scatter/gather list.
55162306a36Sopenharmony_ci *      Validate: operation = 2, the base image in the coherent platform
55262306a36Sopenharmony_ci *                               facility is compared with the image
55362306a36Sopenharmony_ci *                               supplied in the scatter/gather list.
55462306a36Sopenharmony_ci *    list_address: 4K naturally aligned real buffer containing
55562306a36Sopenharmony_ci *                  scatter/gather list entries.
55662306a36Sopenharmony_ci *    num: number of block list entries in the scatter/gather list.
55762306a36Sopenharmony_ci */
55862306a36Sopenharmony_cistatic long cxl_h_download_facility(u64 unit_address, u64 op,
55962306a36Sopenharmony_ci				    u64 list_address, u64 num,
56062306a36Sopenharmony_ci				    u64 *out)
56162306a36Sopenharmony_ci{
56262306a36Sopenharmony_ci	unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
56362306a36Sopenharmony_ci	unsigned int delay, total_delay = 0;
56462306a36Sopenharmony_ci	u64 token = 0;
56562306a36Sopenharmony_ci	long rc;
56662306a36Sopenharmony_ci
56762306a36Sopenharmony_ci	if (*out != 0)
56862306a36Sopenharmony_ci		token = *out;
56962306a36Sopenharmony_ci
57062306a36Sopenharmony_ci	memset(retbuf, 0, sizeof(retbuf));
57162306a36Sopenharmony_ci	while (1) {
57262306a36Sopenharmony_ci		rc = plpar_hcall(H_DOWNLOAD_CA_FACILITY, retbuf,
57362306a36Sopenharmony_ci				 unit_address, op, list_address, num,
57462306a36Sopenharmony_ci				 token);
57562306a36Sopenharmony_ci		token = retbuf[0];
57662306a36Sopenharmony_ci		if (rc != H_BUSY && !H_IS_LONG_BUSY(rc))
57762306a36Sopenharmony_ci			break;
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_ci		if (rc != H_BUSY) {
58062306a36Sopenharmony_ci			delay = get_longbusy_msecs(rc);
58162306a36Sopenharmony_ci			total_delay += delay;
58262306a36Sopenharmony_ci			if (total_delay > CXL_HCALL_TIMEOUT_DOWNLOAD) {
58362306a36Sopenharmony_ci				WARN(1, "Warning: Giving up waiting for CXL hcall "
58462306a36Sopenharmony_ci					"%#x after %u msec\n",
58562306a36Sopenharmony_ci					H_DOWNLOAD_CA_FACILITY, total_delay);
58662306a36Sopenharmony_ci				rc = H_BUSY;
58762306a36Sopenharmony_ci				break;
58862306a36Sopenharmony_ci			}
58962306a36Sopenharmony_ci			msleep(delay);
59062306a36Sopenharmony_ci		}
59162306a36Sopenharmony_ci	}
59262306a36Sopenharmony_ci	_PRINT_MSG(rc, "cxl_h_download_facility(%#.16llx, %s(%#llx, %#llx), %#lx): %li\n",
59362306a36Sopenharmony_ci		 unit_address, OP_STR_DOWNLOAD_ADAPTER(op), list_address, num, retbuf[0], rc);
59462306a36Sopenharmony_ci	trace_cxl_hcall_download_facility(unit_address, OP_STR_DOWNLOAD_ADAPTER(op), list_address, num, retbuf[0], rc);
59562306a36Sopenharmony_ci
59662306a36Sopenharmony_ci	switch (rc) {
59762306a36Sopenharmony_ci	case H_SUCCESS:       /* The operation is completed for the coherent platform facility */
59862306a36Sopenharmony_ci		return 0;
59962306a36Sopenharmony_ci	case H_PARAMETER:     /* An incorrect parameter was supplied */
60062306a36Sopenharmony_ci	case H_FUNCTION:      /* The function is not supported. */
60162306a36Sopenharmony_ci	case H_SG_LIST:       /* An block list entry was invalid */
60262306a36Sopenharmony_ci	case H_BAD_DATA:      /* Image verification failed */
60362306a36Sopenharmony_ci		return -EINVAL;
60462306a36Sopenharmony_ci	case H_AUTHORITY:     /* The partition does not have authority to perform this hcall */
60562306a36Sopenharmony_ci	case H_RESOURCE:      /* The function has page table mappings for MMIO */
60662306a36Sopenharmony_ci	case H_HARDWARE:      /* A hardware event prevented the attach operation */
60762306a36Sopenharmony_ci	case H_STATE:         /* The coherent platform facility is not in a valid state */
60862306a36Sopenharmony_ci	case H_BUSY:
60962306a36Sopenharmony_ci		return -EBUSY;
61062306a36Sopenharmony_ci	case H_CONTINUE:
61162306a36Sopenharmony_ci		*out = retbuf[0];
61262306a36Sopenharmony_ci		return 1;  /* More data is needed for the complete image */
61362306a36Sopenharmony_ci	default:
61462306a36Sopenharmony_ci		WARN(1, "Unexpected return code: %lx", rc);
61562306a36Sopenharmony_ci		return -EINVAL;
61662306a36Sopenharmony_ci	}
61762306a36Sopenharmony_ci}
61862306a36Sopenharmony_ci
61962306a36Sopenharmony_ci/*
62062306a36Sopenharmony_ci * cxl_h_download_adapter_image - Download the base image to the coherent
62162306a36Sopenharmony_ci *                                platform facility.
62262306a36Sopenharmony_ci */
62362306a36Sopenharmony_cilong cxl_h_download_adapter_image(u64 unit_address,
62462306a36Sopenharmony_ci				  u64 list_address, u64 num,
62562306a36Sopenharmony_ci				  u64 *out)
62662306a36Sopenharmony_ci{
62762306a36Sopenharmony_ci	return cxl_h_download_facility(unit_address,
62862306a36Sopenharmony_ci				       H_DOWNLOAD_CA_FACILITY_DOWNLOAD,
62962306a36Sopenharmony_ci				       list_address, num, out);
63062306a36Sopenharmony_ci}
63162306a36Sopenharmony_ci
63262306a36Sopenharmony_ci/*
63362306a36Sopenharmony_ci * cxl_h_validate_adapter_image - Validate the base image in the coherent
63462306a36Sopenharmony_ci *                                platform facility.
63562306a36Sopenharmony_ci */
63662306a36Sopenharmony_cilong cxl_h_validate_adapter_image(u64 unit_address,
63762306a36Sopenharmony_ci				  u64 list_address, u64 num,
63862306a36Sopenharmony_ci				  u64 *out)
63962306a36Sopenharmony_ci{
64062306a36Sopenharmony_ci	return cxl_h_download_facility(unit_address,
64162306a36Sopenharmony_ci				       H_DOWNLOAD_CA_FACILITY_VALIDATE,
64262306a36Sopenharmony_ci				       list_address, num, out);
64362306a36Sopenharmony_ci}
644