1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright 2015 IBM Corp.
7 #include <linux/compiler.h>
8 #include <linux/types.h>
9 #include <linux/delay.h>
10 #include <asm/byteorder.h>
14 #define CXL_HCALL_TIMEOUT 60000
15 #define CXL_HCALL_TIMEOUT_DOWNLOAD 120000
17 #define H_ATTACH_CA_PROCESS 0x344
18 #define H_CONTROL_CA_FUNCTION 0x348
19 #define H_DETACH_CA_PROCESS 0x34C
20 #define H_COLLECT_CA_INT_INFO 0x350
21 #define H_CONTROL_CA_FAULTS 0x354
22 #define H_DOWNLOAD_CA_FUNCTION 0x35C
23 #define H_DOWNLOAD_CA_FACILITY 0x364
24 #define H_CONTROL_CA_FACILITY 0x368
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 */
39 #define H_CONTROL_CA_FAULTS_RESPOND_PSL 1
40 #define H_CONTROL_CA_FAULTS_RESPOND_AFU 2
42 #define H_CONTROL_CA_FACILITY_RESET 1 /* perform a reset */
43 #define H_CONTROL_CA_FACILITY_COLLECT_VPD 2 /* collect VPD */
45 #define H_DOWNLOAD_CA_FACILITY_DOWNLOAD 1 /* download adapter image */
46 #define H_DOWNLOAD_CA_FACILITY_VALIDATE 2 /* validate adapter image */
49 #define _CXL_LOOP_HCALL(call, rc, retbuf, fn, ...) \
51 unsigned int delay, total_delay = 0; \
54 memset(retbuf, 0, sizeof(retbuf)); \
56 rc = call(fn, retbuf, __VA_ARGS__, token); \
58 if (rc != H_BUSY && !H_IS_LONG_BUSY(rc)) \
64 delay = get_longbusy_msecs(rc); \
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); \
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__)
79 #define _PRINT_MSG(rc, format, ...) \
81 if ((rc != H_SUCCESS) && (rc != H_CONTINUE)) \
82 pr_err(format, __VA_ARGS__); \
84 pr_devel(format, __VA_ARGS__); \
88 static char *afu_op_names[] = {
89 "UNKNOWN_OP", /* 0 undefined */
91 "SUSPEND_PROCESS", /* 2 */
92 "RESUME_PROCESS", /* 3 */
93 "READ_ERR_STATE", /* 4 */
94 "GET_AFU_ERR", /* 5 */
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 */
105 static char *control_adapter_op_names
[] = {
106 "UNKNOWN_OP", /* 0 undefined */
108 "COLLECT_VPD", /* 2 */
111 static char *download_op_names
[] = {
112 "UNKNOWN_OP", /* 0 undefined */
117 static char *op_str(unsigned int op
, char *name_array
[], int array_len
)
121 return name_array
[op
];
124 #define OP_STR(op, name_array) op_str(op, name_array, ARRAY_SIZE(name_array))
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)
131 long cxl_h_attach_process(u64 unit_address
,
132 struct cxl_process_element_hcall
*element
,
133 u64
*process_token
, u64
*mmio_addr
, u64
*mmio_size
)
135 unsigned long retbuf
[PLPAR_HCALL_BUFSIZE
];
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
);
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
));
148 case H_SUCCESS
: /* The process info is attached to the coherent platform function */
149 *process_token
= retbuf
[0];
151 *mmio_addr
= retbuf
[1];
153 *mmio_size
= retbuf
[2];
155 case H_PARAMETER
: /* An incorrect parameter was supplied. */
156 case H_FUNCTION
: /* The function is not supported. */
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 */
165 WARN(1, "Unexpected return code: %lx", rc
);
171 * cxl_h_detach_process - Detach a process element from a coherent
174 long cxl_h_detach_process(u64 unit_address
, u64 process_token
)
176 unsigned long retbuf
[PLPAR_HCALL_BUFSIZE
];
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
);
184 case H_SUCCESS
: /* The process was detached from the coherent platform function */
186 case H_PARAMETER
: /* An incorrect parameter was supplied. */
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 */
195 WARN(1, "Unexpected return code: %lx", rc
);
201 * cxl_h_control_function - This H_CONTROL_CA_FUNCTION hypervisor call allows
202 * the partition to manipulate or query
203 * certain coherent platform function behaviors.
205 static long cxl_h_control_function(u64 unit_address
, u64 op
,
206 u64 p1
, u64 p2
, u64 p3
, u64 p4
, u64
*out
)
208 unsigned long retbuf
[PLPAR_HCALL9_BUFSIZE
];
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
);
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
))
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 */
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 */
236 WARN(1, "Unexpected return code: %lx", rc
);
242 * cxl_h_reset_afu - Perform a reset to the coherent platform function.
244 long cxl_h_reset_afu(u64 unit_address
)
246 return cxl_h_control_function(unit_address
,
247 H_CONTROL_CA_FUNCTION_RESET
,
253 * cxl_h_suspend_process - Suspend a process from being executed
254 * Parameter1 = process-token as returned from H_ATTACH_CA_PROCESS when
255 * process was attached.
257 long cxl_h_suspend_process(u64 unit_address
, u64 process_token
)
259 return cxl_h_control_function(unit_address
,
260 H_CONTROL_CA_FUNCTION_SUSPEND_PROCESS
,
261 process_token
, 0, 0, 0,
266 * cxl_h_resume_process - Resume a process to be executed
267 * Parameter1 = process-token as returned from H_ATTACH_CA_PROCESS when
268 * process was attached.
270 long cxl_h_resume_process(u64 unit_address
, u64 process_token
)
272 return cxl_h_control_function(unit_address
,
273 H_CONTROL_CA_FUNCTION_RESUME_PROCESS
,
274 process_token
, 0, 0, 0,
279 * cxl_h_read_error_state - Checks the error state of the coherent
281 * R4 contains the error state
283 long cxl_h_read_error_state(u64 unit_address
, u64
*state
)
285 return cxl_h_control_function(unit_address
,
286 H_CONTROL_CA_FUNCTION_READ_ERR_STATE
,
292 * cxl_h_get_afu_err - collect the AFU error buffer
293 * Parameter1 = byte offset into error buffer to retrieve, valid values
294 * are between 0 and (ibm,error-buffer-size - 1)
295 * Parameter2 = 4K aligned real address of error buffer, to be filled in
296 * Parameter3 = length of error buffer, valid values are 4K or less
298 long cxl_h_get_afu_err(u64 unit_address
, u64 offset
,
299 u64 buf_address
, u64 len
)
301 return cxl_h_control_function(unit_address
,
302 H_CONTROL_CA_FUNCTION_GET_AFU_ERR
,
303 offset
, buf_address
, len
, 0,
308 * cxl_h_get_config - collect configuration record for the
309 * coherent platform function
310 * Parameter1 = # of configuration record to retrieve, valid values are
311 * 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,
316 * Parameter4 = length of configuration buffer, valid values are 4K or less
318 long cxl_h_get_config(u64 unit_address
, u64 cr_num
, u64 offset
,
319 u64 buf_address
, u64 len
)
321 return cxl_h_control_function(unit_address
,
322 H_CONTROL_CA_FUNCTION_GET_CONFIG
,
323 cr_num
, offset
, buf_address
, len
,
328 * cxl_h_terminate_process - Terminate the process before completion
329 * Parameter1 = process-token as returned from H_ATTACH_CA_PROCESS when
330 * process was attached.
332 long cxl_h_terminate_process(u64 unit_address
, u64 process_token
)
334 return cxl_h_control_function(unit_address
,
335 H_CONTROL_CA_FUNCTION_TERMINATE_PROCESS
,
336 process_token
, 0, 0, 0,
341 * cxl_h_collect_vpd - Collect VPD for the coherent platform function.
342 * Parameter1 = # of VPD record to retrieve, valid values are between 0
343 * and (ibm,#config-records - 1).
344 * Parameter2 = 4K naturally aligned real buffer containing block
346 * Parameter3 = number of block list entries in the block list, valid
347 * values are between 0 and 256
349 long cxl_h_collect_vpd(u64 unit_address
, u64 record
, u64 list_address
,
352 return cxl_h_control_function(unit_address
,
353 H_CONTROL_CA_FUNCTION_COLLECT_VPD
,
354 record
, list_address
, num
, 0,
359 * cxl_h_get_fn_error_interrupt - Read the function-wide error data based on an interrupt
361 long cxl_h_get_fn_error_interrupt(u64 unit_address
, u64
*reg
)
363 return cxl_h_control_function(unit_address
,
364 H_CONTROL_CA_FUNCTION_GET_FUNCTION_ERR_INT
,
369 * cxl_h_ack_fn_error_interrupt - Acknowledge function-wide error data
370 * based on an interrupt
371 * Parameter1 = value to write to the function-wide error interrupt register
373 long cxl_h_ack_fn_error_interrupt(u64 unit_address
, u64 value
)
375 return cxl_h_control_function(unit_address
,
376 H_CONTROL_CA_FUNCTION_ACK_FUNCTION_ERR_INT
,
382 * cxl_h_get_error_log - Retrieve the Platform Log ID (PLID) of
385 long cxl_h_get_error_log(u64 unit_address
, u64 value
)
387 return cxl_h_control_function(unit_address
,
388 H_CONTROL_CA_FUNCTION_GET_ERROR_LOG
,
394 * cxl_h_collect_int_info - Collect interrupt info about a coherent
395 * platform function after an interrupt occurred.
397 long cxl_h_collect_int_info(u64 unit_address
, u64 process_token
,
398 struct cxl_irq_info
*info
)
402 BUG_ON(sizeof(*info
) != sizeof(unsigned long[PLPAR_HCALL9_BUFSIZE
]));
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
);
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
);
416 case H_PARAMETER
: /* An incorrect parameter was supplied. */
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. */
423 WARN(1, "Unexpected return code: %lx", rc
);
429 * cxl_h_control_faults - Control the operation of a coherent platform
430 * function after a fault occurs.
433 * control-mask: value to control the faults
434 * looks like PSL_TFC_An shifted >> 32
435 * reset-mask: mask to control reset of function faults
436 * Set reset_mask = 1 to reset PSL errors
438 long cxl_h_control_faults(u64 unit_address
, u64 process_token
,
439 u64 control_mask
, u64 reset_mask
)
441 unsigned long retbuf
[PLPAR_HCALL_BUFSIZE
];
444 memset(retbuf
, 0, sizeof(retbuf
));
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
,
452 trace_cxl_hcall_control_faults(unit_address
, process_token
,
453 control_mask
, reset_mask
, retbuf
[0], rc
);
456 case H_SUCCESS
: /* Faults were successfully controlled for the function. */
458 case H_PARAMETER
: /* An incorrect parameter was supplied. */
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. */
464 case H_FUNCTION
: /* The function is not supported */
465 case H_NOT_FOUND
: /* The operation supplied was not valid */
468 WARN(1, "Unexpected return code: %lx", rc
);
474 * cxl_h_control_facility - This H_CONTROL_CA_FACILITY hypervisor call
475 * allows the partition to manipulate or query
476 * certain coherent platform facility behaviors.
478 static long cxl_h_control_facility(u64 unit_address
, u64 op
,
479 u64 p1
, u64 p2
, u64 p3
, u64 p4
, u64
*out
)
481 unsigned long retbuf
[PLPAR_HCALL9_BUFSIZE
];
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
);
490 case H_SUCCESS
: /* The operation is completed for the coherent platform facility */
491 if (op
== H_CONTROL_CA_FACILITY_COLLECT_VPD
)
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 */
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 */
507 WARN(1, "Unexpected return code: %lx", rc
);
513 * cxl_h_reset_adapter - Perform a reset to the coherent platform facility.
515 long cxl_h_reset_adapter(u64 unit_address
)
517 return cxl_h_control_facility(unit_address
,
518 H_CONTROL_CA_FACILITY_RESET
,
524 * cxl_h_collect_vpd - Collect VPD for the coherent platform function.
525 * Parameter1 = 4K naturally aligned real buffer containing block
527 * Parameter2 = number of block list entries in the block list, valid
528 * values are between 0 and 256
530 long cxl_h_collect_vpd_adapter(u64 unit_address
, u64 list_address
,
533 return cxl_h_control_facility(unit_address
,
534 H_CONTROL_CA_FACILITY_COLLECT_VPD
,
535 list_address
, num
, 0, 0,
540 * cxl_h_download_facility - This H_DOWNLOAD_CA_FACILITY
541 * hypervisor call provide platform support for
542 * downloading a base adapter image to the coherent
543 * platform facility, and for validating the entire
544 * image after the download.
546 * op: operation to perform to the coherent platform function
547 * Download: operation = 1, the base image in the coherent platform
548 * facility is first erased, and then
549 * programmed using the image supplied
550 * in the scatter/gather list.
551 * Validate: operation = 2, the base image in the coherent platform
552 * facility is compared with the image
553 * supplied in the scatter/gather list.
554 * list_address: 4K naturally aligned real buffer containing
555 * scatter/gather list entries.
556 * num: number of block list entries in the scatter/gather list.
558 static long cxl_h_download_facility(u64 unit_address
, u64 op
,
559 u64 list_address
, u64 num
,
562 unsigned long retbuf
[PLPAR_HCALL_BUFSIZE
];
563 unsigned int delay
, total_delay
= 0;
570 memset(retbuf
, 0, sizeof(retbuf
));
572 rc
= plpar_hcall(H_DOWNLOAD_CA_FACILITY
, retbuf
,
573 unit_address
, op
, list_address
, num
,
576 if (rc
!= H_BUSY
&& !H_IS_LONG_BUSY(rc
))
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
);
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
);
597 case H_SUCCESS
: /* The operation is completed for the coherent platform facility */
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 */
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 */
612 return 1; /* More data is needed for the complete image */
614 WARN(1, "Unexpected return code: %lx", rc
);
620 * cxl_h_download_adapter_image - Download the base image to the coherent
623 long cxl_h_download_adapter_image(u64 unit_address
,
624 u64 list_address
, u64 num
,
627 return cxl_h_download_facility(unit_address
,
628 H_DOWNLOAD_CA_FACILITY_DOWNLOAD
,
629 list_address
, num
, out
);
633 * cxl_h_validate_adapter_image - Validate the base image in the coherent
636 long cxl_h_validate_adapter_image(u64 unit_address
,
637 u64 list_address
, u64 num
,
640 return cxl_h_download_facility(unit_address
,
641 H_DOWNLOAD_CA_FACILITY_VALIDATE
,
642 list_address
, num
, out
);