cregit-Linux how code gets into the kernel

Release 4.7 drivers/misc/cxl/hcalls.c

Directory: drivers/misc/cxl
/*
 * Copyright 2015 IBM Corp.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 */


#include <linux/compiler.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <asm/byteorder.h>
#include "hcalls.h"
#include "trace.h"


#define CXL_HCALL_TIMEOUT 60000

#define CXL_HCALL_TIMEOUT_DOWNLOAD 120000


#define H_ATTACH_CA_PROCESS    0x344

#define H_CONTROL_CA_FUNCTION  0x348

#define H_DETACH_CA_PROCESS    0x34C

#define H_COLLECT_CA_INT_INFO  0x350

#define H_CONTROL_CA_FAULTS    0x354

#define H_DOWNLOAD_CA_FUNCTION 0x35C

#define H_DOWNLOAD_CA_FACILITY 0x364

#define H_CONTROL_CA_FACILITY  0x368


#define H_CONTROL_CA_FUNCTION_RESET                   1 
/* perform a reset */

#define H_CONTROL_CA_FUNCTION_SUSPEND_PROCESS         2 
/* suspend a process from being executed */

#define H_CONTROL_CA_FUNCTION_RESUME_PROCESS          3 
/* resume a process to be executed */

#define H_CONTROL_CA_FUNCTION_READ_ERR_STATE          4 
/* read the error state */

#define H_CONTROL_CA_FUNCTION_GET_AFU_ERR             5 
/* collect the AFU error buffer */

#define H_CONTROL_CA_FUNCTION_GET_CONFIG              6 
/* collect configuration record */

#define H_CONTROL_CA_FUNCTION_GET_DOWNLOAD_STATE      7 
/* query to return download status */

#define H_CONTROL_CA_FUNCTION_TERMINATE_PROCESS       8 
/* terminate the process before completion */

#define H_CONTROL_CA_FUNCTION_COLLECT_VPD             9 
/* collect VPD */

#define H_CONTROL_CA_FUNCTION_GET_FUNCTION_ERR_INT   11 
/* read the function-wide error data based on an interrupt */

#define H_CONTROL_CA_FUNCTION_ACK_FUNCTION_ERR_INT   12 
/* acknowledge function-wide error data based on an interrupt */

#define H_CONTROL_CA_FUNCTION_GET_ERROR_LOG          13 
/* retrieve the Platform Log ID (PLID) of an error log */


#define H_CONTROL_CA_FAULTS_RESPOND_PSL         1

#define H_CONTROL_CA_FAULTS_RESPOND_AFU         2


#define H_CONTROL_CA_FACILITY_RESET             1 
/* perform a reset */

#define H_CONTROL_CA_FACILITY_COLLECT_VPD       2 
/* collect VPD */


#define H_DOWNLOAD_CA_FACILITY_DOWNLOAD         1 
/* download adapter image */

#define H_DOWNLOAD_CA_FACILITY_VALIDATE         2 
/* validate adapter image */



#define _CXL_LOOP_HCALL(call, rc, retbuf, fn, ...)			\
	{                                                               \
                unsigned int delay, total_delay = 0;                    \
                u64 token = 0;                                          \
                                                                        \
                memset(retbuf, 0, sizeof(retbuf));                      \
                while (1) {                                             \
                        rc = call(fn, retbuf, __VA_ARGS__, token);      \
                        token = retbuf[0];                              \
                        if (rc != H_BUSY && !H_IS_LONG_BUSY(rc))        \
                                break;                                  \
                                                                        \
                        if (rc == H_BUSY)                               \
                                delay = 10;                             \
                        else                                            \
                                delay = get_longbusy_msecs(rc);         \
                                                                        \
                        total_delay += delay;                           \
                        if (total_delay > CXL_HCALL_TIMEOUT) {          \
                                WARN(1, "Warning: Giving up waiting for CXL hcall " \
                                        "%#x after %u msec\n", fn, total_delay); \
                                rc = H_BUSY;                            \
                                break;                                  \
                        }                                               \
                        msleep(delay);                                  \
                }                                                       \
        }

#define CXL_H_WAIT_UNTIL_DONE(...)  _CXL_LOOP_HCALL(plpar_hcall, __VA_ARGS__)

#define CXL_H9_WAIT_UNTIL_DONE(...) _CXL_LOOP_HCALL(plpar_hcall9, __VA_ARGS__)


#define _PRINT_MSG(rc, format, ...)					\
	{                                                               \
                if ((rc != H_SUCCESS) && (rc != H_CONTINUE))            \
                        pr_err(format, __VA_ARGS__);                    \
                else                                                    \
                        pr_devel(format, __VA_ARGS__);                  \
        }                                                               \


static char *afu_op_names[] = {
	"UNKNOWN_OP",		/* 0 undefined */
	"RESET",		/* 1 */
	"SUSPEND_PROCESS",	/* 2 */
	"RESUME_PROCESS",	/* 3 */
	"READ_ERR_STATE",	/* 4 */
	"GET_AFU_ERR",		/* 5 */
	"GET_CONFIG",		/* 6 */
	"GET_DOWNLOAD_STATE",	/* 7 */
	"TERMINATE_PROCESS",	/* 8 */
	"COLLECT_VPD",		/* 9 */
	"UNKNOWN_OP",		/* 10 undefined */
	"GET_FUNCTION_ERR_INT",	/* 11 */
	"ACK_FUNCTION_ERR_INT",	/* 12 */
	"GET_ERROR_LOG",	/* 13 */
};


static char *control_adapter_op_names[] = {
	"UNKNOWN_OP",		/* 0 undefined */
	"RESET",		/* 1 */
	"COLLECT_VPD",		/* 2 */
};


static char *download_op_names[] = {
	"UNKNOWN_OP",		/* 0 undefined */
	"DOWNLOAD",		/* 1 */
	"VALIDATE",		/* 2 */
};


static char *op_str(unsigned int op, char *name_array[], int array_len) { if (op >= array_len) return "UNKNOWN_OP"; return name_array[op]; }

Contributors

PersonTokensPropCommitsCommitProp
christophe lombardchristophe lombard34100.00%1100.00%
Total34100.00%1100.00%

#define OP_STR(op, name_array) op_str(op, name_array, ARRAY_SIZE(name_array)) #define OP_STR_AFU(op) OP_STR(op, afu_op_names) #define OP_STR_CONTROL_ADAPTER(op) OP_STR(op, control_adapter_op_names) #define OP_STR_DOWNLOAD_ADAPTER(op) OP_STR(op, download_op_names)
long cxl_h_attach_process(u64 unit_address, struct cxl_process_element_hcall *element, u64 *process_token, u64 *mmio_addr, u64 *mmio_size) { unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; long rc; CXL_H_WAIT_UNTIL_DONE(rc, retbuf, H_ATTACH_CA_PROCESS, unit_address, virt_to_phys(element)); _PRINT_MSG(rc, "cxl_h_attach_process(%#.16llx, %#.16lx): %li\n", unit_address, virt_to_phys(element), rc); trace_cxl_hcall_attach(unit_address, virt_to_phys(element), retbuf[0], retbuf[1], retbuf[2], rc); pr_devel("token: 0x%.8lx mmio_addr: 0x%lx mmio_size: 0x%lx\nProcess Element Structure:\n", retbuf[0], retbuf[1], retbuf[2]); cxl_dump_debug_buffer(element, sizeof(*element)); switch (rc) { case H_SUCCESS: /* The process info is attached to the coherent platform function */ *process_token = retbuf[0]; if (mmio_addr) *mmio_addr = retbuf[1]; if (mmio_size) *mmio_size = retbuf[2]; return 0; case H_PARAMETER: /* An incorrect parameter was supplied. */ case H_FUNCTION: /* The function is not supported. */ return -EINVAL; case H_AUTHORITY: /* The partition does not have authority to perform this hcall */ case H_RESOURCE: /* The coherent platform function does not have enough additional resource to attach the process */ case H_HARDWARE: /* A hardware event prevented the attach operation */ case H_STATE: /* The coherent platform function is not in a valid state */ case H_BUSY: return -EBUSY; default: WARN(1, "Unexpected return code: %lx", rc); return -EINVAL; } }

Contributors

PersonTokensPropCommitsCommitProp
christophe lombardchristophe lombard219100.00%2100.00%
Total219100.00%2100.00%

/** * cxl_h_detach_process - Detach a process element from a coherent * platform function. */
long cxl_h_detach_process(u64 unit_address, u64 process_token) { unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; long rc; CXL_H_WAIT_UNTIL_DONE(rc, retbuf, H_DETACH_CA_PROCESS, unit_address, process_token); _PRINT_MSG(rc, "cxl_h_detach_process(%#.16llx, 0x%.8llx): %li\n", unit_address, process_token, rc); trace_cxl_hcall_detach(unit_address, process_token, rc); switch (rc) { case H_SUCCESS: /* The process was detached from the coherent platform function */ return 0; case H_PARAMETER: /* An incorrect parameter was supplied. */ return -EINVAL; case H_AUTHORITY: /* The partition does not have authority to perform this hcall */ case H_RESOURCE: /* The function has page table mappings for MMIO */ case H_HARDWARE: /* A hardware event prevented the detach operation */ case H_STATE: /* The coherent platform function is not in a valid state */ case H_BUSY: return -EBUSY; default: WARN(1, "Unexpected return code: %lx", rc); return -EINVAL; } }

Contributors

PersonTokensPropCommitsCommitProp
christophe lombardchristophe lombard114100.00%2100.00%
Total114100.00%2100.00%

/** * cxl_h_control_function - This H_CONTROL_CA_FUNCTION hypervisor call allows * the partition to manipulate or query * certain coherent platform function behaviors. */
static long cxl_h_control_function(u64 unit_address, u64 op, u64 p1, u64 p2, u64 p3, u64 p4, u64 *out) { unsigned long retbuf[PLPAR_HCALL9_BUFSIZE]; long rc; CXL_H9_WAIT_UNTIL_DONE(rc, retbuf, H_CONTROL_CA_FUNCTION, unit_address, op, p1, p2, p3, p4); _PRINT_MSG(rc, "cxl_h_control_function(%#.16llx, %s(%#llx, %#llx, %#llx, %#llx, R4: %#lx)): %li\n", unit_address, OP_STR_AFU(op), p1, p2, p3, p4, retbuf[0], rc); trace_cxl_hcall_control_function(unit_address, OP_STR_AFU(op), p1, p2, p3, p4, retbuf[0], rc); switch (rc) { case H_SUCCESS: /* The operation is completed for the coherent platform function */ if ((op == H_CONTROL_CA_FUNCTION_GET_FUNCTION_ERR_INT || op == H_CONTROL_CA_FUNCTION_READ_ERR_STATE || op == H_CONTROL_CA_FUNCTION_COLLECT_VPD)) *out = retbuf[0]; return 0; case H_PARAMETER: /* An incorrect parameter was supplied. */ case H_FUNCTION: /* The function is not supported. */ case H_NOT_FOUND: /* The operation supplied was not valid */ case H_NOT_AVAILABLE: /* The operation cannot be performed because the AFU has not been downloaded */ case H_SG_LIST: /* An block list entry was invalid */ return -EINVAL; case H_AUTHORITY: /* The partition does not have authority to perform this hcall */ case H_RESOURCE: /* The function has page table mappings for MMIO */ case H_HARDWARE: /* A hardware event prevented the attach operation */ case H_STATE: /* The coherent platform function is not in a valid state */ case H_BUSY: return -EBUSY; default: WARN(1, "Unexpected return code: %lx", rc); return -EINVAL; } }

Contributors

PersonTokensPropCommitsCommitProp
christophe lombardchristophe lombard211100.00%2100.00%
Total211100.00%2100.00%

/** * cxl_h_reset_afu - Perform a reset to the coherent platform function. */
long cxl_h_reset_afu(u64 unit_address) { return cxl_h_control_function(unit_address, H_CONTROL_CA_FUNCTION_RESET, 0, 0, 0, 0, NULL); }

Contributors

PersonTokensPropCommitsCommitProp
christophe lombardchristophe lombard26100.00%1100.00%
Total26100.00%1100.00%

/** * cxl_h_suspend_process - Suspend a process from being executed * Parameter1 = process-token as returned from H_ATTACH_CA_PROCESS when * process was attached. */
long cxl_h_suspend_process(u64 unit_address, u64 process_token) { return cxl_h_control_function(unit_address, H_CONTROL_CA_FUNCTION_SUSPEND_PROCESS, process_token, 0, 0, 0, NULL); }

Contributors

PersonTokensPropCommitsCommitProp
christophe lombardchristophe lombard29100.00%1100.00%
Total29100.00%1100.00%

/** * cxl_h_resume_process - Resume a process to be executed * Parameter1 = process-token as returned from H_ATTACH_CA_PROCESS when * process was attached. */
long cxl_h_resume_process(u64 unit_address, u64 process_token) { return cxl_h_control_function(unit_address, H_CONTROL_CA_FUNCTION_RESUME_PROCESS, process_token, 0, 0, 0, NULL); }

Contributors

PersonTokensPropCommitsCommitProp
christophe lombardchristophe lombard29100.00%1100.00%
Total29100.00%1100.00%

/** * cxl_h_read_error_state - Checks the error state of the coherent * platform function. * R4 contains the error state */
long cxl_h_read_error_state(u64 unit_address, u64 *state) { return cxl_h_control_function(unit_address, H_CONTROL_CA_FUNCTION_READ_ERR_STATE, 0, 0, 0, 0, state); }

Contributors

PersonTokensPropCommitsCommitProp
christophe lombardchristophe lombard30100.00%1100.00%
Total30100.00%1100.00%

/** * cxl_h_get_afu_err - collect the AFU error buffer * Parameter1 = byte offset into error buffer to retrieve, valid values * are between 0 and (ibm,error-buffer-size - 1) * Parameter2 = 4K aligned real address of error buffer, to be filled in * Parameter3 = length of error buffer, valid values are 4K or less */
long cxl_h_get_afu_err(u64 unit_address, u64 offset, u64 buf_address, u64 len) { return cxl_h_control_function(unit_address, H_CONTROL_CA_FUNCTION_GET_AFU_ERR, offset, buf_address, len, 0, NULL); }

Contributors

PersonTokensPropCommitsCommitProp
christophe lombardchristophe lombard35100.00%1100.00%
Total35100.00%1100.00%

/** * cxl_h_get_config - collect configuration record for the * coherent platform function * Parameter1 = # of configuration record to retrieve, valid values are * between 0 and (ibm,#config-records - 1) * Parameter2 = byte offset into configuration record to retrieve, * valid values are between 0 and (ibm,config-record-size - 1) * Parameter3 = 4K aligned real address of configuration record buffer, * to be filled in * Parameter4 = length of configuration buffer, valid values are 4K or less */
long cxl_h_get_config(u64 unit_address, u64 cr_num, u64 offset, u64 buf_address, u64 len) { return cxl_h_control_function(unit_address, H_CONTROL_CA_FUNCTION_GET_CONFIG, cr_num, offset, buf_address, len, NULL); }

Contributors

PersonTokensPropCommitsCommitProp
christophe lombardchristophe lombard38100.00%1100.00%
Total38100.00%1100.00%

/** * cxl_h_terminate_process - Terminate the process before completion * Parameter1 = process-token as returned from H_ATTACH_CA_PROCESS when * process was attached. */
long cxl_h_terminate_process(u64 unit_address, u64 process_token) { return cxl_h_control_function(unit_address, H_CONTROL_CA_FUNCTION_TERMINATE_PROCESS, process_token, 0, 0, 0, NULL); }

Contributors

PersonTokensPropCommitsCommitProp
christophe lombardchristophe lombard29100.00%1100.00%
Total29100.00%1100.00%

/** * cxl_h_collect_vpd - Collect VPD for the coherent platform function. * Parameter1 = # of VPD record to retrieve, valid values are between 0 * and (ibm,#config-records - 1). * Parameter2 = 4K naturally aligned real buffer containing block * list entries * Parameter3 = number of block list entries in the block list, valid * values are between 0 and 256 */
long cxl_h_collect_vpd(u64 unit_address, u64 record, u64 list_address, u64 num, u64 *out) { return cxl_h_control_function(unit_address, H_CONTROL_CA_FUNCTION_COLLECT_VPD, record, list_address, num, 0, out); }

Contributors

PersonTokensPropCommitsCommitProp
christophe lombardchristophe lombard39100.00%1100.00%
Total39100.00%1100.00%

/** * cxl_h_get_fn_error_interrupt - Read the function-wide error data based on an interrupt */
long cxl_h_get_fn_error_interrupt(u64 unit_address, u64 *reg) { return cxl_h_control_function(unit_address, H_CONTROL_CA_FUNCTION_GET_FUNCTION_ERR_INT, 0, 0, 0, 0, reg); }

Contributors

PersonTokensPropCommitsCommitProp
christophe lombardchristophe lombard30100.00%1100.00%
Total30100.00%1100.00%

/** * cxl_h_ack_fn_error_interrupt - Acknowledge function-wide error data * based on an interrupt * Parameter1 = value to write to the function-wide error interrupt register */
long cxl_h_ack_fn_error_interrupt(u64 unit_address, u64 value) { return cxl_h_control_function(unit_address, H_CONTROL_CA_FUNCTION_ACK_FUNCTION_ERR_INT, value, 0, 0, 0, NULL); }

Contributors

PersonTokensPropCommitsCommitProp
christophe lombardchristophe lombard29100.00%1100.00%
Total29100.00%1100.00%

/** * cxl_h_get_error_log - Retrieve the Platform Log ID (PLID) of * an error log */
long cxl_h_get_error_log(u64 unit_address, u64 value) { return cxl_h_control_function(unit_address, H_CONTROL_CA_FUNCTION_GET_ERROR_LOG, 0, 0, 0, 0, NULL); }

Contributors

PersonTokensPropCommitsCommitProp
christophe lombardchristophe lombard29100.00%1100.00%
Total29100.00%1100.00%

/** * cxl_h_collect_int_info - Collect interrupt info about a coherent * platform function after an interrupt occurred. */
long cxl_h_collect_int_info(u64 unit_address, u64 process_token, struct cxl_irq_info *info) { long rc; BUG_ON(sizeof(*info) != sizeof(unsigned long[PLPAR_HCALL9_BUFSIZE])); rc = plpar_hcall9(H_COLLECT_CA_INT_INFO, (unsigned long *) info, unit_address, process_token); _PRINT_MSG(rc, "cxl_h_collect_int_info(%#.16llx, 0x%llx): %li\n", unit_address, process_token, rc); trace_cxl_hcall_collect_int_info(unit_address, process_token, rc); switch (rc) { case H_SUCCESS: /* The interrupt info is returned in return registers. */ pr_devel("dsisr:%#llx, dar:%#llx, dsr:%#llx, pid:%u, tid:%u, afu_err:%#llx, errstat:%#llx\n", info->dsisr, info->dar, info->dsr, info->pid, info->tid, info->afu_err, info->errstat); return 0; case H_PARAMETER: /* An incorrect parameter was supplied. */ return -EINVAL; case H_AUTHORITY: /* The partition does not have authority to perform this hcall. */ case H_HARDWARE: /* A hardware event prevented the collection of the interrupt info.*/ case H_STATE: /* The coherent platform function is not in a valid state to collect interrupt info. */ return -EBUSY; default: WARN(1, "Unexpected return code: %lx", rc); return -EINVAL; } }

Contributors

PersonTokensPropCommitsCommitProp
christophe lombardchristophe lombard161100.00%2100.00%
Total161100.00%2100.00%

/** * cxl_h_control_faults - Control the operation of a coherent platform * function after a fault occurs. * * Parameters * control-mask: value to control the faults * looks like PSL_TFC_An shifted >> 32 * reset-mask: mask to control reset of function faults * Set reset_mask = 1 to reset PSL errors */
long cxl_h_control_faults(u64 unit_address, u64 process_token, u64 control_mask, u64 reset_mask) { unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; long rc; memset(retbuf, 0, sizeof(retbuf)); rc = plpar_hcall(H_CONTROL_CA_FAULTS, retbuf, unit_address, H_CONTROL_CA_FAULTS_RESPOND_PSL, process_token, control_mask, reset_mask); _PRINT_MSG(rc, "cxl_h_control_faults(%#.16llx, 0x%llx, %#llx, %#llx): %li (%#lx)\n", unit_address, process_token, control_mask, reset_mask, rc, retbuf[0]); trace_cxl_hcall_control_faults(unit_address, process_token, control_mask, reset_mask, retbuf[0], rc); switch (rc) { case H_SUCCESS: /* Faults were successfully controlled for the function. */ return 0; case H_PARAMETER: /* An incorrect parameter was supplied. */ return -EINVAL; case H_HARDWARE: /* A hardware event prevented the control of faults. */ case H_STATE: /* The function was in an invalid state. */ case H_AUTHORITY: /* The partition does not have authority to perform this hcall; the coherent platform facilities may need to be licensed. */ return -EBUSY; case H_FUNCTION: /* The function is not supported */ case H_NOT_FOUND: /* The operation supplied was not valid */ return -EINVAL; default: WARN(1, "Unexpected return code: %lx", rc); return -EINVAL; } }

Contributors

PersonTokensPropCommitsCommitProp
christophe lombardchristophe lombard161100.00%2100.00%
Total161100.00%2100.00%

/** * cxl_h_control_facility - This H_CONTROL_CA_FACILITY hypervisor call * allows the partition to manipulate or query * certain coherent platform facility behaviors. */
static long cxl_h_control_facility(u64 unit_address, u64 op, u64 p1, u64 p2, u64 p3, u64 p4, u64 *out) { unsigned long retbuf[PLPAR_HCALL9_BUFSIZE]; long rc; CXL_H9_WAIT_UNTIL_DONE(rc, retbuf, H_CONTROL_CA_FACILITY, unit_address, op, p1, p2, p3, p4); _PRINT_MSG(rc, "cxl_h_control_facility(%#.16llx, %s(%#llx, %#llx, %#llx, %#llx, R4: %#lx)): %li\n", unit_address, OP_STR_CONTROL_ADAPTER(op), p1, p2, p3, p4, retbuf[0], rc); trace_cxl_hcall_control_facility(unit_address, OP_STR_CONTROL_ADAPTER(op), p1, p2, p3, p4, retbuf[0], rc); switch (rc) { case H_SUCCESS: /* The operation is completed for the coherent platform facility */ if (op == H_CONTROL_CA_FACILITY_COLLECT_VPD) *out = retbuf[0]; return 0; case H_PARAMETER: /* An incorrect parameter was supplied. */ case H_FUNCTION: /* The function is not supported. */ case H_NOT_FOUND: /* The operation supplied was not valid */ case H_NOT_AVAILABLE: /* The operation cannot be performed because the AFU has not been downloaded */ case H_SG_LIST: /* An block list entry was invalid */ return -EINVAL; case H_AUTHORITY: /* The partition does not have authority to perform this hcall */ case H_RESOURCE: /* The function has page table mappings for MMIO */ case H_HARDWARE: /* A hardware event prevented the attach operation */ case H_STATE: /* The coherent platform facility is not in a valid state */ case H_BUSY: return -EBUSY; default: WARN(1, "Unexpected return code: %lx", rc); return -EINVAL; } }

Contributors

PersonTokensPropCommitsCommitProp
christophe lombardchristophe lombard201100.00%2100.00%
Total201100.00%2100.00%

/** * cxl_h_reset_adapter - Perform a reset to the coherent platform facility. */
long cxl_h_reset_adapter(u64 unit_address) { return cxl_h_control_facility(unit_address, H_CONTROL_CA_FACILITY_RESET, 0, 0, 0, 0, NULL); }

Contributors

PersonTokensPropCommitsCommitProp
christophe lombardchristophe lombard26100.00%1100.00%
Total26100.00%1100.00%

/** * cxl_h_collect_vpd - Collect VPD for the coherent platform function. * Parameter1 = 4K naturally aligned real buffer containing block * list entries * Parameter2 = number of block list entries in the block list, valid * values are between 0 and 256 */
long cxl_h_collect_vpd_adapter(u64 unit_address, u64 list_address, u64 num, u64 *out) { return cxl_h_control_facility(unit_address, H_CONTROL_CA_FACILITY_COLLECT_VPD, list_address, num, 0, 0, out); }

Contributors

PersonTokensPropCommitsCommitProp
christophe lombardchristophe lombard36100.00%1100.00%
Total36100.00%1100.00%

/** * cxl_h_download_facility - This H_DOWNLOAD_CA_FACILITY * hypervisor call provide platform support for * downloading a base adapter image to the coherent * platform facility, and for validating the entire * image after the download. * Parameters * op: operation to perform to the coherent platform function * Download: operation = 1, the base image in the coherent platform * facility is first erased, and then * programmed using the image supplied * in the scatter/gather list. * Validate: operation = 2, the base image in the coherent platform * facility is compared with the image * supplied in the scatter/gather list. * list_address: 4K naturally aligned real buffer containing * scatter/gather list entries. * num: number of block list entries in the scatter/gather list. */
static long cxl_h_download_facility(u64 unit_address, u64 op, u64 list_address, u64 num, u64 *out) { unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; unsigned int delay, total_delay = 0; u64 token = 0; long rc; if (*out != 0) token = *out; memset(retbuf, 0, sizeof(retbuf)); while (1) { rc = plpar_hcall(H_DOWNLOAD_CA_FACILITY, retbuf, unit_address, op, list_address, num, token); token = retbuf[0]; if (rc != H_BUSY && !H_IS_LONG_BUSY(rc)) break; if (rc != H_BUSY) { delay = get_longbusy_msecs(rc); total_delay += delay; if (total_delay > CXL_HCALL_TIMEOUT_DOWNLOAD) { WARN(1, "Warning: Giving up waiting for CXL hcall " "%#x after %u msec\n", H_DOWNLOAD_CA_FACILITY, total_delay); rc = H_BUSY; break; } msleep(delay); } } _PRINT_MSG(rc, "cxl_h_download_facility(%#.16llx, %s(%#llx, %#llx), %#lx): %li\n", unit_address, OP_STR_DOWNLOAD_ADAPTER(op), list_address, num, retbuf[0], rc); trace_cxl_hcall_download_facility(unit_address, OP_STR_DOWNLOAD_ADAPTER(op), list_address, num, retbuf[0], rc); switch (rc) { case H_SUCCESS: /* The operation is completed for the coherent platform facility */ return 0; case H_PARAMETER: /* An incorrect parameter was supplied */ case H_FUNCTION: /* The function is not supported. */ case H_SG_LIST: /* An block list entry was invalid */ case H_BAD_DATA: /* Image verification failed */ return -EINVAL; case H_AUTHORITY: /* The partition does not have authority to perform this hcall */ case H_RESOURCE: /* The function has page table mappings for MMIO */ case H_HARDWARE: /* A hardware event prevented the attach operation */ case H_STATE: /* The coherent platform facility is not in a valid state */ case H_BUSY: return -EBUSY; case H_CONTINUE: *out = retbuf[0]; return 1; /* More data is needed for the complete image */ default: WARN(1, "Unexpected return code: %lx", rc); return -EINVAL; } }

Contributors

PersonTokensPropCommitsCommitProp
christophe lombardchristophe lombard294100.00%2100.00%
Total294100.00%2100.00%

/** * cxl_h_download_adapter_image - Download the base image to the coherent * platform facility. */
long cxl_h_download_adapter_image(u64 unit_address, u64 list_address, u64 num, u64 *out) { return cxl_h_download_facility(unit_address, H_DOWNLOAD_CA_FACILITY_DOWNLOAD, list_address, num, out); }

Contributors

PersonTokensPropCommitsCommitProp
christophe lombardchristophe lombard32100.00%1100.00%
Total32100.00%1100.00%

/** * cxl_h_validate_adapter_image - Validate the base image in the coherent * platform facility. */
long cxl_h_validate_adapter_image(u64 unit_address, u64 list_address, u64 num, u64 *out) { return cxl_h_download_facility(unit_address, H_DOWNLOAD_CA_FACILITY_VALIDATE, list_address, num, out); }

Contributors

PersonTokensPropCommitsCommitProp
christophe lombardchristophe lombard32100.00%1100.00%
Total32100.00%1100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
christophe lombardchristophe lombard2183100.00%2100.00%
Total2183100.00%2100.00%
Directory: drivers/misc/cxl
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}