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