1*444c4ba4SChristophe Lombard /* 2*444c4ba4SChristophe Lombard * Copyright 2015 IBM Corp. 3*444c4ba4SChristophe Lombard * 4*444c4ba4SChristophe Lombard * This program is free software; you can redistribute it and/or 5*444c4ba4SChristophe Lombard * modify it under the terms of the GNU General Public License 6*444c4ba4SChristophe Lombard * as published by the Free Software Foundation; either version 7*444c4ba4SChristophe Lombard * 2 of the License, or (at your option) any later version. 8*444c4ba4SChristophe Lombard */ 9*444c4ba4SChristophe Lombard 10*444c4ba4SChristophe Lombard 11*444c4ba4SChristophe Lombard #include <linux/compiler.h> 12*444c4ba4SChristophe Lombard #include <linux/types.h> 13*444c4ba4SChristophe Lombard #include <linux/delay.h> 14*444c4ba4SChristophe Lombard #include <asm/hvcall.h> 15*444c4ba4SChristophe Lombard #include <asm/byteorder.h> 16*444c4ba4SChristophe Lombard #include "hcalls.h" 17*444c4ba4SChristophe Lombard 18*444c4ba4SChristophe Lombard #define CXL_HCALL_TIMEOUT 60000 19*444c4ba4SChristophe Lombard #define CXL_HCALL_TIMEOUT_DOWNLOAD 120000 20*444c4ba4SChristophe Lombard 21*444c4ba4SChristophe Lombard #define H_ATTACH_CA_PROCESS 0x344 22*444c4ba4SChristophe Lombard #define H_CONTROL_CA_FUNCTION 0x348 23*444c4ba4SChristophe Lombard #define H_DETACH_CA_PROCESS 0x34C 24*444c4ba4SChristophe Lombard #define H_COLLECT_CA_INT_INFO 0x350 25*444c4ba4SChristophe Lombard #define H_CONTROL_CA_FAULTS 0x354 26*444c4ba4SChristophe Lombard #define H_DOWNLOAD_CA_FUNCTION 0x35C 27*444c4ba4SChristophe Lombard #define H_DOWNLOAD_CA_FACILITY 0x364 28*444c4ba4SChristophe Lombard #define H_CONTROL_CA_FACILITY 0x368 29*444c4ba4SChristophe Lombard 30*444c4ba4SChristophe Lombard #define H_CONTROL_CA_FUNCTION_RESET 1 /* perform a reset */ 31*444c4ba4SChristophe Lombard #define H_CONTROL_CA_FUNCTION_SUSPEND_PROCESS 2 /* suspend a process from being executed */ 32*444c4ba4SChristophe Lombard #define H_CONTROL_CA_FUNCTION_RESUME_PROCESS 3 /* resume a process to be executed */ 33*444c4ba4SChristophe Lombard #define H_CONTROL_CA_FUNCTION_READ_ERR_STATE 4 /* read the error state */ 34*444c4ba4SChristophe Lombard #define H_CONTROL_CA_FUNCTION_GET_AFU_ERR 5 /* collect the AFU error buffer */ 35*444c4ba4SChristophe Lombard #define H_CONTROL_CA_FUNCTION_GET_CONFIG 6 /* collect configuration record */ 36*444c4ba4SChristophe Lombard #define H_CONTROL_CA_FUNCTION_GET_DOWNLOAD_STATE 7 /* query to return download status */ 37*444c4ba4SChristophe Lombard #define H_CONTROL_CA_FUNCTION_TERMINATE_PROCESS 8 /* terminate the process before completion */ 38*444c4ba4SChristophe Lombard #define H_CONTROL_CA_FUNCTION_COLLECT_VPD 9 /* collect VPD */ 39*444c4ba4SChristophe Lombard #define H_CONTROL_CA_FUNCTION_GET_FUNCTION_ERR_INT 11 /* read the function-wide error data based on an interrupt */ 40*444c4ba4SChristophe Lombard #define H_CONTROL_CA_FUNCTION_ACK_FUNCTION_ERR_INT 12 /* acknowledge function-wide error data based on an interrupt */ 41*444c4ba4SChristophe Lombard #define H_CONTROL_CA_FUNCTION_GET_ERROR_LOG 13 /* retrieve the Platform Log ID (PLID) of an error log */ 42*444c4ba4SChristophe Lombard 43*444c4ba4SChristophe Lombard #define H_CONTROL_CA_FAULTS_RESPOND_PSL 1 44*444c4ba4SChristophe Lombard #define H_CONTROL_CA_FAULTS_RESPOND_AFU 2 45*444c4ba4SChristophe Lombard 46*444c4ba4SChristophe Lombard #define H_CONTROL_CA_FACILITY_RESET 1 /* perform a reset */ 47*444c4ba4SChristophe Lombard #define H_CONTROL_CA_FACILITY_COLLECT_VPD 2 /* collect VPD */ 48*444c4ba4SChristophe Lombard 49*444c4ba4SChristophe Lombard #define H_DOWNLOAD_CA_FACILITY_DOWNLOAD 1 /* download adapter image */ 50*444c4ba4SChristophe Lombard #define H_DOWNLOAD_CA_FACILITY_VALIDATE 2 /* validate adapter image */ 51*444c4ba4SChristophe Lombard 52*444c4ba4SChristophe Lombard 53*444c4ba4SChristophe Lombard #define _CXL_LOOP_HCALL(call, rc, retbuf, fn, ...) \ 54*444c4ba4SChristophe Lombard { \ 55*444c4ba4SChristophe Lombard unsigned int delay, total_delay = 0; \ 56*444c4ba4SChristophe Lombard u64 token = 0; \ 57*444c4ba4SChristophe Lombard \ 58*444c4ba4SChristophe Lombard memset(retbuf, 0, sizeof(retbuf)); \ 59*444c4ba4SChristophe Lombard while (1) { \ 60*444c4ba4SChristophe Lombard rc = call(fn, retbuf, __VA_ARGS__, token); \ 61*444c4ba4SChristophe Lombard token = retbuf[0]; \ 62*444c4ba4SChristophe Lombard if (rc != H_BUSY && !H_IS_LONG_BUSY(rc)) \ 63*444c4ba4SChristophe Lombard break; \ 64*444c4ba4SChristophe Lombard \ 65*444c4ba4SChristophe Lombard if (rc == H_BUSY) \ 66*444c4ba4SChristophe Lombard delay = 10; \ 67*444c4ba4SChristophe Lombard else \ 68*444c4ba4SChristophe Lombard delay = get_longbusy_msecs(rc); \ 69*444c4ba4SChristophe Lombard \ 70*444c4ba4SChristophe Lombard total_delay += delay; \ 71*444c4ba4SChristophe Lombard if (total_delay > CXL_HCALL_TIMEOUT) { \ 72*444c4ba4SChristophe Lombard WARN(1, "Warning: Giving up waiting for CXL hcall " \ 73*444c4ba4SChristophe Lombard "%#x after %u msec\n", fn, total_delay); \ 74*444c4ba4SChristophe Lombard rc = H_BUSY; \ 75*444c4ba4SChristophe Lombard break; \ 76*444c4ba4SChristophe Lombard } \ 77*444c4ba4SChristophe Lombard msleep(delay); \ 78*444c4ba4SChristophe Lombard } \ 79*444c4ba4SChristophe Lombard } 80*444c4ba4SChristophe Lombard #define CXL_H_WAIT_UNTIL_DONE(...) _CXL_LOOP_HCALL(plpar_hcall, __VA_ARGS__) 81*444c4ba4SChristophe Lombard #define CXL_H9_WAIT_UNTIL_DONE(...) _CXL_LOOP_HCALL(plpar_hcall9, __VA_ARGS__) 82*444c4ba4SChristophe Lombard 83*444c4ba4SChristophe Lombard #define _PRINT_MSG(rc, format, ...) \ 84*444c4ba4SChristophe Lombard { \ 85*444c4ba4SChristophe Lombard if ((rc != H_SUCCESS) && (rc != H_CONTINUE)) \ 86*444c4ba4SChristophe Lombard pr_err(format, __VA_ARGS__); \ 87*444c4ba4SChristophe Lombard else \ 88*444c4ba4SChristophe Lombard pr_devel(format, __VA_ARGS__); \ 89*444c4ba4SChristophe Lombard } \ 90*444c4ba4SChristophe Lombard 91*444c4ba4SChristophe Lombard 92*444c4ba4SChristophe Lombard static char *afu_op_names[] = { 93*444c4ba4SChristophe Lombard "UNKNOWN_OP", /* 0 undefined */ 94*444c4ba4SChristophe Lombard "RESET", /* 1 */ 95*444c4ba4SChristophe Lombard "SUSPEND_PROCESS", /* 2 */ 96*444c4ba4SChristophe Lombard "RESUME_PROCESS", /* 3 */ 97*444c4ba4SChristophe Lombard "READ_ERR_STATE", /* 4 */ 98*444c4ba4SChristophe Lombard "GET_AFU_ERR", /* 5 */ 99*444c4ba4SChristophe Lombard "GET_CONFIG", /* 6 */ 100*444c4ba4SChristophe Lombard "GET_DOWNLOAD_STATE", /* 7 */ 101*444c4ba4SChristophe Lombard "TERMINATE_PROCESS", /* 8 */ 102*444c4ba4SChristophe Lombard "COLLECT_VPD", /* 9 */ 103*444c4ba4SChristophe Lombard "UNKNOWN_OP", /* 10 undefined */ 104*444c4ba4SChristophe Lombard "GET_FUNCTION_ERR_INT", /* 11 */ 105*444c4ba4SChristophe Lombard "ACK_FUNCTION_ERR_INT", /* 12 */ 106*444c4ba4SChristophe Lombard "GET_ERROR_LOG", /* 13 */ 107*444c4ba4SChristophe Lombard }; 108*444c4ba4SChristophe Lombard 109*444c4ba4SChristophe Lombard static char *control_adapter_op_names[] = { 110*444c4ba4SChristophe Lombard "UNKNOWN_OP", /* 0 undefined */ 111*444c4ba4SChristophe Lombard "RESET", /* 1 */ 112*444c4ba4SChristophe Lombard "COLLECT_VPD", /* 2 */ 113*444c4ba4SChristophe Lombard }; 114*444c4ba4SChristophe Lombard 115*444c4ba4SChristophe Lombard static char *download_op_names[] = { 116*444c4ba4SChristophe Lombard "UNKNOWN_OP", /* 0 undefined */ 117*444c4ba4SChristophe Lombard "DOWNLOAD", /* 1 */ 118*444c4ba4SChristophe Lombard "VALIDATE", /* 2 */ 119*444c4ba4SChristophe Lombard }; 120*444c4ba4SChristophe Lombard 121*444c4ba4SChristophe Lombard static char *op_str(unsigned int op, char *name_array[], int array_len) 122*444c4ba4SChristophe Lombard { 123*444c4ba4SChristophe Lombard if (op >= array_len) 124*444c4ba4SChristophe Lombard return "UNKNOWN_OP"; 125*444c4ba4SChristophe Lombard return name_array[op]; 126*444c4ba4SChristophe Lombard } 127*444c4ba4SChristophe Lombard 128*444c4ba4SChristophe Lombard #define OP_STR(op, name_array) op_str(op, name_array, ARRAY_SIZE(name_array)) 129*444c4ba4SChristophe Lombard 130*444c4ba4SChristophe Lombard #define OP_STR_AFU(op) OP_STR(op, afu_op_names) 131*444c4ba4SChristophe Lombard #define OP_STR_CONTROL_ADAPTER(op) OP_STR(op, control_adapter_op_names) 132*444c4ba4SChristophe Lombard #define OP_STR_DOWNLOAD_ADAPTER(op) OP_STR(op, download_op_names) 133*444c4ba4SChristophe Lombard 134*444c4ba4SChristophe Lombard 135*444c4ba4SChristophe Lombard long cxl_h_attach_process(u64 unit_address, 136*444c4ba4SChristophe Lombard struct cxl_process_element_hcall *element, 137*444c4ba4SChristophe Lombard u64 *process_token, u64 *mmio_addr, u64 *mmio_size) 138*444c4ba4SChristophe Lombard { 139*444c4ba4SChristophe Lombard unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; 140*444c4ba4SChristophe Lombard long rc; 141*444c4ba4SChristophe Lombard 142*444c4ba4SChristophe Lombard CXL_H_WAIT_UNTIL_DONE(rc, retbuf, H_ATTACH_CA_PROCESS, unit_address, virt_to_phys(element)); 143*444c4ba4SChristophe Lombard _PRINT_MSG(rc, "cxl_h_attach_process(%#.16llx, %#.16lx): %li\n", 144*444c4ba4SChristophe Lombard unit_address, virt_to_phys(element), rc); 145*444c4ba4SChristophe Lombard 146*444c4ba4SChristophe Lombard pr_devel("token: 0x%.8lx mmio_addr: 0x%lx mmio_size: 0x%lx\nProcess Element Structure:\n", 147*444c4ba4SChristophe Lombard retbuf[0], retbuf[1], retbuf[2]); 148*444c4ba4SChristophe Lombard cxl_dump_debug_buffer(element, sizeof(*element)); 149*444c4ba4SChristophe Lombard 150*444c4ba4SChristophe Lombard switch (rc) { 151*444c4ba4SChristophe Lombard case H_SUCCESS: /* The process info is attached to the coherent platform function */ 152*444c4ba4SChristophe Lombard *process_token = retbuf[0]; 153*444c4ba4SChristophe Lombard if (mmio_addr) 154*444c4ba4SChristophe Lombard *mmio_addr = retbuf[1]; 155*444c4ba4SChristophe Lombard if (mmio_size) 156*444c4ba4SChristophe Lombard *mmio_size = retbuf[2]; 157*444c4ba4SChristophe Lombard return 0; 158*444c4ba4SChristophe Lombard case H_PARAMETER: /* An incorrect parameter was supplied. */ 159*444c4ba4SChristophe Lombard case H_FUNCTION: /* The function is not supported. */ 160*444c4ba4SChristophe Lombard return -EINVAL; 161*444c4ba4SChristophe Lombard case H_AUTHORITY: /* The partition does not have authority to perform this hcall */ 162*444c4ba4SChristophe Lombard case H_RESOURCE: /* The coherent platform function does not have enough additional resource to attach the process */ 163*444c4ba4SChristophe Lombard case H_HARDWARE: /* A hardware event prevented the attach operation */ 164*444c4ba4SChristophe Lombard case H_STATE: /* The coherent platform function is not in a valid state */ 165*444c4ba4SChristophe Lombard case H_BUSY: 166*444c4ba4SChristophe Lombard return -EBUSY; 167*444c4ba4SChristophe Lombard default: 168*444c4ba4SChristophe Lombard WARN(1, "Unexpected return code: %lx", rc); 169*444c4ba4SChristophe Lombard return -EINVAL; 170*444c4ba4SChristophe Lombard } 171*444c4ba4SChristophe Lombard } 172*444c4ba4SChristophe Lombard 173*444c4ba4SChristophe Lombard /** 174*444c4ba4SChristophe Lombard * cxl_h_detach_process - Detach a process element from a coherent 175*444c4ba4SChristophe Lombard * platform function. 176*444c4ba4SChristophe Lombard */ 177*444c4ba4SChristophe Lombard long cxl_h_detach_process(u64 unit_address, u64 process_token) 178*444c4ba4SChristophe Lombard { 179*444c4ba4SChristophe Lombard unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; 180*444c4ba4SChristophe Lombard long rc; 181*444c4ba4SChristophe Lombard 182*444c4ba4SChristophe Lombard CXL_H_WAIT_UNTIL_DONE(rc, retbuf, H_DETACH_CA_PROCESS, unit_address, process_token); 183*444c4ba4SChristophe Lombard _PRINT_MSG(rc, "cxl_h_detach_process(%#.16llx, 0x%.8llx): %li\n", unit_address, process_token, rc); 184*444c4ba4SChristophe Lombard 185*444c4ba4SChristophe Lombard switch (rc) { 186*444c4ba4SChristophe Lombard case H_SUCCESS: /* The process was detached from the coherent platform function */ 187*444c4ba4SChristophe Lombard return 0; 188*444c4ba4SChristophe Lombard case H_PARAMETER: /* An incorrect parameter was supplied. */ 189*444c4ba4SChristophe Lombard return -EINVAL; 190*444c4ba4SChristophe Lombard case H_AUTHORITY: /* The partition does not have authority to perform this hcall */ 191*444c4ba4SChristophe Lombard case H_RESOURCE: /* The function has page table mappings for MMIO */ 192*444c4ba4SChristophe Lombard case H_HARDWARE: /* A hardware event prevented the detach operation */ 193*444c4ba4SChristophe Lombard case H_STATE: /* The coherent platform function is not in a valid state */ 194*444c4ba4SChristophe Lombard case H_BUSY: 195*444c4ba4SChristophe Lombard return -EBUSY; 196*444c4ba4SChristophe Lombard default: 197*444c4ba4SChristophe Lombard WARN(1, "Unexpected return code: %lx", rc); 198*444c4ba4SChristophe Lombard return -EINVAL; 199*444c4ba4SChristophe Lombard } 200*444c4ba4SChristophe Lombard } 201*444c4ba4SChristophe Lombard 202*444c4ba4SChristophe Lombard /** 203*444c4ba4SChristophe Lombard * cxl_h_control_function - This H_CONTROL_CA_FUNCTION hypervisor call allows 204*444c4ba4SChristophe Lombard * the partition to manipulate or query 205*444c4ba4SChristophe Lombard * certain coherent platform function behaviors. 206*444c4ba4SChristophe Lombard */ 207*444c4ba4SChristophe Lombard static long cxl_h_control_function(u64 unit_address, u64 op, 208*444c4ba4SChristophe Lombard u64 p1, u64 p2, u64 p3, u64 p4, u64 *out) 209*444c4ba4SChristophe Lombard { 210*444c4ba4SChristophe Lombard unsigned long retbuf[PLPAR_HCALL9_BUFSIZE]; 211*444c4ba4SChristophe Lombard long rc; 212*444c4ba4SChristophe Lombard 213*444c4ba4SChristophe Lombard CXL_H9_WAIT_UNTIL_DONE(rc, retbuf, H_CONTROL_CA_FUNCTION, unit_address, op, p1, p2, p3, p4); 214*444c4ba4SChristophe Lombard _PRINT_MSG(rc, "cxl_h_control_function(%#.16llx, %s(%#llx, %#llx, %#llx, %#llx, R4: %#lx)): %li\n", 215*444c4ba4SChristophe Lombard unit_address, OP_STR_AFU(op), p1, p2, p3, p4, retbuf[0], rc); 216*444c4ba4SChristophe Lombard 217*444c4ba4SChristophe Lombard switch (rc) { 218*444c4ba4SChristophe Lombard case H_SUCCESS: /* The operation is completed for the coherent platform function */ 219*444c4ba4SChristophe Lombard if ((op == H_CONTROL_CA_FUNCTION_GET_FUNCTION_ERR_INT || 220*444c4ba4SChristophe Lombard op == H_CONTROL_CA_FUNCTION_READ_ERR_STATE || 221*444c4ba4SChristophe Lombard op == H_CONTROL_CA_FUNCTION_COLLECT_VPD)) 222*444c4ba4SChristophe Lombard *out = retbuf[0]; 223*444c4ba4SChristophe Lombard return 0; 224*444c4ba4SChristophe Lombard case H_PARAMETER: /* An incorrect parameter was supplied. */ 225*444c4ba4SChristophe Lombard case H_FUNCTION: /* The function is not supported. */ 226*444c4ba4SChristophe Lombard case H_NOT_FOUND: /* The operation supplied was not valid */ 227*444c4ba4SChristophe Lombard case H_NOT_AVAILABLE: /* The operation cannot be performed because the AFU has not been downloaded */ 228*444c4ba4SChristophe Lombard case H_SG_LIST: /* An block list entry was invalid */ 229*444c4ba4SChristophe Lombard return -EINVAL; 230*444c4ba4SChristophe Lombard case H_AUTHORITY: /* The partition does not have authority to perform this hcall */ 231*444c4ba4SChristophe Lombard case H_RESOURCE: /* The function has page table mappings for MMIO */ 232*444c4ba4SChristophe Lombard case H_HARDWARE: /* A hardware event prevented the attach operation */ 233*444c4ba4SChristophe Lombard case H_STATE: /* The coherent platform function is not in a valid state */ 234*444c4ba4SChristophe Lombard case H_BUSY: 235*444c4ba4SChristophe Lombard return -EBUSY; 236*444c4ba4SChristophe Lombard default: 237*444c4ba4SChristophe Lombard WARN(1, "Unexpected return code: %lx", rc); 238*444c4ba4SChristophe Lombard return -EINVAL; 239*444c4ba4SChristophe Lombard } 240*444c4ba4SChristophe Lombard } 241*444c4ba4SChristophe Lombard 242*444c4ba4SChristophe Lombard /** 243*444c4ba4SChristophe Lombard * cxl_h_reset_afu - Perform a reset to the coherent platform function. 244*444c4ba4SChristophe Lombard */ 245*444c4ba4SChristophe Lombard long cxl_h_reset_afu(u64 unit_address) 246*444c4ba4SChristophe Lombard { 247*444c4ba4SChristophe Lombard return cxl_h_control_function(unit_address, 248*444c4ba4SChristophe Lombard H_CONTROL_CA_FUNCTION_RESET, 249*444c4ba4SChristophe Lombard 0, 0, 0, 0, 250*444c4ba4SChristophe Lombard NULL); 251*444c4ba4SChristophe Lombard } 252*444c4ba4SChristophe Lombard 253*444c4ba4SChristophe Lombard /** 254*444c4ba4SChristophe Lombard * cxl_h_suspend_process - Suspend a process from being executed 255*444c4ba4SChristophe Lombard * Parameter1 = process-token as returned from H_ATTACH_CA_PROCESS when 256*444c4ba4SChristophe Lombard * process was attached. 257*444c4ba4SChristophe Lombard */ 258*444c4ba4SChristophe Lombard long cxl_h_suspend_process(u64 unit_address, u64 process_token) 259*444c4ba4SChristophe Lombard { 260*444c4ba4SChristophe Lombard return cxl_h_control_function(unit_address, 261*444c4ba4SChristophe Lombard H_CONTROL_CA_FUNCTION_SUSPEND_PROCESS, 262*444c4ba4SChristophe Lombard process_token, 0, 0, 0, 263*444c4ba4SChristophe Lombard NULL); 264*444c4ba4SChristophe Lombard } 265*444c4ba4SChristophe Lombard 266*444c4ba4SChristophe Lombard /** 267*444c4ba4SChristophe Lombard * cxl_h_resume_process - Resume a process to be executed 268*444c4ba4SChristophe Lombard * Parameter1 = process-token as returned from H_ATTACH_CA_PROCESS when 269*444c4ba4SChristophe Lombard * process was attached. 270*444c4ba4SChristophe Lombard */ 271*444c4ba4SChristophe Lombard long cxl_h_resume_process(u64 unit_address, u64 process_token) 272*444c4ba4SChristophe Lombard { 273*444c4ba4SChristophe Lombard return cxl_h_control_function(unit_address, 274*444c4ba4SChristophe Lombard H_CONTROL_CA_FUNCTION_RESUME_PROCESS, 275*444c4ba4SChristophe Lombard process_token, 0, 0, 0, 276*444c4ba4SChristophe Lombard NULL); 277*444c4ba4SChristophe Lombard } 278*444c4ba4SChristophe Lombard 279*444c4ba4SChristophe Lombard /** 280*444c4ba4SChristophe Lombard * cxl_h_read_error_state - Checks the error state of the coherent 281*444c4ba4SChristophe Lombard * platform function. 282*444c4ba4SChristophe Lombard * R4 contains the error state 283*444c4ba4SChristophe Lombard */ 284*444c4ba4SChristophe Lombard long cxl_h_read_error_state(u64 unit_address, u64 *state) 285*444c4ba4SChristophe Lombard { 286*444c4ba4SChristophe Lombard return cxl_h_control_function(unit_address, 287*444c4ba4SChristophe Lombard H_CONTROL_CA_FUNCTION_READ_ERR_STATE, 288*444c4ba4SChristophe Lombard 0, 0, 0, 0, 289*444c4ba4SChristophe Lombard state); 290*444c4ba4SChristophe Lombard } 291*444c4ba4SChristophe Lombard 292*444c4ba4SChristophe Lombard /** 293*444c4ba4SChristophe Lombard * cxl_h_get_afu_err - collect the AFU error buffer 294*444c4ba4SChristophe Lombard * Parameter1 = byte offset into error buffer to retrieve, valid values 295*444c4ba4SChristophe Lombard * are between 0 and (ibm,error-buffer-size - 1) 296*444c4ba4SChristophe Lombard * Parameter2 = 4K aligned real address of error buffer, to be filled in 297*444c4ba4SChristophe Lombard * Parameter3 = length of error buffer, valid values are 4K or less 298*444c4ba4SChristophe Lombard */ 299*444c4ba4SChristophe Lombard long cxl_h_get_afu_err(u64 unit_address, u64 offset, 300*444c4ba4SChristophe Lombard u64 buf_address, u64 len) 301*444c4ba4SChristophe Lombard { 302*444c4ba4SChristophe Lombard return cxl_h_control_function(unit_address, 303*444c4ba4SChristophe Lombard H_CONTROL_CA_FUNCTION_GET_AFU_ERR, 304*444c4ba4SChristophe Lombard offset, buf_address, len, 0, 305*444c4ba4SChristophe Lombard NULL); 306*444c4ba4SChristophe Lombard } 307*444c4ba4SChristophe Lombard 308*444c4ba4SChristophe Lombard /** 309*444c4ba4SChristophe Lombard * cxl_h_get_config - collect configuration record for the 310*444c4ba4SChristophe Lombard * coherent platform function 311*444c4ba4SChristophe Lombard * Parameter1 = # of configuration record to retrieve, valid values are 312*444c4ba4SChristophe Lombard * between 0 and (ibm,#config-records - 1) 313*444c4ba4SChristophe Lombard * Parameter2 = byte offset into configuration record to retrieve, 314*444c4ba4SChristophe Lombard * valid values are between 0 and (ibm,config-record-size - 1) 315*444c4ba4SChristophe Lombard * Parameter3 = 4K aligned real address of configuration record buffer, 316*444c4ba4SChristophe Lombard * to be filled in 317*444c4ba4SChristophe Lombard * Parameter4 = length of configuration buffer, valid values are 4K or less 318*444c4ba4SChristophe Lombard */ 319*444c4ba4SChristophe Lombard long cxl_h_get_config(u64 unit_address, u64 cr_num, u64 offset, 320*444c4ba4SChristophe Lombard u64 buf_address, u64 len) 321*444c4ba4SChristophe Lombard { 322*444c4ba4SChristophe Lombard return cxl_h_control_function(unit_address, 323*444c4ba4SChristophe Lombard H_CONTROL_CA_FUNCTION_GET_CONFIG, 324*444c4ba4SChristophe Lombard cr_num, offset, buf_address, len, 325*444c4ba4SChristophe Lombard NULL); 326*444c4ba4SChristophe Lombard } 327*444c4ba4SChristophe Lombard 328*444c4ba4SChristophe Lombard /** 329*444c4ba4SChristophe Lombard * cxl_h_terminate_process - Terminate the process before completion 330*444c4ba4SChristophe Lombard * Parameter1 = process-token as returned from H_ATTACH_CA_PROCESS when 331*444c4ba4SChristophe Lombard * process was attached. 332*444c4ba4SChristophe Lombard */ 333*444c4ba4SChristophe Lombard long cxl_h_terminate_process(u64 unit_address, u64 process_token) 334*444c4ba4SChristophe Lombard { 335*444c4ba4SChristophe Lombard return cxl_h_control_function(unit_address, 336*444c4ba4SChristophe Lombard H_CONTROL_CA_FUNCTION_TERMINATE_PROCESS, 337*444c4ba4SChristophe Lombard process_token, 0, 0, 0, 338*444c4ba4SChristophe Lombard NULL); 339*444c4ba4SChristophe Lombard } 340*444c4ba4SChristophe Lombard 341*444c4ba4SChristophe Lombard /** 342*444c4ba4SChristophe Lombard * cxl_h_collect_vpd - Collect VPD for the coherent platform function. 343*444c4ba4SChristophe Lombard * Parameter1 = # of VPD record to retrieve, valid values are between 0 344*444c4ba4SChristophe Lombard * and (ibm,#config-records - 1). 345*444c4ba4SChristophe Lombard * Parameter2 = 4K naturally aligned real buffer containing block 346*444c4ba4SChristophe Lombard * list entries 347*444c4ba4SChristophe Lombard * Parameter3 = number of block list entries in the block list, valid 348*444c4ba4SChristophe Lombard * values are between 0 and 256 349*444c4ba4SChristophe Lombard */ 350*444c4ba4SChristophe Lombard long cxl_h_collect_vpd(u64 unit_address, u64 record, u64 list_address, 351*444c4ba4SChristophe Lombard u64 num, u64 *out) 352*444c4ba4SChristophe Lombard { 353*444c4ba4SChristophe Lombard return cxl_h_control_function(unit_address, 354*444c4ba4SChristophe Lombard H_CONTROL_CA_FUNCTION_COLLECT_VPD, 355*444c4ba4SChristophe Lombard record, list_address, num, 0, 356*444c4ba4SChristophe Lombard out); 357*444c4ba4SChristophe Lombard } 358*444c4ba4SChristophe Lombard 359*444c4ba4SChristophe Lombard /** 360*444c4ba4SChristophe Lombard * cxl_h_get_fn_error_interrupt - Read the function-wide error data based on an interrupt 361*444c4ba4SChristophe Lombard */ 362*444c4ba4SChristophe Lombard long cxl_h_get_fn_error_interrupt(u64 unit_address, u64 *reg) 363*444c4ba4SChristophe Lombard { 364*444c4ba4SChristophe Lombard return cxl_h_control_function(unit_address, 365*444c4ba4SChristophe Lombard H_CONTROL_CA_FUNCTION_GET_FUNCTION_ERR_INT, 366*444c4ba4SChristophe Lombard 0, 0, 0, 0, reg); 367*444c4ba4SChristophe Lombard } 368*444c4ba4SChristophe Lombard 369*444c4ba4SChristophe Lombard /** 370*444c4ba4SChristophe Lombard * cxl_h_ack_fn_error_interrupt - Acknowledge function-wide error data 371*444c4ba4SChristophe Lombard * based on an interrupt 372*444c4ba4SChristophe Lombard * Parameter1 = value to write to the function-wide error interrupt register 373*444c4ba4SChristophe Lombard */ 374*444c4ba4SChristophe Lombard long cxl_h_ack_fn_error_interrupt(u64 unit_address, u64 value) 375*444c4ba4SChristophe Lombard { 376*444c4ba4SChristophe Lombard return cxl_h_control_function(unit_address, 377*444c4ba4SChristophe Lombard H_CONTROL_CA_FUNCTION_ACK_FUNCTION_ERR_INT, 378*444c4ba4SChristophe Lombard value, 0, 0, 0, 379*444c4ba4SChristophe Lombard NULL); 380*444c4ba4SChristophe Lombard } 381*444c4ba4SChristophe Lombard 382*444c4ba4SChristophe Lombard /** 383*444c4ba4SChristophe Lombard * cxl_h_get_error_log - Retrieve the Platform Log ID (PLID) of 384*444c4ba4SChristophe Lombard * an error log 385*444c4ba4SChristophe Lombard */ 386*444c4ba4SChristophe Lombard long cxl_h_get_error_log(u64 unit_address, u64 value) 387*444c4ba4SChristophe Lombard { 388*444c4ba4SChristophe Lombard return cxl_h_control_function(unit_address, 389*444c4ba4SChristophe Lombard H_CONTROL_CA_FUNCTION_GET_ERROR_LOG, 390*444c4ba4SChristophe Lombard 0, 0, 0, 0, 391*444c4ba4SChristophe Lombard NULL); 392*444c4ba4SChristophe Lombard } 393*444c4ba4SChristophe Lombard 394*444c4ba4SChristophe Lombard /** 395*444c4ba4SChristophe Lombard * cxl_h_collect_int_info - Collect interrupt info about a coherent 396*444c4ba4SChristophe Lombard * platform function after an interrupt occurred. 397*444c4ba4SChristophe Lombard */ 398*444c4ba4SChristophe Lombard long cxl_h_collect_int_info(u64 unit_address, u64 process_token, 399*444c4ba4SChristophe Lombard struct cxl_irq_info *info) 400*444c4ba4SChristophe Lombard { 401*444c4ba4SChristophe Lombard long rc; 402*444c4ba4SChristophe Lombard 403*444c4ba4SChristophe Lombard BUG_ON(sizeof(*info) != sizeof(unsigned long[PLPAR_HCALL9_BUFSIZE])); 404*444c4ba4SChristophe Lombard 405*444c4ba4SChristophe Lombard rc = plpar_hcall9(H_COLLECT_CA_INT_INFO, (unsigned long *) info, 406*444c4ba4SChristophe Lombard unit_address, process_token); 407*444c4ba4SChristophe Lombard _PRINT_MSG(rc, "cxl_h_collect_int_info(%#.16llx, 0x%llx): %li\n", 408*444c4ba4SChristophe Lombard unit_address, process_token, rc); 409*444c4ba4SChristophe Lombard 410*444c4ba4SChristophe Lombard switch (rc) { 411*444c4ba4SChristophe Lombard case H_SUCCESS: /* The interrupt info is returned in return registers. */ 412*444c4ba4SChristophe Lombard pr_devel("dsisr:%#llx, dar:%#llx, dsr:%#llx, pid:%u, tid:%u, afu_err:%#llx, errstat:%#llx\n", 413*444c4ba4SChristophe Lombard info->dsisr, info->dar, info->dsr, info->pid, 414*444c4ba4SChristophe Lombard info->tid, info->afu_err, info->errstat); 415*444c4ba4SChristophe Lombard return 0; 416*444c4ba4SChristophe Lombard case H_PARAMETER: /* An incorrect parameter was supplied. */ 417*444c4ba4SChristophe Lombard return -EINVAL; 418*444c4ba4SChristophe Lombard case H_AUTHORITY: /* The partition does not have authority to perform this hcall. */ 419*444c4ba4SChristophe Lombard case H_HARDWARE: /* A hardware event prevented the collection of the interrupt info.*/ 420*444c4ba4SChristophe Lombard case H_STATE: /* The coherent platform function is not in a valid state to collect interrupt info. */ 421*444c4ba4SChristophe Lombard return -EBUSY; 422*444c4ba4SChristophe Lombard default: 423*444c4ba4SChristophe Lombard WARN(1, "Unexpected return code: %lx", rc); 424*444c4ba4SChristophe Lombard return -EINVAL; 425*444c4ba4SChristophe Lombard } 426*444c4ba4SChristophe Lombard } 427*444c4ba4SChristophe Lombard 428*444c4ba4SChristophe Lombard /** 429*444c4ba4SChristophe Lombard * cxl_h_control_faults - Control the operation of a coherent platform 430*444c4ba4SChristophe Lombard * function after a fault occurs. 431*444c4ba4SChristophe Lombard * 432*444c4ba4SChristophe Lombard * Parameters 433*444c4ba4SChristophe Lombard * control-mask: value to control the faults 434*444c4ba4SChristophe Lombard * looks like PSL_TFC_An shifted >> 32 435*444c4ba4SChristophe Lombard * reset-mask: mask to control reset of function faults 436*444c4ba4SChristophe Lombard * Set reset_mask = 1 to reset PSL errors 437*444c4ba4SChristophe Lombard */ 438*444c4ba4SChristophe Lombard long cxl_h_control_faults(u64 unit_address, u64 process_token, 439*444c4ba4SChristophe Lombard u64 control_mask, u64 reset_mask) 440*444c4ba4SChristophe Lombard { 441*444c4ba4SChristophe Lombard unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; 442*444c4ba4SChristophe Lombard long rc; 443*444c4ba4SChristophe Lombard 444*444c4ba4SChristophe Lombard memset(retbuf, 0, sizeof(retbuf)); 445*444c4ba4SChristophe Lombard 446*444c4ba4SChristophe Lombard rc = plpar_hcall(H_CONTROL_CA_FAULTS, retbuf, unit_address, 447*444c4ba4SChristophe Lombard H_CONTROL_CA_FAULTS_RESPOND_PSL, process_token, 448*444c4ba4SChristophe Lombard control_mask, reset_mask); 449*444c4ba4SChristophe Lombard _PRINT_MSG(rc, "cxl_h_control_faults(%#.16llx, 0x%llx, %#llx, %#llx): %li (%#lx)\n", 450*444c4ba4SChristophe Lombard unit_address, process_token, control_mask, reset_mask, 451*444c4ba4SChristophe Lombard rc, retbuf[0]); 452*444c4ba4SChristophe Lombard 453*444c4ba4SChristophe Lombard switch (rc) { 454*444c4ba4SChristophe Lombard case H_SUCCESS: /* Faults were successfully controlled for the function. */ 455*444c4ba4SChristophe Lombard return 0; 456*444c4ba4SChristophe Lombard case H_PARAMETER: /* An incorrect parameter was supplied. */ 457*444c4ba4SChristophe Lombard return -EINVAL; 458*444c4ba4SChristophe Lombard case H_HARDWARE: /* A hardware event prevented the control of faults. */ 459*444c4ba4SChristophe Lombard case H_STATE: /* The function was in an invalid state. */ 460*444c4ba4SChristophe Lombard case H_AUTHORITY: /* The partition does not have authority to perform this hcall; the coherent platform facilities may need to be licensed. */ 461*444c4ba4SChristophe Lombard return -EBUSY; 462*444c4ba4SChristophe Lombard case H_FUNCTION: /* The function is not supported */ 463*444c4ba4SChristophe Lombard case H_NOT_FOUND: /* The operation supplied was not valid */ 464*444c4ba4SChristophe Lombard return -EINVAL; 465*444c4ba4SChristophe Lombard default: 466*444c4ba4SChristophe Lombard WARN(1, "Unexpected return code: %lx", rc); 467*444c4ba4SChristophe Lombard return -EINVAL; 468*444c4ba4SChristophe Lombard } 469*444c4ba4SChristophe Lombard } 470*444c4ba4SChristophe Lombard 471*444c4ba4SChristophe Lombard /** 472*444c4ba4SChristophe Lombard * cxl_h_control_facility - This H_CONTROL_CA_FACILITY hypervisor call 473*444c4ba4SChristophe Lombard * allows the partition to manipulate or query 474*444c4ba4SChristophe Lombard * certain coherent platform facility behaviors. 475*444c4ba4SChristophe Lombard */ 476*444c4ba4SChristophe Lombard static long cxl_h_control_facility(u64 unit_address, u64 op, 477*444c4ba4SChristophe Lombard u64 p1, u64 p2, u64 p3, u64 p4, u64 *out) 478*444c4ba4SChristophe Lombard { 479*444c4ba4SChristophe Lombard unsigned long retbuf[PLPAR_HCALL9_BUFSIZE]; 480*444c4ba4SChristophe Lombard long rc; 481*444c4ba4SChristophe Lombard 482*444c4ba4SChristophe Lombard CXL_H9_WAIT_UNTIL_DONE(rc, retbuf, H_CONTROL_CA_FACILITY, unit_address, op, p1, p2, p3, p4); 483*444c4ba4SChristophe Lombard _PRINT_MSG(rc, "cxl_h_control_facility(%#.16llx, %s(%#llx, %#llx, %#llx, %#llx, R4: %#lx)): %li\n", 484*444c4ba4SChristophe Lombard unit_address, OP_STR_CONTROL_ADAPTER(op), p1, p2, p3, p4, retbuf[0], rc); 485*444c4ba4SChristophe Lombard 486*444c4ba4SChristophe Lombard switch (rc) { 487*444c4ba4SChristophe Lombard case H_SUCCESS: /* The operation is completed for the coherent platform facility */ 488*444c4ba4SChristophe Lombard if (op == H_CONTROL_CA_FACILITY_COLLECT_VPD) 489*444c4ba4SChristophe Lombard *out = retbuf[0]; 490*444c4ba4SChristophe Lombard return 0; 491*444c4ba4SChristophe Lombard case H_PARAMETER: /* An incorrect parameter was supplied. */ 492*444c4ba4SChristophe Lombard case H_FUNCTION: /* The function is not supported. */ 493*444c4ba4SChristophe Lombard case H_NOT_FOUND: /* The operation supplied was not valid */ 494*444c4ba4SChristophe Lombard case H_NOT_AVAILABLE: /* The operation cannot be performed because the AFU has not been downloaded */ 495*444c4ba4SChristophe Lombard case H_SG_LIST: /* An block list entry was invalid */ 496*444c4ba4SChristophe Lombard return -EINVAL; 497*444c4ba4SChristophe Lombard case H_AUTHORITY: /* The partition does not have authority to perform this hcall */ 498*444c4ba4SChristophe Lombard case H_RESOURCE: /* The function has page table mappings for MMIO */ 499*444c4ba4SChristophe Lombard case H_HARDWARE: /* A hardware event prevented the attach operation */ 500*444c4ba4SChristophe Lombard case H_STATE: /* The coherent platform facility is not in a valid state */ 501*444c4ba4SChristophe Lombard case H_BUSY: 502*444c4ba4SChristophe Lombard return -EBUSY; 503*444c4ba4SChristophe Lombard default: 504*444c4ba4SChristophe Lombard WARN(1, "Unexpected return code: %lx", rc); 505*444c4ba4SChristophe Lombard return -EINVAL; 506*444c4ba4SChristophe Lombard } 507*444c4ba4SChristophe Lombard } 508*444c4ba4SChristophe Lombard 509*444c4ba4SChristophe Lombard /** 510*444c4ba4SChristophe Lombard * cxl_h_reset_adapter - Perform a reset to the coherent platform facility. 511*444c4ba4SChristophe Lombard */ 512*444c4ba4SChristophe Lombard long cxl_h_reset_adapter(u64 unit_address) 513*444c4ba4SChristophe Lombard { 514*444c4ba4SChristophe Lombard return cxl_h_control_facility(unit_address, 515*444c4ba4SChristophe Lombard H_CONTROL_CA_FACILITY_RESET, 516*444c4ba4SChristophe Lombard 0, 0, 0, 0, 517*444c4ba4SChristophe Lombard NULL); 518*444c4ba4SChristophe Lombard } 519*444c4ba4SChristophe Lombard 520*444c4ba4SChristophe Lombard /** 521*444c4ba4SChristophe Lombard * cxl_h_collect_vpd - Collect VPD for the coherent platform function. 522*444c4ba4SChristophe Lombard * Parameter1 = 4K naturally aligned real buffer containing block 523*444c4ba4SChristophe Lombard * list entries 524*444c4ba4SChristophe Lombard * Parameter2 = number of block list entries in the block list, valid 525*444c4ba4SChristophe Lombard * values are between 0 and 256 526*444c4ba4SChristophe Lombard */ 527*444c4ba4SChristophe Lombard long cxl_h_collect_vpd_adapter(u64 unit_address, u64 list_address, 528*444c4ba4SChristophe Lombard u64 num, u64 *out) 529*444c4ba4SChristophe Lombard { 530*444c4ba4SChristophe Lombard return cxl_h_control_facility(unit_address, 531*444c4ba4SChristophe Lombard H_CONTROL_CA_FACILITY_COLLECT_VPD, 532*444c4ba4SChristophe Lombard list_address, num, 0, 0, 533*444c4ba4SChristophe Lombard out); 534*444c4ba4SChristophe Lombard } 535*444c4ba4SChristophe Lombard 536*444c4ba4SChristophe Lombard /** 537*444c4ba4SChristophe Lombard * cxl_h_download_facility - This H_DOWNLOAD_CA_FACILITY 538*444c4ba4SChristophe Lombard * hypervisor call provide platform support for 539*444c4ba4SChristophe Lombard * downloading a base adapter image to the coherent 540*444c4ba4SChristophe Lombard * platform facility, and for validating the entire 541*444c4ba4SChristophe Lombard * image after the download. 542*444c4ba4SChristophe Lombard * Parameters 543*444c4ba4SChristophe Lombard * op: operation to perform to the coherent platform function 544*444c4ba4SChristophe Lombard * Download: operation = 1, the base image in the coherent platform 545*444c4ba4SChristophe Lombard * facility is first erased, and then 546*444c4ba4SChristophe Lombard * programmed using the image supplied 547*444c4ba4SChristophe Lombard * in the scatter/gather list. 548*444c4ba4SChristophe Lombard * Validate: operation = 2, the base image in the coherent platform 549*444c4ba4SChristophe Lombard * facility is compared with the image 550*444c4ba4SChristophe Lombard * supplied in the scatter/gather list. 551*444c4ba4SChristophe Lombard * list_address: 4K naturally aligned real buffer containing 552*444c4ba4SChristophe Lombard * scatter/gather list entries. 553*444c4ba4SChristophe Lombard * num: number of block list entries in the scatter/gather list. 554*444c4ba4SChristophe Lombard */ 555*444c4ba4SChristophe Lombard static long cxl_h_download_facility(u64 unit_address, u64 op, 556*444c4ba4SChristophe Lombard u64 list_address, u64 num, 557*444c4ba4SChristophe Lombard u64 *out) 558*444c4ba4SChristophe Lombard { 559*444c4ba4SChristophe Lombard unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; 560*444c4ba4SChristophe Lombard unsigned int delay, total_delay = 0; 561*444c4ba4SChristophe Lombard u64 token = 0; 562*444c4ba4SChristophe Lombard long rc; 563*444c4ba4SChristophe Lombard 564*444c4ba4SChristophe Lombard if (*out != 0) 565*444c4ba4SChristophe Lombard token = *out; 566*444c4ba4SChristophe Lombard 567*444c4ba4SChristophe Lombard memset(retbuf, 0, sizeof(retbuf)); 568*444c4ba4SChristophe Lombard while (1) { 569*444c4ba4SChristophe Lombard rc = plpar_hcall(H_DOWNLOAD_CA_FACILITY, retbuf, 570*444c4ba4SChristophe Lombard unit_address, op, list_address, num, 571*444c4ba4SChristophe Lombard token); 572*444c4ba4SChristophe Lombard token = retbuf[0]; 573*444c4ba4SChristophe Lombard if (rc != H_BUSY && !H_IS_LONG_BUSY(rc)) 574*444c4ba4SChristophe Lombard break; 575*444c4ba4SChristophe Lombard 576*444c4ba4SChristophe Lombard if (rc != H_BUSY) { 577*444c4ba4SChristophe Lombard delay = get_longbusy_msecs(rc); 578*444c4ba4SChristophe Lombard total_delay += delay; 579*444c4ba4SChristophe Lombard if (total_delay > CXL_HCALL_TIMEOUT_DOWNLOAD) { 580*444c4ba4SChristophe Lombard WARN(1, "Warning: Giving up waiting for CXL hcall " 581*444c4ba4SChristophe Lombard "%#x after %u msec\n", 582*444c4ba4SChristophe Lombard H_DOWNLOAD_CA_FACILITY, total_delay); 583*444c4ba4SChristophe Lombard rc = H_BUSY; 584*444c4ba4SChristophe Lombard break; 585*444c4ba4SChristophe Lombard } 586*444c4ba4SChristophe Lombard msleep(delay); 587*444c4ba4SChristophe Lombard } 588*444c4ba4SChristophe Lombard } 589*444c4ba4SChristophe Lombard _PRINT_MSG(rc, "cxl_h_download_facility(%#.16llx, %s(%#llx, %#llx), %#lx): %li\n", 590*444c4ba4SChristophe Lombard unit_address, OP_STR_DOWNLOAD_ADAPTER(op), list_address, num, retbuf[0], rc); 591*444c4ba4SChristophe Lombard 592*444c4ba4SChristophe Lombard switch (rc) { 593*444c4ba4SChristophe Lombard case H_SUCCESS: /* The operation is completed for the coherent platform facility */ 594*444c4ba4SChristophe Lombard return 0; 595*444c4ba4SChristophe Lombard case H_PARAMETER: /* An incorrect parameter was supplied */ 596*444c4ba4SChristophe Lombard case H_FUNCTION: /* The function is not supported. */ 597*444c4ba4SChristophe Lombard case H_SG_LIST: /* An block list entry was invalid */ 598*444c4ba4SChristophe Lombard case H_BAD_DATA: /* Image verification failed */ 599*444c4ba4SChristophe Lombard return -EINVAL; 600*444c4ba4SChristophe Lombard case H_AUTHORITY: /* The partition does not have authority to perform this hcall */ 601*444c4ba4SChristophe Lombard case H_RESOURCE: /* The function has page table mappings for MMIO */ 602*444c4ba4SChristophe Lombard case H_HARDWARE: /* A hardware event prevented the attach operation */ 603*444c4ba4SChristophe Lombard case H_STATE: /* The coherent platform facility is not in a valid state */ 604*444c4ba4SChristophe Lombard case H_BUSY: 605*444c4ba4SChristophe Lombard return -EBUSY; 606*444c4ba4SChristophe Lombard case H_CONTINUE: 607*444c4ba4SChristophe Lombard *out = retbuf[0]; 608*444c4ba4SChristophe Lombard return 1; /* More data is needed for the complete image */ 609*444c4ba4SChristophe Lombard default: 610*444c4ba4SChristophe Lombard WARN(1, "Unexpected return code: %lx", rc); 611*444c4ba4SChristophe Lombard return -EINVAL; 612*444c4ba4SChristophe Lombard } 613*444c4ba4SChristophe Lombard } 614*444c4ba4SChristophe Lombard 615*444c4ba4SChristophe Lombard /** 616*444c4ba4SChristophe Lombard * cxl_h_download_adapter_image - Download the base image to the coherent 617*444c4ba4SChristophe Lombard * platform facility. 618*444c4ba4SChristophe Lombard */ 619*444c4ba4SChristophe Lombard long cxl_h_download_adapter_image(u64 unit_address, 620*444c4ba4SChristophe Lombard u64 list_address, u64 num, 621*444c4ba4SChristophe Lombard u64 *out) 622*444c4ba4SChristophe Lombard { 623*444c4ba4SChristophe Lombard return cxl_h_download_facility(unit_address, 624*444c4ba4SChristophe Lombard H_DOWNLOAD_CA_FACILITY_DOWNLOAD, 625*444c4ba4SChristophe Lombard list_address, num, out); 626*444c4ba4SChristophe Lombard } 627*444c4ba4SChristophe Lombard 628*444c4ba4SChristophe Lombard /** 629*444c4ba4SChristophe Lombard * cxl_h_validate_adapter_image - Validate the base image in the coherent 630*444c4ba4SChristophe Lombard * platform facility. 631*444c4ba4SChristophe Lombard */ 632*444c4ba4SChristophe Lombard long cxl_h_validate_adapter_image(u64 unit_address, 633*444c4ba4SChristophe Lombard u64 list_address, u64 num, 634*444c4ba4SChristophe Lombard u64 *out) 635*444c4ba4SChristophe Lombard { 636*444c4ba4SChristophe Lombard return cxl_h_download_facility(unit_address, 637*444c4ba4SChristophe Lombard H_DOWNLOAD_CA_FACILITY_VALIDATE, 638*444c4ba4SChristophe Lombard list_address, num, out); 639*444c4ba4SChristophe Lombard } 640